From a39ae3101165c25e94a5276b65ebe5cfc7f1b6ba Mon Sep 17 00:00:00 2001 From: Aleksei Gusev Date: Fri, 3 May 2013 14:50:24 +0300 Subject: [PATCH] Update for new detect_timezone.js --- detect_timezone.js | 316 --------------------------------- example.htm | 8 +- jquery.detect_timezone.js | 18 +- jstz.js | 358 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 371 insertions(+), 329 deletions(-) delete mode 100644 detect_timezone.js create mode 100644 jstz.js diff --git a/detect_timezone.js b/detect_timezone.js deleted file mode 100644 index d883a6f..0000000 --- a/detect_timezone.js +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Original script by Josh Fraser (http://www.onlineaspect.com) - * Continued and maintained by Jon Nylander at https://bitbucket.org/pellepim/jstimezonedetect - * - * Provided under the Do Whatever You Want With This Code License. - */ -/** - * Namespace to hold all the code for timezone detection. - */ -var jstz = {}; -jstz.HEMISPHERE_SOUTH = 'SOUTH'; -jstz.HEMISPHERE_NORTH = 'NORTH'; -jstz.HEMISPHERE_UNKNOWN = 'N/A'; -jstz.olson = {}; - -/** - * A simple object containing information of utc_offset, which olson timezone key to use, - * and if the timezone cares about daylight savings or not. - * - * @constructor - * @param {string} offset - for example '-11:00' - * @param {string} olson_tz - the olson Identifier, such as "America/Denver" - * @param {boolean} uses_dst - flag for whether the time zone somehow cares about daylight savings. - */ -jstz.TimeZone = function (offset, olson_tz, uses_dst) { - this.utc_offset = offset; - this.olson_tz = olson_tz; - this.uses_dst = uses_dst; -}; - -/** - * Prints out the result. - * But before it does that, it calls this.ambiguity_check. - */ -jstz.TimeZone.prototype.display = function () { - this.ambiguity_check(); - var response_text = 'UTC-offset: ' + this.utc_offset + '
'; - response_text += 'Zoneinfo key: ' + this.olson_tz + '
'; - response_text += 'Zone uses DST: ' + (this.uses_dst ? 'yes' : 'no') + '
'; - - return response_text; -}; - -/** - * Checks if a timezone has possible ambiguities. I.e timezones that are similar. - * - * If the preliminary scan determines that we're in America/Denver. We double check - * here that we're really there and not in America/Mazatlan. - * - * This is done by checking known dates for when daylight savings start for different - * timezones. - */ -jstz.TimeZone.prototype.ambiguity_check = function () { - var ambiguity_list, length, i, tz; - ambiguity_list = jstz.olson.ambiguity_list[this.olson_tz]; - - if (typeof (ambiguity_list) === 'undefined') { - return; - } - - length = ambiguity_list.length; - i = 0; - - for (; i < length; i += 1) { - tz = ambiguity_list[i]; - - if (jstz.date_is_dst(jstz.olson.dst_start_dates[tz])) { - this.olson_tz = tz; - return; - } - } -}; - -/** - * Checks whether a given date is in daylight savings time. - * - * If the date supplied is after june, we assume that we're checking - * for southern hemisphere DST. - * - * @param {Date} date - * @returns {boolean} - */ -jstz.date_is_dst = function (date) { - var date_offset, base_offset; - base_offset = ((date.getMonth() > 5 ? jstz.get_june_offset() - : jstz.get_january_offset())); - - date_offset = jstz.get_date_offset(date); - - return (base_offset - date_offset) !== 0; -}; - -/** - * Gets the offset in minutes from UTC for a certain date. - * - * @param date - * @returns {number} - */ -jstz.get_date_offset = function (date) { - return -date.getTimezoneOffset(); -}; - -/** - * This function does some basic calculations to create information about - * the user's timezone. - * - * Returns a primitive object on the format - * {'utc_offset' : -9, 'dst': 1, hemisphere' : 'north'} - * where dst is 1 if the region uses daylight savings. - * - * @returns {Object} - */ -jstz.get_timezone_info = function () { - var january_offset, june_offset, diff; - january_offset = jstz.get_january_offset(); - june_offset = jstz.get_june_offset(); - diff = january_offset - june_offset; - - if (diff < 0) { - return { - 'utc_offset' : january_offset, - 'dst': 1, - 'hemisphere' : jstz.HEMISPHERE_NORTH - }; - } else if (diff > 0) { - return { - 'utc_offset' : june_offset, - 'dst' : 1, - 'hemisphere' : jstz.HEMISPHERE_SOUTH - }; - } - - return { - 'utc_offset' : january_offset, - 'dst': 0, - 'hemisphere' : jstz.HEMISPHERE_UNKNOWN - }; -}; - -jstz.get_january_offset = function () { - return jstz.get_date_offset(new Date(2011, 0, 1, 0, 0, 0, 0)); -}; - -jstz.get_june_offset = function () { - return jstz.get_date_offset(new Date(2011, 5, 1, 0, 0, 0, 0)); -}; - -/** - * Uses get_timezone_info() to formulate a key to use in the olson.timezones dictionary. - * - * Returns a primitive object on the format: - * {'timezone': TimeZone, 'key' : 'the key used to find the TimeZone object'} - * - * @returns Object - */ -jstz.determine_timezone = function () { - var timezone_key_info, hemisphere_suffix, tz_key; - timezone_key_info = jstz.get_timezone_info(); - hemisphere_suffix = ''; - - if (timezone_key_info.hemisphere === jstz.HEMISPHERE_SOUTH) { - hemisphere_suffix = ',s'; - } - - tz_key = timezone_key_info.utc_offset + ',' + timezone_key_info.dst + hemisphere_suffix; - - return {'timezone' : jstz.olson.timezones[tz_key], 'key' : tz_key}; -}; - -/** - * The keys in this dictionary are comma separated as such: - * - * First the offset compared to UTC time in minutes. - * - * Then a flag which is 0 if the timezone does not take daylight savings into account and 1 if it does. - * - * Thirdly an optional 's' signifies that the timezone is in the southern hemisphere, only interesting for timezones with DST. - * - * The values of the dictionary are TimeZone objects. - */ -jstz.olson.timezones = { - '-720,0' : new jstz.TimeZone('-12:00', 'Etc/GMT+12', false), - '-660,0' : new jstz.TimeZone('-11:00', 'Pacific/Pago_Pago', false), - '-600,1' : new jstz.TimeZone('-11:00', 'America/Adak', true), - '-660,1,s' : new jstz.TimeZone('-11:00', 'Pacific/Apia', true), - '-600,0' : new jstz.TimeZone('-10:00', 'Pacific/Honolulu', false), - '-570,0' : new jstz.TimeZone('-10:30', 'Pacific/Marquesas', false), - '-540,0' : new jstz.TimeZone('-09:00', 'Pacific/Gambier', false), - '-540,1' : new jstz.TimeZone('-09:00', 'America/Anchorage', true), - '-480,1' : new jstz.TimeZone('-08:00', 'America/Los_Angeles', true), - '-480,0' : new jstz.TimeZone('-08:00', 'Pacific/Pitcairn', false), - '-420,0' : new jstz.TimeZone('-07:00', 'America/Phoenix', false), - '-420,1' : new jstz.TimeZone('-07:00', 'America/Denver', true), - '-360,0' : new jstz.TimeZone('-06:00', 'America/Guatemala', false), - '-360,1' : new jstz.TimeZone('-06:00', 'America/Chicago', true), - '-360,1,s' : new jstz.TimeZone('-06:00', 'Pacific/Easter', true), - '-300,0' : new jstz.TimeZone('-05:00', 'America/Bogota', false), - '-300,1' : new jstz.TimeZone('-05:00', 'America/New_York', true), - '-270,0' : new jstz.TimeZone('-04:30', 'America/Caracas', false), - '-240,1' : new jstz.TimeZone('-04:00', 'America/Halifax', true), - '-240,0' : new jstz.TimeZone('-04:00', 'America/Santo_Domingo', false), - '-240,1,s' : new jstz.TimeZone('-04:00', 'America/Asuncion', true), - '-210,1' : new jstz.TimeZone('-03:30', 'America/St_Johns', true), - '-180,1' : new jstz.TimeZone('-03:00', 'America/Godthab', true), - '-180,0' : new jstz.TimeZone('-03:00', 'America/Argentina/Buenos_Aires', false), - '-180,1,s' : new jstz.TimeZone('-03:00', 'America/Montevideo', true), - '-120,0' : new jstz.TimeZone('-02:00', 'America/Noronha', false), - '-120,1' : new jstz.TimeZone('-02:00', 'Etc/GMT+2', true), - '-60,1' : new jstz.TimeZone('-01:00', 'Atlantic/Azores', true), - '-60,0' : new jstz.TimeZone('-01:00', 'Atlantic/Cape_Verde', false), - '0,0' : new jstz.TimeZone('00:00', 'Etc/UTC', false), - '0,1' : new jstz.TimeZone('00:00', 'Europe/London', true), - '60,1' : new jstz.TimeZone('+01:00', 'Europe/Berlin', true), - '60,0' : new jstz.TimeZone('+01:00', 'Africa/Lagos', false), - '60,1,s' : new jstz.TimeZone('+01:00', 'Africa/Windhoek', true), - '120,1' : new jstz.TimeZone('+02:00', 'Asia/Beirut', true), - '120,0' : new jstz.TimeZone('+02:00', 'Africa/Johannesburg', false), - '180,1' : new jstz.TimeZone('+03:00', 'Europe/Moscow', true), - '180,0' : new jstz.TimeZone('+03:00', 'Asia/Baghdad', false), - '210,1' : new jstz.TimeZone('+03:30', 'Asia/Tehran', true), - '240,0' : new jstz.TimeZone('+04:00', 'Asia/Dubai', false), - '240,1' : new jstz.TimeZone('+04:00', 'Asia/Yerevan', true), - '270,0' : new jstz.TimeZone('+04:30', 'Asia/Kabul', false), - '300,1' : new jstz.TimeZone('+05:00', 'Asia/Yekaterinburg', true), - '300,0' : new jstz.TimeZone('+05:00', 'Asia/Karachi', false), - '330,0' : new jstz.TimeZone('+05:30', 'Asia/Kolkata', false), - '345,0' : new jstz.TimeZone('+05:45', 'Asia/Kathmandu', false), - '360,0' : new jstz.TimeZone('+06:00', 'Asia/Dhaka', false), - '360,1' : new jstz.TimeZone('+06:00', 'Asia/Omsk', true), - '390,0' : new jstz.TimeZone('+06:30', 'Asia/Rangoon', false), - '420,1' : new jstz.TimeZone('+07:00', 'Asia/Krasnoyarsk', true), - '420,0' : new jstz.TimeZone('+07:00', 'Asia/Jakarta', false), - '480,0' : new jstz.TimeZone('+08:00', 'Asia/Shanghai', false), - '480,1' : new jstz.TimeZone('+08:00', 'Asia/Irkutsk', true), - '525,0' : new jstz.TimeZone('+08:45', 'Australia/Eucla', true), - '525,1,s' : new jstz.TimeZone('+08:45', 'Australia/Eucla', true), - '540,1' : new jstz.TimeZone('+09:00', 'Asia/Yakutsk', true), - '540,0' : new jstz.TimeZone('+09:00', 'Asia/Tokyo', false), - '570,0' : new jstz.TimeZone('+09:30', 'Australia/Darwin', false), - '570,1,s' : new jstz.TimeZone('+09:30', 'Australia/Adelaide', true), - '600,0' : new jstz.TimeZone('+10:00', 'Australia/Brisbane', false), - '600,1' : new jstz.TimeZone('+10:00', 'Asia/Vladivostok', true), - '600,1,s' : new jstz.TimeZone('+10:00', 'Australia/Sydney', true), - '630,1,s' : new jstz.TimeZone('+10:30', 'Australia/Lord_Howe', true), - '660,1' : new jstz.TimeZone('+11:00', 'Asia/Kamchatka', true), - '660,0' : new jstz.TimeZone('+11:00', 'Pacific/Noumea', false), - '690,0' : new jstz.TimeZone('+11:30', 'Pacific/Norfolk', false), - '720,1,s' : new jstz.TimeZone('+12:00', 'Pacific/Auckland', true), - '720,0' : new jstz.TimeZone('+12:00', 'Pacific/Tarawa', false), - '765,1,s' : new jstz.TimeZone('+12:45', 'Pacific/Chatham', true), - '780,0' : new jstz.TimeZone('+13:00', 'Pacific/Tongatapu', false), - '840,0' : new jstz.TimeZone('+14:00', 'Pacific/Kiritimati', false) -}; - -/** - * This object contains information on when daylight savings starts for - * different timezones. - * - * The list is short for a reason. Often we do not have to be very specific - * to single out the correct timezone. But when we do, this list comes in - * handy. - * - * Each value is a date denoting when daylight savings starts for that timezone. - */ -jstz.olson.dst_start_dates = { - 'America/Denver' : new Date(2011, 2, 13, 3, 0, 0, 0), - 'America/Mazatlan' : new Date(2011, 3, 3, 3, 0, 0, 0), - 'America/Chicago' : new Date(2011, 2, 13, 3, 0, 0, 0), - 'America/Mexico_City' : new Date(2011, 3, 3, 3, 0, 0, 0), - 'Atlantic/Stanley' : new Date(2011, 8, 4, 7, 0, 0, 0), - 'America/Asuncion' : new Date(2011, 9, 2, 3, 0, 0, 0), - 'America/Santiago' : new Date(2011, 9, 9, 3, 0, 0, 0), - 'America/Campo_Grande' : new Date(2011, 9, 16, 5, 0, 0, 0), - 'America/Montevideo' : new Date(2011, 9, 2, 3, 0, 0, 0), - 'America/Sao_Paulo' : new Date(2011, 9, 16, 5, 0, 0, 0), - 'America/Los_Angeles' : new Date(2011, 2, 13, 8, 0, 0, 0), - 'America/Santa_Isabel' : new Date(2011, 3, 5, 8, 0, 0, 0), - 'America/Havana' : new Date(2011, 2, 13, 2, 0, 0, 0), - 'America/New_York' : new Date(2011, 2, 13, 7, 0, 0, 0), - 'Asia/Gaza' : new Date(2011, 2, 26, 23, 0, 0, 0), - 'Asia/Beirut' : new Date(2011, 2, 27, 1, 0, 0, 0), - 'Europe/Minsk' : new Date(2011, 2, 27, 3, 0, 0, 0), - 'Europe/Istanbul' : new Date(2011, 2, 27, 7, 0, 0, 0), - 'Asia/Damascus' : new Date(2011, 3, 1, 2, 0, 0, 0), - 'Asia/Jerusalem' : new Date(2011, 3, 1, 6, 0, 0, 0), - 'Africa/Cairo' : new Date(2011, 3, 29, 4, 0, 0, 0), - 'Asia/Yerevan' : new Date(2011, 2, 27, 4, 0, 0, 0), - 'Asia/Baku' : new Date(2011, 2, 27, 8, 0, 0, 0), - 'Pacific/Auckland' : new Date(2011, 8, 26, 7, 0, 0, 0), - 'Pacific/Fiji' : new Date(2010, 11, 29, 23, 0, 0, 0), - 'America/Halifax' : new Date(2011, 2, 13, 6, 0, 0, 0), - 'America/Goose_Bay' : new Date(2011, 2, 13, 2, 1, 0, 0), - 'America/Miquelon' : new Date(2011, 2, 13, 5, 0, 0, 0), - 'America/Godthab' : new Date(2011, 2, 27, 1, 0, 0, 0) -}; - -/** - * The keys in this object are timezones that we know may be ambiguous after - * a preliminary scan through the olson_tz object. - * - * The array of timezones to compare must be in the order that daylight savings - * starts for the regions. - */ -jstz.olson.ambiguity_list = { - 'America/Denver' : ['America/Denver', 'America/Mazatlan'], - 'America/Chicago' : ['America/Chicago', 'America/Mexico_City'], - 'America/Asuncion' : ['Atlantic/Stanley', 'America/Asuncion', 'America/Santiago', 'America/Campo_Grande'], - 'America/Montevideo' : ['America/Montevideo', 'America/Sao_Paulo'], - 'Asia/Beirut' : ['Asia/Gaza', 'Asia/Beirut', 'Europe/Minsk', 'Europe/Istanbul', 'Asia/Damascus', 'Asia/Jerusalem', 'Africa/Cairo'], - 'Asia/Yerevan' : ['Asia/Yerevan', 'Asia/Baku'], - 'Pacific/Auckland' : ['Pacific/Auckland', 'Pacific/Fiji'], - 'America/Los_Angeles' : ['America/Los_Angeles', 'America/Santa_Isabel'], - 'America/New_York' : ['America/Havana', 'America/New_York'], - 'America/Halifax' : ['America/Goose_Bay', 'America/Halifax'], - 'America/Godthab' : ['America/Miquelon', 'America/Godthab'] -}; diff --git a/example.htm b/example.htm index e168498..c498083 100644 --- a/example.htm +++ b/example.htm @@ -3,19 +3,19 @@ Detect jQuery TimeZone Plugin - +

jQuery TimeZone Detect Plugin Sample

- Your Timezone: + Your Timezone:

- \ No newline at end of file + diff --git a/jquery.detect_timezone.js b/jquery.detect_timezone.js index 5eb020e..abb73fa 100644 --- a/jquery.detect_timezone.js +++ b/jquery.detect_timezone.js @@ -9,25 +9,25 @@ (function( $ ){ $.fn.set_timezone = function(options) { - - this.val(this.get_timezone(options)); + + this.val(this.get_timezone(options)); return this; }; - + $.fn.get_timezone = function(options) { - + var settings = { 'debug' : false, 'default' : 'America/New_York' }; - + if(options) { $.extend( settings, options ); } - - var tz_info = jstz.determine_timezone(); + + var tz_info = jstz.determine(); var timezone = tz_info.timezone; - if (timezone != 'undefined') { + if (timezone !== undefined) { timezone.ambiguity_check(); return timezone.olson_tz; } else { @@ -37,5 +37,5 @@ return settings['default'] } }; - + })( jQuery ); diff --git a/jstz.js b/jstz.js new file mode 100644 index 0000000..e46556e --- /dev/null +++ b/jstz.js @@ -0,0 +1,358 @@ +/** + * This script gives you the zone info key representing your device's time zone setting. + * + * @name jsTimezoneDetect + * @version 1.0.5 + * @author Jon Nylander + * @license MIT License - http://www.opensource.org/licenses/mit-license.php + * + * For usage and examples, visit: + * http://pellepim.bitbucket.org/jstz/ + * + * Copyright (c) Jon Nylander + */ + +/*jslint undef: true */ +/*global console, exports*/ + +(function(root) { + /** + * Namespace to hold all the code for timezone detection. + */ + var jstz = (function () { + 'use strict'; + var HEMISPHERE_SOUTH = 's', + + /** + * Gets the offset in minutes from UTC for a certain date. + * @param {Date} date + * @returns {Number} + */ + get_date_offset = function (date) { + var offset = -date.getTimezoneOffset(); + return (offset !== null ? offset : 0); + }, + + get_date = function (year, month, date) { + var d = new Date(); + if (year !== undefined) { + d.setFullYear(year); + } + d.setMonth(month); + d.setDate(date); + return d; + }, + + get_january_offset = function (year) { + return get_date_offset(get_date(year, 0 ,2)); + }, + + get_june_offset = function (year) { + return get_date_offset(get_date(year, 5, 2)); + }, + + /** + * Private method. + * Checks whether a given date is in daylight saving time. + * If the date supplied is after august, we assume that we're checking + * for southern hemisphere DST. + * @param {Date} date + * @returns {Boolean} + */ + date_is_dst = function (date) { + var is_southern = date.getMonth() > 7, + base_offset = is_southern ? get_june_offset(date.getFullYear()) : + get_january_offset(date.getFullYear()), + date_offset = get_date_offset(date), + is_west = base_offset < 0, + dst_offset = base_offset - date_offset; + + if (!is_west && !is_southern) { + return dst_offset < 0; + } + + return dst_offset !== 0; + }, + + /** + * This function does some basic calculations to create information about + * the user's timezone. It uses REFERENCE_YEAR as a solid year for which + * the script has been tested rather than depend on the year set by the + * client device. + * + * Returns a key that can be used to do lookups in jstz.olson.timezones. + * eg: "720,1,2". + * + * @returns {String} + */ + + lookup_key = function () { + var january_offset = get_january_offset(), + june_offset = get_june_offset(), + diff = january_offset - june_offset; + + if (diff < 0) { + return january_offset + ",1"; + } else if (diff > 0) { + return june_offset + ",1," + HEMISPHERE_SOUTH; + } + + return january_offset + ",0"; + }, + + /** + * Uses get_timezone_info() to formulate a key to use in the olson.timezones dictionary. + * + * Returns a primitive object on the format: + * {'timezone': TimeZone, 'key' : 'the key used to find the TimeZone object'} + * + * @returns Object + */ + determine = function () { + var key = lookup_key(); + return new jstz.TimeZone(jstz.olson.timezones[key]); + }, + + /** + * This object contains information on when daylight savings starts for + * different timezones. + * + * The list is short for a reason. Often we do not have to be very specific + * to single out the correct timezone. But when we do, this list comes in + * handy. + * + * Each value is a date denoting when daylight savings starts for that timezone. + */ + dst_start_for = function (tz_name) { + + var ru_pre_dst_change = new Date(2010, 6, 15, 1, 0, 0, 0), // In 2010 Russia had DST, this allows us to detect Russia :) + dst_starts = { + 'America/Denver': new Date(2011, 2, 13, 3, 0, 0, 0), + 'America/Mazatlan': new Date(2011, 3, 3, 3, 0, 0, 0), + 'America/Chicago': new Date(2011, 2, 13, 3, 0, 0, 0), + 'America/Mexico_City': new Date(2011, 3, 3, 3, 0, 0, 0), + 'America/Asuncion': new Date(2012, 9, 7, 3, 0, 0, 0), + 'America/Santiago': new Date(2012, 9, 3, 3, 0, 0, 0), + 'America/Campo_Grande': new Date(2012, 9, 21, 5, 0, 0, 0), + 'America/Montevideo': new Date(2011, 9, 2, 3, 0, 0, 0), + 'America/Sao_Paulo': new Date(2011, 9, 16, 5, 0, 0, 0), + 'America/Los_Angeles': new Date(2011, 2, 13, 8, 0, 0, 0), + 'America/Santa_Isabel': new Date(2011, 3, 5, 8, 0, 0, 0), + 'America/Havana': new Date(2012, 2, 10, 2, 0, 0, 0), + 'America/New_York': new Date(2012, 2, 10, 7, 0, 0, 0), + 'Europe/Helsinki': new Date(2013, 2, 31, 5, 0, 0, 0), + 'Pacific/Auckland': new Date(2011, 8, 26, 7, 0, 0, 0), + 'America/Halifax': new Date(2011, 2, 13, 6, 0, 0, 0), + 'America/Goose_Bay': new Date(2011, 2, 13, 2, 1, 0, 0), + 'America/Miquelon': new Date(2011, 2, 13, 5, 0, 0, 0), + 'America/Godthab': new Date(2011, 2, 27, 1, 0, 0, 0), + 'Europe/Moscow': ru_pre_dst_change, + 'Asia/Amman': new Date(2013, 2, 29, 1, 0, 0, 0), + 'Asia/Beirut': new Date(2013, 2, 31, 2, 0, 0, 0), + 'Asia/Damascus': new Date(2013, 3, 6, 2, 0, 0, 0), + 'Asia/Jerusalem': new Date(2013, 2, 29, 5, 0, 0, 0), + 'Asia/Yekaterinburg': ru_pre_dst_change, + 'Asia/Omsk': ru_pre_dst_change, + 'Asia/Krasnoyarsk': ru_pre_dst_change, + 'Asia/Irkutsk': ru_pre_dst_change, + 'Asia/Yakutsk': ru_pre_dst_change, + 'Asia/Vladivostok': ru_pre_dst_change, + 'Asia/Baku': new Date(2013, 2, 31, 4, 0, 0), + 'Asia/Yerevan': new Date(2013, 2, 31, 3, 0, 0), + 'Asia/Kamchatka': ru_pre_dst_change, + 'Asia/Gaza': new Date(2010, 2, 27, 4, 0, 0), + 'Africa/Cairo': new Date(2010, 4, 1, 3, 0, 0), + 'Europe/Minsk': ru_pre_dst_change, + 'Pacific/Apia': new Date(2010, 10, 1, 1, 0, 0, 0), + 'Pacific/Fiji': new Date(2010, 11, 1, 0, 0, 0), + 'Australia/Perth': new Date(2008, 10, 1, 1, 0, 0, 0) + }; + + return dst_starts[tz_name]; + }; + + return { + determine: determine, + date_is_dst: date_is_dst, + dst_start_for: dst_start_for + }; + }()); + + /** + * Simple object to perform ambiguity check and to return name of time zone. + */ + jstz.TimeZone = function (tz_name) { + 'use strict'; + /** + * The keys in this object are timezones that we know may be ambiguous after + * a preliminary scan through the olson_tz object. + * + * The array of timezones to compare must be in the order that daylight savings + * starts for the regions. + */ + var AMBIGUITIES = { + 'America/Denver': ['America/Denver', 'America/Mazatlan'], + 'America/Chicago': ['America/Chicago', 'America/Mexico_City'], + 'America/Santiago': ['America/Santiago', 'America/Asuncion', 'America/Campo_Grande'], + 'America/Montevideo': ['America/Montevideo', 'America/Sao_Paulo'], + 'Asia/Beirut': ['Asia/Amman', 'Asia/Jerusalem', 'Asia/Beirut', 'Europe/Helsinki','Asia/Damascus'], + 'Pacific/Auckland': ['Pacific/Auckland', 'Pacific/Fiji'], + 'America/Los_Angeles': ['America/Los_Angeles', 'America/Santa_Isabel'], + 'America/New_York': ['America/Havana', 'America/New_York'], + 'America/Halifax': ['America/Goose_Bay', 'America/Halifax'], + 'America/Godthab': ['America/Miquelon', 'America/Godthab'], + 'Asia/Dubai': ['Europe/Moscow'], + 'Asia/Dhaka': ['Asia/Yekaterinburg'], + 'Asia/Jakarta': ['Asia/Omsk'], + 'Asia/Shanghai': ['Asia/Krasnoyarsk', 'Australia/Perth'], + 'Asia/Tokyo': ['Asia/Irkutsk'], + 'Australia/Brisbane': ['Asia/Yakutsk'], + 'Pacific/Noumea': ['Asia/Vladivostok'], + 'Pacific/Tarawa': ['Asia/Kamchatka', 'Pacific/Fiji'], + 'Pacific/Tongatapu': ['Pacific/Apia'], + 'Asia/Baghdad': ['Europe/Minsk'], + 'Asia/Baku': ['Asia/Yerevan','Asia/Baku'], + 'Africa/Johannesburg': ['Asia/Gaza', 'Africa/Cairo'] + }, + + timezone_name = tz_name, + + /** + * Checks if a timezone has possible ambiguities. I.e timezones that are similar. + * + * For example, if the preliminary scan determines that we're in America/Denver. + * We double check here that we're really there and not in America/Mazatlan. + * + * This is done by checking known dates for when daylight savings start for different + * timezones during 2010 and 2011. + */ + ambiguity_check = function () { + var ambiguity_list = AMBIGUITIES[timezone_name], + length = ambiguity_list.length, + i = 0, + tz = ambiguity_list[0]; + + for (; i < length; i += 1) { + tz = ambiguity_list[i]; + + if (jstz.date_is_dst(jstz.dst_start_for(tz))) { + timezone_name = tz; + return; + } + } + }, + + /** + * Checks if it is possible that the timezone is ambiguous. + */ + is_ambiguous = function () { + return typeof (AMBIGUITIES[timezone_name]) !== 'undefined'; + }; + + if (is_ambiguous()) { + ambiguity_check(); + } + + return { + name: function () { + return timezone_name; + } + }; + }; + + jstz.olson = {}; + + /* + * The keys in this dictionary are comma separated as such: + * + * First the offset compared to UTC time in minutes. + * + * Then a flag which is 0 if the timezone does not take daylight savings into account and 1 if it + * does. + * + * Thirdly an optional 's' signifies that the timezone is in the southern hemisphere, + * only interesting for timezones with DST. + * + * The mapped arrays is used for constructing the jstz.TimeZone object from within + * jstz.determine_timezone(); + */ + jstz.olson.timezones = { + '-720,0' : 'Pacific/Majuro', + '-660,0' : 'Pacific/Pago_Pago', + '-600,1' : 'America/Adak', + '-600,0' : 'Pacific/Honolulu', + '-570,0' : 'Pacific/Marquesas', + '-540,0' : 'Pacific/Gambier', + '-540,1' : 'America/Anchorage', + '-480,1' : 'America/Los_Angeles', + '-480,0' : 'Pacific/Pitcairn', + '-420,0' : 'America/Phoenix', + '-420,1' : 'America/Denver', + '-360,0' : 'America/Guatemala', + '-360,1' : 'America/Chicago', + '-360,1,s' : 'Pacific/Easter', + '-300,0' : 'America/Bogota', + '-300,1' : 'America/New_York', + '-270,0' : 'America/Caracas', + '-240,1' : 'America/Halifax', + '-240,0' : 'America/Santo_Domingo', + '-240,1,s' : 'America/Santiago', + '-210,1' : 'America/St_Johns', + '-180,1' : 'America/Godthab', + '-180,0' : 'America/Argentina/Buenos_Aires', + '-180,1,s' : 'America/Montevideo', + '-120,0' : 'America/Noronha', + '-120,1' : 'America/Noronha', + '-60,1' : 'Atlantic/Azores', + '-60,0' : 'Atlantic/Cape_Verde', + '0,0' : 'UTC', + '0,1' : 'Europe/London', + '60,1' : 'Europe/Berlin', + '60,0' : 'Africa/Lagos', + '60,1,s' : 'Africa/Windhoek', + '120,1' : 'Asia/Beirut', + '120,0' : 'Africa/Johannesburg', + '180,0' : 'Asia/Baghdad', + '180,1' : 'Europe/Moscow', + '210,1' : 'Asia/Tehran', + '240,0' : 'Asia/Dubai', + '240,1' : 'Asia/Baku', + '270,0' : 'Asia/Kabul', + '300,1' : 'Asia/Yekaterinburg', + '300,0' : 'Asia/Karachi', + '330,0' : 'Asia/Kolkata', + '345,0' : 'Asia/Kathmandu', + '360,0' : 'Asia/Dhaka', + '360,1' : 'Asia/Omsk', + '390,0' : 'Asia/Rangoon', + '420,1' : 'Asia/Krasnoyarsk', + '420,0' : 'Asia/Jakarta', + '480,0' : 'Asia/Shanghai', + '480,1' : 'Asia/Irkutsk', + '525,0' : 'Australia/Eucla', + '525,1,s' : 'Australia/Eucla', + '540,1' : 'Asia/Yakutsk', + '540,0' : 'Asia/Tokyo', + '570,0' : 'Australia/Darwin', + '570,1,s' : 'Australia/Adelaide', + '600,0' : 'Australia/Brisbane', + '600,1' : 'Asia/Vladivostok', + '600,1,s' : 'Australia/Sydney', + '630,1,s' : 'Australia/Lord_Howe', + '660,1' : 'Asia/Kamchatka', + '660,0' : 'Pacific/Noumea', + '690,0' : 'Pacific/Norfolk', + '720,1,s' : 'Pacific/Auckland', + '720,0' : 'Pacific/Tarawa', + '765,1,s' : 'Pacific/Chatham', + '780,0' : 'Pacific/Tongatapu', + '780,1,s' : 'Pacific/Apia', + '840,0' : 'Pacific/Kiritimati' + }; + + if (typeof exports !== 'undefined') { + exports.jstz = jstz; + } else { + root.jstz = jstz; + } +})(this);