diff --git a/jstz/jstz.js b/jstz/jstz.js new file mode 100644 index 00000000..0dfddeb9 --- /dev/null +++ b/jstz/jstz.js @@ -0,0 +1,1425 @@ +(function (root) {/*global exports, Intl*/ +/** + * 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 - https://bitbucket.org/pellepim/jstimezonedetect/src/default/LICENCE.txt + * + * For usage and examples, visit: + * http://pellepim.bitbucket.org/jstz/ + * + * Copyright (c) Jon Nylander + */ + + +/** + * Namespace to hold all the code for timezone detection. + */ +var jstz = (function () { + 'use strict'; + var HEMISPHERE_SOUTH = 's', + + consts = { + DAY: 86400000, + HOUR: 3600000, + MINUTE: 60000, + SECOND: 1000, + BASELINE_YEAR: 2014, + MAX_SCORE: 864000000, // 10 days + AMBIGUITIES: { + 'America/Denver': ['America/Mazatlan'], + 'Europe/London': ['Africa/Casablanca'], + 'America/Chicago': ['America/Mexico_City'], + 'America/Asuncion': ['America/Campo_Grande', 'America/Santiago'], + 'America/Montevideo': ['America/Sao_Paulo', 'America/Santiago'], + // Europe/Minsk should not be in this list... but Windows. + 'Asia/Beirut': ['Asia/Amman', 'Asia/Jerusalem', 'Europe/Helsinki', 'Asia/Damascus', 'Africa/Cairo', 'Asia/Gaza', 'Europe/Minsk'], + 'Pacific/Auckland': ['Pacific/Fiji'], + 'America/Los_Angeles': ['America/Santa_Isabel'], + 'America/New_York': ['America/Havana'], + 'America/Halifax': ['America/Goose_Bay'], + 'America/Godthab': ['America/Miquelon'], + 'Asia/Dubai': ['Asia/Yerevan'], + 'Asia/Jakarta': ['Asia/Krasnoyarsk'], + 'Asia/Shanghai': ['Asia/Irkutsk', 'Australia/Perth'], + 'Australia/Sydney': ['Australia/Lord_Howe'], + 'Asia/Tokyo': ['Asia/Yakutsk'], + 'Asia/Dhaka': ['Asia/Omsk'], + // In the real world Yerevan is not ambigous for Baku... but Windows. + 'Asia/Baku': ['Asia/Yerevan'], + 'Australia/Brisbane': ['Asia/Vladivostok'], + 'Pacific/Noumea': ['Asia/Vladivostok'], + 'Pacific/Majuro': ['Asia/Kamchatka', 'Pacific/Fiji'], + 'Pacific/Tongatapu': ['Pacific/Apia'], + 'Asia/Baghdad': ['Europe/Minsk', 'Europe/Moscow'], + 'Asia/Karachi': ['Asia/Yekaterinburg'], + 'Africa/Johannesburg': ['Asia/Gaza', 'Africa/Cairo'] + } + }, + + /** + * Gets the offset in minutes from UTC for a certain date. + * @param {Date} date + * @returns {Number} + */ + get_date_offset = function get_date_offset(date) { + var offset = -date.getTimezoneOffset(); + return (offset !== null ? 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 lookup_key() { + var january_offset = get_date_offset(new Date(consts.BASELINE_YEAR, 0, 2)), + june_offset = get_date_offset(new Date(consts.BASELINE_YEAR, 5, 2)), + 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"; + }, + + + /** + * Tries to get the time zone key directly from the operating system for those + * environments that support the ECMAScript Internationalization API. + */ + get_from_internationalization_api = function get_from_internationalization_api() { + var format, timezone; + if (typeof Intl === "undefined" || typeof Intl.DateTimeFormat === "undefined") { + return; + } + + format = Intl.DateTimeFormat(); + + if (typeof format === "undefined" || typeof format.resolvedOptions === "undefined") { + return; + } + + timezone = format.resolvedOptions().timeZone; + + if (timezone && (timezone.indexOf("/") > -1 || timezone === 'UTC')) { + return timezone; + } + + }, + + /** + * Starting point for getting all the DST rules for a specific year + * for the current timezone (as described by the client system). + * + * Returns an object with start and end attributes, or false if no + * DST rules were found for the year. + * + * @param year + * @returns {Object} || {Boolean} + */ + dst_dates = function dst_dates(year) { + var yearstart = new Date(year, 0, 1, 0, 0, 1, 0).getTime(); + var yearend = new Date(year, 12, 31, 23, 59, 59).getTime(); + var current = yearstart; + var offset = (new Date(current)).getTimezoneOffset(); + var dst_start = null; + var dst_end = null; + + while (current < yearend - 86400000) { + var dateToCheck = new Date(current); + var dateToCheckOffset = dateToCheck.getTimezoneOffset(); + + if (dateToCheckOffset !== offset) { + if (dateToCheckOffset < offset) { + dst_start = dateToCheck; + } + if (dateToCheckOffset > offset) { + dst_end = dateToCheck; + } + offset = dateToCheckOffset; + } + + current += 86400000; + } + + if (dst_start && dst_end) { + return { + s: find_dst_fold(dst_start).getTime(), + e: find_dst_fold(dst_end).getTime() + }; + } + + return false; + }, + + /** + * Probably completely unnecessary function that recursively finds the + * exact (to the second) time when a DST rule was changed. + * + * @param a_date - The candidate Date. + * @param padding - integer specifying the padding to allow around the candidate + * date for finding the fold. + * @param iterator - integer specifying how many milliseconds to iterate while + * searching for the fold. + * + * @returns {Date} + */ + find_dst_fold = function find_dst_fold(a_date, padding, iterator) { + if (typeof padding === 'undefined') { + padding = consts.DAY; + iterator = consts.HOUR; + } + + var date_start = new Date(a_date.getTime() - padding).getTime(); + var date_end = a_date.getTime() + padding; + var offset = new Date(date_start).getTimezoneOffset(); + + var current = date_start; + + var dst_change = null; + while (current < date_end - iterator) { + var dateToCheck = new Date(current); + var dateToCheckOffset = dateToCheck.getTimezoneOffset(); + + if (dateToCheckOffset !== offset) { + dst_change = dateToCheck; + break; + } + current += iterator; + } + + if (padding === consts.DAY) { + return find_dst_fold(dst_change, consts.HOUR, consts.MINUTE); + } + + if (padding === consts.HOUR) { + return find_dst_fold(dst_change, consts.MINUTE, consts.SECOND); + } + + return dst_change; + }, + + windows7_adaptations = function windows7_adaptions(rule_list, preliminary_timezone, score, sample) { + if (score !== 'N/A') { + return score; + } + if (preliminary_timezone === 'Asia/Beirut') { + if (sample.name === 'Africa/Cairo') { + if (rule_list[6].s === 1398376800000 && rule_list[6].e === 1411678800000) { + return 0; + } + } + if (sample.name === 'Asia/Jerusalem') { + if (rule_list[6].s === 1395964800000 && rule_list[6].e === 1411858800000) { + return 0; + } + } + } else if (preliminary_timezone === 'America/Santiago') { + if (sample.name === 'America/Asuncion') { + if (rule_list[6].s === 1412481600000 && rule_list[6].e === 1397358000000) { + return 0; + } + } + if (sample.name === 'America/Campo_Grande') { + if (rule_list[6].s === 1413691200000 && rule_list[6].e === 1392519600000) { + return 0; + } + } + } else if (preliminary_timezone === 'America/Montevideo') { + if (sample.name === 'America/Sao_Paulo') { + if (rule_list[6].s === 1413687600000 && rule_list[6].e === 1392516000000) { + return 0; + } + } + } else if (preliminary_timezone === 'Pacific/Auckland') { + if (sample.name === 'Pacific/Fiji') { + if (rule_list[6].s === 1414245600000 && rule_list[6].e === 1396101600000) { + return 0; + } + } + } + + return score; + }, + + /** + * Takes the DST rules for the current timezone, and proceeds to find matches + * in the jstz.olson.dst_rules.zones array. + * + * Compares samples to the current timezone on a scoring basis. + * + * Candidates are ruled immediately if either the candidate or the current zone + * has a DST rule where the other does not. + * + * Candidates are ruled out immediately if the current zone has a rule that is + * outside the DST scope of the candidate. + * + * Candidates are included for scoring if the current zones rules fall within the + * span of the samples rules. + * + * Low score is best, the score is calculated by summing up the differences in DST + * rules and if the consts.MAX_SCORE is overreached the candidate is ruled out. + * + * Yah follow? :) + * + * @param rule_list + * @param preliminary_timezone + * @returns {*} + */ + best_dst_match = function best_dst_match(rule_list, preliminary_timezone) { + var score_sample = function score_sample(sample) { + var score = 0; + + for (var j = 0; j < rule_list.length; j++) { + + // Both sample and current time zone report DST during the year. + if (!!sample.rules[j] && !!rule_list[j]) { + + // The current time zone's DST rules are inside the sample's. Include. + if (rule_list[j].s >= sample.rules[j].s && rule_list[j].e <= sample.rules[j].e) { + score = 0; + score += Math.abs(rule_list[j].s - sample.rules[j].s); + score += Math.abs(sample.rules[j].e - rule_list[j].e); + + // The current time zone's DST rules are outside the sample's. Discard. + } else { + score = 'N/A'; + break; + } + + // The max score has been reached. Discard. + if (score > consts.MAX_SCORE) { + score = 'N/A'; + break; + } + } + } + + score = windows7_adaptations(rule_list, preliminary_timezone, score, sample); + + return score; + }; + var scoreboard = {}; + var dst_zones = jstz.olson.dst_rules.zones; + var dst_zones_length = dst_zones.length; + var ambiguities = consts.AMBIGUITIES[preliminary_timezone]; + + for (var i = 0; i < dst_zones_length; i++) { + var sample = dst_zones[i]; + var score = score_sample(dst_zones[i]); + + if (score !== 'N/A') { + scoreboard[sample.name] = score; + } + } + + for (var tz in scoreboard) { + if (scoreboard.hasOwnProperty(tz)) { + for (var j = 0; j < ambiguities.length; j++) { + if (ambiguities[j] === tz) { + return tz; + } + } + } + } + + return preliminary_timezone; + }, + + /** + * Takes the preliminary_timezone as detected by lookup_key(). + * + * Builds up the current timezones DST rules for the years defined + * in the jstz.olson.dst_rules.years array. + * + * If there are no DST occurences for those years, immediately returns + * the preliminary timezone. Otherwise proceeds and tries to solve + * ambiguities. + * + * @param preliminary_timezone + * @returns {String} timezone_name + */ + get_by_dst = function get_by_dst(preliminary_timezone) { + var get_rules = function get_rules() { + var rule_list = []; + for (var i = 0; i < jstz.olson.dst_rules.years.length; i++) { + var year_rules = dst_dates(jstz.olson.dst_rules.years[i]); + rule_list.push(year_rules); + } + return rule_list; + }; + var check_has_dst = function check_has_dst(rules) { + for (var i = 0; i < rules.length; i++) { + if (rules[i] !== false) { + return true; + } + } + return false; + }; + var rules = get_rules(); + var has_dst = check_has_dst(rules); + + if (has_dst) { + return best_dst_match(rules, preliminary_timezone); + } + + return preliminary_timezone; + }, + + /** + * Uses get_timezone_info() to formulate a key to use in the olson.timezones dictionary. + * + * Returns an object with one function ".name()" + * + * @returns Object + */ + determine = function determine() { + var preliminary_tz = get_from_internationalization_api(); + + if (!preliminary_tz) { + preliminary_tz = jstz.olson.timezones[lookup_key()]; + + if (typeof consts.AMBIGUITIES[preliminary_tz] !== 'undefined') { + preliminary_tz = get_by_dst(preliminary_tz); + } + } + + return { + name: function () { + return preliminary_tz; + } + }; + }; + + return { + determine: determine + }; +}()); + + +jstz.olson = 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(); + */ +jstz.olson.timezones = { + '-720,0': 'Etc/GMT+12', + '-660,0': 'Pacific/Pago_Pago', + '-660,1,s': 'Pacific/Apia', // Why? Because windows... cry! + '-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/Asuncion', + '-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/Majuro', + '765,1,s': 'Pacific/Chatham', + '780,0': 'Pacific/Tongatapu', + '780,1,s': 'Pacific/Apia', + '840,0': 'Pacific/Kiritimati' +}; + +/* Build time: 2015-09-17 08:50:28Z Build by invoking python utilities/dst.py generate */ +jstz.olson.dst_rules = { + "years": [ + 2008, + 2009, + 2010, + 2011, + 2012, + 2013, + 2014 + ], + "zones": [ + { + "name": "Africa/Cairo", + "rules": [ + { + "e": 1219957200000, + "s": 1209074400000 + }, + { + "e": 1250802000000, + "s": 1240524000000 + }, + { + "e": 1285880400000, + "s": 1284069600000 + }, + false, + false, + false, + { + "e": 1411678800000, + "s": 1406844000000 + } + ] + }, + { + "name": "Africa/Casablanca", + "rules": [ + { + "e": 1220223600000, + "s": 1212278400000 + }, + { + "e": 1250809200000, + "s": 1243814400000 + }, + { + "e": 1281222000000, + "s": 1272758400000 + }, + { + "e": 1312066800000, + "s": 1301788800000 + }, + { + "e": 1348970400000, + "s": 1345428000000 + }, + { + "e": 1382839200000, + "s": 1376100000000 + }, + { + "e": 1414288800000, + "s": 1406944800000 + } + ] + }, + { + "name": "America/Asuncion", + "rules": [ + { + "e": 1205031600000, + "s": 1224388800000 + }, + { + "e": 1236481200000, + "s": 1255838400000 + }, + { + "e": 1270954800000, + "s": 1286078400000 + }, + { + "e": 1302404400000, + "s": 1317528000000 + }, + { + "e": 1333854000000, + "s": 1349582400000 + }, + { + "e": 1364094000000, + "s": 1381032000000 + }, + { + "e": 1395543600000, + "s": 1412481600000 + } + ] + }, + { + "name": "America/Campo_Grande", + "rules": [ + { + "e": 1203217200000, + "s": 1224388800000 + }, + { + "e": 1234666800000, + "s": 1255838400000 + }, + { + "e": 1266721200000, + "s": 1287288000000 + }, + { + "e": 1298170800000, + "s": 1318737600000 + }, + { + "e": 1330225200000, + "s": 1350792000000 + }, + { + "e": 1361070000000, + "s": 1382241600000 + }, + { + "e": 1392519600000, + "s": 1413691200000 + } + ] + }, + { + "name": "America/Goose_Bay", + "rules": [ + { + "e": 1225594860000, + "s": 1205035260000 + }, + { + "e": 1257044460000, + "s": 1236484860000 + }, + { + "e": 1289098860000, + "s": 1268539260000 + }, + { + "e": 1320555600000, + "s": 1299988860000 + }, + { + "e": 1352005200000, + "s": 1331445600000 + }, + { + "e": 1383454800000, + "s": 1362895200000 + }, + { + "e": 1414904400000, + "s": 1394344800000 + } + ] + }, + { + "name": "America/Havana", + "rules": [ + { + "e": 1224997200000, + "s": 1205643600000 + }, + { + "e": 1256446800000, + "s": 1236488400000 + }, + { + "e": 1288501200000, + "s": 1268542800000 + }, + { + "e": 1321160400000, + "s": 1300597200000 + }, + { + "e": 1352005200000, + "s": 1333256400000 + }, + { + "e": 1383454800000, + "s": 1362891600000 + }, + { + "e": 1414904400000, + "s": 1394341200000 + } + ] + }, + { + "name": "America/Mazatlan", + "rules": [ + { + "e": 1225008000000, + "s": 1207472400000 + }, + { + "e": 1256457600000, + "s": 1238922000000 + }, + { + "e": 1288512000000, + "s": 1270371600000 + }, + { + "e": 1319961600000, + "s": 1301821200000 + }, + { + "e": 1351411200000, + "s": 1333270800000 + }, + { + "e": 1382860800000, + "s": 1365325200000 + }, + { + "e": 1414310400000, + "s": 1396774800000 + } + ] + }, + { + "name": "America/Mexico_City", + "rules": [ + { + "e": 1225004400000, + "s": 1207468800000 + }, + { + "e": 1256454000000, + "s": 1238918400000 + }, + { + "e": 1288508400000, + "s": 1270368000000 + }, + { + "e": 1319958000000, + "s": 1301817600000 + }, + { + "e": 1351407600000, + "s": 1333267200000 + }, + { + "e": 1382857200000, + "s": 1365321600000 + }, + { + "e": 1414306800000, + "s": 1396771200000 + } + ] + }, + { + "name": "America/Miquelon", + "rules": [ + { + "e": 1225598400000, + "s": 1205038800000 + }, + { + "e": 1257048000000, + "s": 1236488400000 + }, + { + "e": 1289102400000, + "s": 1268542800000 + }, + { + "e": 1320552000000, + "s": 1299992400000 + }, + { + "e": 1352001600000, + "s": 1331442000000 + }, + { + "e": 1383451200000, + "s": 1362891600000 + }, + { + "e": 1414900800000, + "s": 1394341200000 + } + ] + }, + { + "name": "America/Santa_Isabel", + "rules": [ + { + "e": 1225011600000, + "s": 1207476000000 + }, + { + "e": 1256461200000, + "s": 1238925600000 + }, + { + "e": 1288515600000, + "s": 1270375200000 + }, + { + "e": 1319965200000, + "s": 1301824800000 + }, + { + "e": 1351414800000, + "s": 1333274400000 + }, + { + "e": 1382864400000, + "s": 1365328800000 + }, + { + "e": 1414314000000, + "s": 1396778400000 + } + ] + }, + { + "name": "America/Santiago", + "rules": [ + { + "e": 1206846000000, + "s": 1223784000000 + }, + { + "e": 1237086000000, + "s": 1255233600000 + }, + { + "e": 1270350000000, + "s": 1286683200000 + }, + { + "e": 1304823600000, + "s": 1313899200000 + }, + { + "e": 1335668400000, + "s": 1346558400000 + }, + { + "e": 1367118000000, + "s": 1378612800000 + }, + { + "e": 1398567600000, + "s": 1410062400000 + } + ] + }, + { + "name": "America/Sao_Paulo", + "rules": [ + { + "e": 1203213600000, + "s": 1224385200000 + }, + { + "e": 1234663200000, + "s": 1255834800000 + }, + { + "e": 1266717600000, + "s": 1287284400000 + }, + { + "e": 1298167200000, + "s": 1318734000000 + }, + { + "e": 1330221600000, + "s": 1350788400000 + }, + { + "e": 1361066400000, + "s": 1382238000000 + }, + { + "e": 1392516000000, + "s": 1413687600000 + } + ] + }, + { + "name": "Asia/Amman", + "rules": [ + { + "e": 1225404000000, + "s": 1206655200000 + }, + { + "e": 1256853600000, + "s": 1238104800000 + }, + { + "e": 1288303200000, + "s": 1269554400000 + }, + { + "e": 1319752800000, + "s": 1301608800000 + }, + false, + false, + { + "e": 1414706400000, + "s": 1395957600000 + } + ] + }, + { + "name": "Asia/Damascus", + "rules": [ + { + "e": 1225486800000, + "s": 1207260000000 + }, + { + "e": 1256850000000, + "s": 1238104800000 + }, + { + "e": 1288299600000, + "s": 1270159200000 + }, + { + "e": 1319749200000, + "s": 1301608800000 + }, + { + "e": 1351198800000, + "s": 1333058400000 + }, + { + "e": 1382648400000, + "s": 1364508000000 + }, + { + "e": 1414702800000, + "s": 1395957600000 + } + ] + }, + { + "name": "Asia/Dubai", + "rules": [ + false, + false, + false, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Gaza", + "rules": [ + { + "e": 1219957200000, + "s": 1206655200000 + }, + { + "e": 1252015200000, + "s": 1238104800000 + }, + { + "e": 1281474000000, + "s": 1269640860000 + }, + { + "e": 1312146000000, + "s": 1301608860000 + }, + { + "e": 1348178400000, + "s": 1333058400000 + }, + { + "e": 1380229200000, + "s": 1364508000000 + }, + { + "e": 1414098000000, + "s": 1395957600000 + } + ] + }, + { + "name": "Asia/Irkutsk", + "rules": [ + { + "e": 1224957600000, + "s": 1206813600000 + }, + { + "e": 1256407200000, + "s": 1238263200000 + }, + { + "e": 1288461600000, + "s": 1269712800000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Jerusalem", + "rules": [ + { + "e": 1223161200000, + "s": 1206662400000 + }, + { + "e": 1254006000000, + "s": 1238112000000 + }, + { + "e": 1284246000000, + "s": 1269561600000 + }, + { + "e": 1317510000000, + "s": 1301616000000 + }, + { + "e": 1348354800000, + "s": 1333065600000 + }, + { + "e": 1382828400000, + "s": 1364515200000 + }, + { + "e": 1414278000000, + "s": 1395964800000 + } + ] + }, + { + "name": "Asia/Kamchatka", + "rules": [ + { + "e": 1224943200000, + "s": 1206799200000 + }, + { + "e": 1256392800000, + "s": 1238248800000 + }, + { + "e": 1288450800000, + "s": 1269698400000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Krasnoyarsk", + "rules": [ + { + "e": 1224961200000, + "s": 1206817200000 + }, + { + "e": 1256410800000, + "s": 1238266800000 + }, + { + "e": 1288465200000, + "s": 1269716400000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Omsk", + "rules": [ + { + "e": 1224964800000, + "s": 1206820800000 + }, + { + "e": 1256414400000, + "s": 1238270400000 + }, + { + "e": 1288468800000, + "s": 1269720000000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Vladivostok", + "rules": [ + { + "e": 1224950400000, + "s": 1206806400000 + }, + { + "e": 1256400000000, + "s": 1238256000000 + }, + { + "e": 1288454400000, + "s": 1269705600000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Yakutsk", + "rules": [ + { + "e": 1224954000000, + "s": 1206810000000 + }, + { + "e": 1256403600000, + "s": 1238259600000 + }, + { + "e": 1288458000000, + "s": 1269709200000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Yekaterinburg", + "rules": [ + { + "e": 1224968400000, + "s": 1206824400000 + }, + { + "e": 1256418000000, + "s": 1238274000000 + }, + { + "e": 1288472400000, + "s": 1269723600000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Asia/Yerevan", + "rules": [ + { + "e": 1224972000000, + "s": 1206828000000 + }, + { + "e": 1256421600000, + "s": 1238277600000 + }, + { + "e": 1288476000000, + "s": 1269727200000 + }, + { + "e": 1319925600000, + "s": 1301176800000 + }, + false, + false, + false + ] + }, + { + "name": "Australia/Lord_Howe", + "rules": [ + { + "e": 1207407600000, + "s": 1223134200000 + }, + { + "e": 1238857200000, + "s": 1254583800000 + }, + { + "e": 1270306800000, + "s": 1286033400000 + }, + { + "e": 1301756400000, + "s": 1317483000000 + }, + { + "e": 1333206000000, + "s": 1349537400000 + }, + { + "e": 1365260400000, + "s": 1380987000000 + }, + { + "e": 1396710000000, + "s": 1412436600000 + } + ] + }, + { + "name": "Australia/Perth", + "rules": [ + { + "e": 1206813600000, + "s": 1224957600000 + }, + false, + false, + false, + false, + false, + false + ] + }, + { + "name": "Europe/Helsinki", + "rules": [ + { + "e": 1224982800000, + "s": 1206838800000 + }, + { + "e": 1256432400000, + "s": 1238288400000 + }, + { + "e": 1288486800000, + "s": 1269738000000 + }, + { + "e": 1319936400000, + "s": 1301187600000 + }, + { + "e": 1351386000000, + "s": 1332637200000 + }, + { + "e": 1382835600000, + "s": 1364691600000 + }, + { + "e": 1414285200000, + "s": 1396141200000 + } + ] + }, + { + "name": "Europe/Minsk", + "rules": [ + { + "e": 1224979200000, + "s": 1206835200000 + }, + { + "e": 1256428800000, + "s": 1238284800000 + }, + { + "e": 1288483200000, + "s": 1269734400000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Europe/Moscow", + "rules": [ + { + "e": 1224975600000, + "s": 1206831600000 + }, + { + "e": 1256425200000, + "s": 1238281200000 + }, + { + "e": 1288479600000, + "s": 1269730800000 + }, + false, + false, + false, + false + ] + }, + { + "name": "Pacific/Apia", + "rules": [ + false, + false, + false, + { + "e": 1301752800000, + "s": 1316872800000 + }, + { + "e": 1333202400000, + "s": 1348927200000 + }, + { + "e": 1365256800000, + "s": 1380376800000 + }, + { + "e": 1396706400000, + "s": 1411826400000 + } + ] + }, + { + "name": "Pacific/Fiji", + "rules": [ + false, + false, + { + "e": 1269698400000, + "s": 1287842400000 + }, + { + "e": 1327154400000, + "s": 1319292000000 + }, + { + "e": 1358604000000, + "s": 1350741600000 + }, + { + "e": 1390050000000, + "s": 1382796000000 + }, + { + "e": 1421503200000, + "s": 1414850400000 + } + ] + }, + { + "name": "Europe/London", + "rules": [ + { + "e": 1224982800000, + "s": 1206838800000 + }, + { + "e": 1256432400000, + "s": 1238288400000 + }, + { + "e": 1288486800000, + "s": 1269738000000 + }, + { + "e": 1319936400000, + "s": 1301187600000 + }, + { + "e": 1351386000000, + "s": 1332637200000 + }, + { + "e": 1382835600000, + "s": 1364691600000 + }, + { + "e": 1414285200000, + "s": 1396141200000 + } + ] + } + ] +}; + if (typeof exports !== 'undefined') { + module.exports.jstz = jstz; + } else { + root.jstz = jstz; + } +})(this); diff --git a/jstz/jstz.min.js b/jstz/jstz.min.js new file mode 100644 index 00000000..4b45ae16 --- /dev/null +++ b/jstz/jstz.min.js @@ -0,0 +1,2 @@ +/* jstz.min.js Version: 1.0.5 Build date: 2015-09-17 */ +!function(e){var a=function(){"use strict";var e="s",s={DAY:864e5,HOUR:36e5,MINUTE:6e4,SECOND:1e3,BASELINE_YEAR:2014,MAX_SCORE:864e6,AMBIGUITIES:{"America/Denver":["America/Mazatlan"],"Europe/London":["Africa/Casablanca"],"America/Chicago":["America/Mexico_City"],"America/Asuncion":["America/Campo_Grande","America/Santiago"],"America/Montevideo":["America/Sao_Paulo","America/Santiago"],"Asia/Beirut":["Asia/Amman","Asia/Jerusalem","Europe/Helsinki","Asia/Damascus","Africa/Cairo","Asia/Gaza","Europe/Minsk"],"Pacific/Auckland":["Pacific/Fiji"],"America/Los_Angeles":["America/Santa_Isabel"],"America/New_York":["America/Havana"],"America/Halifax":["America/Goose_Bay"],"America/Godthab":["America/Miquelon"],"Asia/Dubai":["Asia/Yerevan"],"Asia/Jakarta":["Asia/Krasnoyarsk"],"Asia/Shanghai":["Asia/Irkutsk","Australia/Perth"],"Australia/Sydney":["Australia/Lord_Howe"],"Asia/Tokyo":["Asia/Yakutsk"],"Asia/Dhaka":["Asia/Omsk"],"Asia/Baku":["Asia/Yerevan"],"Australia/Brisbane":["Asia/Vladivostok"],"Pacific/Noumea":["Asia/Vladivostok"],"Pacific/Majuro":["Asia/Kamchatka","Pacific/Fiji"],"Pacific/Tongatapu":["Pacific/Apia"],"Asia/Baghdad":["Europe/Minsk","Europe/Moscow"],"Asia/Karachi":["Asia/Yekaterinburg"],"Africa/Johannesburg":["Asia/Gaza","Africa/Cairo"]}},i=function(e){var a=-e.getTimezoneOffset();return null!==a?a:0},r=function(){var a=i(new Date(s.BASELINE_YEAR,0,2)),r=i(new Date(s.BASELINE_YEAR,5,2)),n=a-r;return 0>n?a+",1":n>0?r+",1,"+e:a+",0"},n=function(){var e,a;if("undefined"!=typeof Intl&&"undefined"!=typeof Intl.DateTimeFormat&&(e=Intl.DateTimeFormat(),"undefined"!=typeof e&&"undefined"!=typeof e.resolvedOptions))return a=e.resolvedOptions().timeZone,a&&(a.indexOf("/")>-1||"UTC"===a)?a:void 0},o=function(e){for(var a=new Date(e,0,1,0,0,1,0).getTime(),s=new Date(e,12,31,23,59,59).getTime(),i=a,r=new Date(i).getTimezoneOffset(),n=null,o=null;s-864e5>i;){var t=new Date(i),u=t.getTimezoneOffset();u!==r&&(r>u&&(n=t),u>r&&(o=t),r=u),i+=864e5}return n&&o?{s:A(n).getTime(),e:A(o).getTime()}:!1},A=function l(e,a,i){"undefined"==typeof a&&(a=s.DAY,i=s.HOUR);for(var r=new Date(e.getTime()-a).getTime(),n=e.getTime()+a,o=new Date(r).getTimezoneOffset(),A=r,t=null;n-i>A;){var u=new Date(A),c=u.getTimezoneOffset();if(c!==o){t=u;break}A+=i}return a===s.DAY?l(t,s.HOUR,s.MINUTE):a===s.HOUR?l(t,s.MINUTE,s.SECOND):t},t=function(e,a,s,i){if("N/A"!==s)return s;if("Asia/Beirut"===a){if("Africa/Cairo"===i.name&&13983768e5===e[6].s&&14116788e5===e[6].e)return 0;if("Asia/Jerusalem"===i.name&&13959648e5===e[6].s&&14118588e5===e[6].e)return 0}else if("America/Santiago"===a){if("America/Asuncion"===i.name&&14124816e5===e[6].s&&1397358e6===e[6].e)return 0;if("America/Campo_Grande"===i.name&&14136912e5===e[6].s&&13925196e5===e[6].e)return 0}else if("America/Montevideo"===a){if("America/Sao_Paulo"===i.name&&14136876e5===e[6].s&&1392516e6===e[6].e)return 0}else if("Pacific/Auckland"===a&&"Pacific/Fiji"===i.name&&14142456e5===e[6].s&&13961016e5===e[6].e)return 0;return s},u=function(e,i){for(var r=function(a){for(var r=0,n=0;n=a.rules[n].s&&e[n].e<=a.rules[n].e)){r="N/A";break}if(r=0,r+=Math.abs(e[n].s-a.rules[n].s),r+=Math.abs(a.rules[n].e-e[n].e),r>s.MAX_SCORE){r="N/A";break}}return r=t(e,i,r,a)},n={},o=a.olson.dst_rules.zones,A=o.length,u=s.AMBIGUITIES[i],c=0;A>c;c++){var m=o[c],l=r(o[c]);"N/A"!==l&&(n[m.name]=l)}for(var f in n)if(n.hasOwnProperty(f))for(var d=0;d