/**
* @copyright 2015 Tridium, Inc. All Rights Reserved.
* @author Gareth Johnson
*/
/**
* Defines {@link baja.TimeZone}.
* @module baja/obj/TimeZone
*/
define([ 'bajaScript/sys',
'bajaScript/baja/obj/RelTime',
'bajaScript/baja/obj/Simple',
'bajaScript/baja/obj/objUtil',
'bajaScript/baja/obj/dateTimeUtil' ], function (
baja,
RelTime,
Simple,
objUtil,
dateTimeUtil) {
'use strict';
var cacheDecode = objUtil.cacheDecode,
cacheEncode = objUtil.cacheEncode,
isDstActive = dateTimeUtil.isDstActive;
function hourAndMinute(relTime) {
var hour = relTime.getHoursPart(),
minute = relTime.getMinutesPart();
return (hour >= 0 ? '+' : '') + hour + (minute > 0 ? ':' + minute : '');
}
/**
* Represents a `baja:TimeZone` in BajaScript.
*
* @class
* @alias baja.TimeZone
* @extends baja.Simple
*/
var TimeZone = function TimeZone() {
Simple.apply(this, arguments);
};
TimeZone.prototype = Object.create(Simple.prototype);
TimeZone.prototype.constructor = TimeZone;
/**
* Make a new `baja:TimeZone` instance.
*
* There is not usually a reason, nor a good way, to create time zones
* directly in BajaScript: you will most likely want to use the time zones
* returned from the station, using the `TimeZoneDatabase`.
*
* @param {string} id
* @param {number} [utcOffset=0] UTC offset in milliseconds
* @param {number} [dstOffset=0] DST offset in milliseconds
* @param {string} [startRule=null] daylight savings start rule, encoded as a
* string. This can be specific to the JVM. `null` is an acceptable value.
* @param {string} [endRule=null] daylight savings end rule - same caveats as
* startRule
* @param {Object} [params]
* @param {string} [params.displayName] long display name, when DST is
* inactive
* @param {string} [params.dstDisplayName] long display name, when DST is
* active
* @param {string} [params.shortDisplayName] short display name, when DST is
* inactive
* @param {string} [params.shortDstDisplayName] short display name, when DST
* is active
*/
TimeZone.make = function (id, utcOffset, dstOffset, startRule, endRule, params) {
if (typeof id !== 'string') {
throw new Error('time zone id required');
}
params = params || {};
var z = new TimeZone();
z.$id = id;
z.$utcOffset = utcOffset || 0;
z.$dstOffset = dstOffset || 0;
z.$startRule = startRule || null;
z.$endRule = endRule || null;
z.$dn = params.displayName;
z.$ddn = params.dstDisplayName;
z.$sdn = params.shortDisplayName;
z.$dsdn = params.shortDstDisplayName;
return z;
};
/**
* Return true if daylight savings time is active for the given date.
* Note: If no timezone is provided, this will not use timezone rules, rather
* a simplistic method of comparing offsets in January and June for the local
* browser.
*
* If a timezone is provided, daylights savings will be determined at the
* given date in that timezone.
*
* Please note: javascript dates will always have a local timezone
* offset. The underlying milliseconds from epoch value will be used as the
* source of truth for the time. This point in time will then be used to
* determine whether daylight savings is active at that underlying millisecond
* value in the given timezone (if provided).
*
* @param {Date} [d] the date to check. If omitted, the current date will be
* checked.
* @param {baja.TimeZone} [timeZone] the timezone to use.
* @returns {boolean} true if daylight savings time is active
*/
TimeZone.isDstActive = function (d, timeZone) {
return isDstActive(d, timeZone);
};
/**
* @see .make
*/
TimeZone.prototype.make = function () {
return TimeZone.make.apply(TimeZone, arguments);
};
/**
* Return the string encoding of the daylight start rule. This can be JVM
* specific and usually not of use in a BajaScript application.
*
* @private
* @returns {string|null}
*/
TimeZone.prototype.$getDaylightStartRule = function () {
return this.$startRule;
};
/**
* Return the string encoding of the daylight end rule. This can be JVM
* specific and usually not of use in a BajaScript application.
*
* @private
* @returns {string|null}
*/
TimeZone.prototype.$getDaylightEndRule = function () {
return this.$endRule;
};
/**
* Decode a `baja:TimeZone` instance from the given string.
*
* @function
* @param {string} str
* @returns {baja.TimeZone}
*/
TimeZone.prototype.decodeFromString = cacheDecode(function (str) {
var fields = str.split(';'),
id = fields[0];
if (fields.length === 1) {
return TimeZone.make(id);
}
var utc = parseInt(fields[1], 10),
dst = parseInt(fields[2], 10),
startRule = fields[3],
endRule = fields[4];
if (isNaN(utc) || isNaN(dst)) {
throw new Error('invalid time zone string ' + str);
}
return TimeZone.make(id, utc, dst, startRule, endRule);
});
/**
* Encode this `baja:TimeZone` instance to a string.
*
* @function
* @returns {string}
*/
TimeZone.prototype.encodeToString = cacheEncode(function () {
return [
this.getId(),
this.getUtcOffset(),
this.getDaylightAdjustment(),
String(this.$getDaylightStartRule()),
String(this.$getDaylightEndRule())
].join(';');
});
TimeZone.prototype.getDataTypeSymbol = function () {
return 'z';
};
/**
* Return the DST adjustment, in milliseconds.
*
* @returns {number}
*/
TimeZone.prototype.getDaylightAdjustment = function () {
return this.$dstOffset;
};
/**
* Get the display name for this time zone.
*
* @param {boolean} [dst] whether DST should be considered active when getting
* the display name. If omitted, the method will consider whether DST is
* active at the present moment.
* @returns {string}
*/
TimeZone.prototype.getDisplayName = function (dst) {
if (arguments.length === 0) {
dst = TimeZone.isDstActive();
}
return dst ? this.$ddn : this.$dn;
};
/**
* Get the time zone ID.
*
* @returns {string}
*/
TimeZone.prototype.getId = function () {
return this.$id;
};
/**
* Get the short display name for this time zone.
*
* @param {boolean} [dst] whether DST should be considered active when getting
* the short display name. If omitted, the method will consider whether DST is
* active at the present moment.
* @returns {string}
*/
TimeZone.prototype.getShortDisplayName = function (dst) {
if (arguments.length === 0) {
dst = TimeZone.isDstActive();
}
return dst ? this.$dsdn : this.$sdn;
};
/**
* Get the UTC offset in milliseconds.
*
* @returns {number}
*/
TimeZone.prototype.getUtcOffset = function () {
return this.$utcOffset;
};
TimeZone.prototype.toString = function () {
var utcOffset = this.getUtcOffset(),
utcRelTime = RelTime.make(utcOffset),
daylight = this.getDaylightAdjustment(),
str = this.getId() + ' (' + hourAndMinute(utcRelTime);
if (daylight !== 0) {
str += '/' + hourAndMinute(RelTime.make(utcOffset + daylight));
}
return str + ')';
};
/** @type baja.TimeZone */
TimeZone.UTC = TimeZone.make("UTC");
/** @type baja.TimeZone */
TimeZone.GMT = TimeZone.make("GMT");
/** @type baja.TimeZone */
TimeZone.NULL = TimeZone.make("NULL");
/** @type baja.TimeZone */
TimeZone.DEFAULT = TimeZone.UTC;
return TimeZone;
});