parent
b8a1340538
commit
bb18fe1384
@ -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); |
||||
Loading…
Reference in new issue