├── .hgignore ├── test ├── recurring_tester.sh ├── run.js ├── test.html └── smoke_tests.sh ├── .hgtags ├── grunt.js ├── package.json ├── bower.json ├── LICENCE.txt ├── README.md ├── jstz.min.js └── jstz.js /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | *~ 3 | *.pyc 4 | .settings 5 | .project 6 | -------------------------------------------------------------------------------- /test/recurring_tester.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | while : 3 | do 4 | clear 5 | node run.js 6 | sleep 1 7 | done -------------------------------------------------------------------------------- /test/run.js: -------------------------------------------------------------------------------- 1 | var jstz = require("../jstz"); 2 | 3 | function determine_current_timezone() { 4 | var tz = jstz.jstz.determine(); 5 | console.log(tz.name()); 6 | } 7 | 8 | determine_current_timezone(); 9 | 10 | -------------------------------------------------------------------------------- /.hgtags: -------------------------------------------------------------------------------- 1 | a9cf858adcd49b888ed4ae8676fa1f667091c0fb stable 2 | a9cf858adcd49b888ed4ae8676fa1f667091c0fb stable 3 | 2f8591e0e0d9e974d0ead54721757871b252b261 stable 4 | 2f8591e0e0d9e974d0ead54721757871b252b261 stable 5 | 7c1b3d7e26ab4cb2b93de09e63d8e239530be4f2 stable 6 | 7c1b3d7e26ab4cb2b93de09e63d8e239530be4f2 stable 7 | 4acc739c3859cd4a6cfc5ea18df90a9a9e01b89e stable 8 | 0aba564fe816811753578e36f3051f24644fc5d8 1.0.4 9 | -------------------------------------------------------------------------------- /grunt.js: -------------------------------------------------------------------------------- 1 | /*global module*/ 2 | module.exports = function (grunt) { 3 | grunt.initConfig({ 4 | pkg: '', 5 | meta: { 6 | banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> */' 7 | }, 8 | lint: { 9 | all: ['jstz.js'] 10 | }, 11 | min: { 12 | dist: { 13 | src: ['','jstz.js'], 14 | dest: 'jstz.min.js' 15 | } 16 | } 17 | }); 18 | 19 | // Default task. 20 | grunt.registerTask('default', 'lint min'); 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jstimezonedetect", 3 | "main": "jstz.js", 4 | "version": "1.0.5", 5 | "description": "This script gives you the zone info key representing your device's time zone setting. The return value is an IANA zone info key (aka the Olson time zone database).", 6 | "homepage": "http://pellepim.bitbucket.org/jstz/", 7 | "keywords": [ 8 | "time", 9 | "timezone", 10 | "tz", 11 | "date" 12 | ], 13 | "maintainers": [ 14 | { 15 | "name": "Jon Nylander", 16 | "web": "http://www.bagonca.com/blog/" 17 | } 18 | ], 19 | "repositories": [ 20 | { 21 | "type": "hg", 22 | "url": "https://bitbucket.org/pellepim/jstimezonedetect" 23 | } 24 | ], 25 | "licenses": [ 26 | { 27 | "type": "MIT", 28 | "url": "https://bitbucket.org/pellepim/jstimezonedetect/src/default/LICENCE.txt" 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jstimezonedetect", 3 | "main": "jstz.js", 4 | "version": "1.0.5", 5 | "description": "This script gives you the zone info key representing your device's time zone setting. The return value is an IANA zone info key (aka the Olson time zone database).", 6 | "homepage": "http://pellepim.bitbucket.org/jstz/", 7 | "keywords": [ 8 | "time", 9 | "timezone", 10 | "tz", 11 | "date" 12 | ], 13 | "ignore": [ 14 | "test", 15 | ".hg*", 16 | "LICENCE.txt", 17 | "README.md", 18 | "grunt.js", 19 | "jstz.min.js", 20 | "package.json" 21 | ], 22 | "maintainers": [ 23 | { 24 | "name": "Jon Nylander", 25 | "web": "http://www.bagonca.com/blog/" 26 | } 27 | ], 28 | "repositories": [ 29 | { 30 | "type": "hg", 31 | "url": "https://bitbucket.org/pellepim/jstimezonedetect" 32 | } 33 | ], 34 | "licenses": [ 35 | { 36 | "type": "MIT", 37 | "url": "https://bitbucket.org/pellepim/jstimezonedetect/src/default/LICENCE.txt" 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /LICENCE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Jon Nylander, project maintained at 4 | https://bitbucket.org/pellepim/jstimezonedetect 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to 11 | do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | This script gives you the zone info key representing your device's time zone setting. 4 | 5 | The return value is an [IANA zone info key][1] (aka the Olson time zone database). 6 | 7 | The IANA timezone database is pretty much standard for most platforms (UNIX and Mac support it natively, and every programming language in the world either has native support or well maintained libraries that support it). 8 | 9 | ## Example Use 10 | 11 | Since version 1.0.4 the [library is hosted on cdnjs.com][10]. I strongly recommend including it from there. 12 | 13 | Invoke the script by calling 14 | 15 | :::javascript 16 | var tz = jstz.determine(); // Determines the time zone of the browser client 17 | tz.name(); // Returns the name of the time zone eg "Europe/Berlin" 18 | 19 | ## Use Case 20 | 21 | The script is useful if you do not want to disturb your users with questions about what time zone they are in. You can rely on this script to give you a key that is usable for server side datetime normalisations across time zones. 22 | 23 | ## Limitations 24 | 25 | This script does not do geo-location, nor does it care very much about historical time zones. 26 | 27 | So if you are unhappy with the time zone "Europe/Berlin" when the user is in fact in "Europe/Stockholm" - this script is not for you. (They are both identical in modern time). 28 | 29 | Also, if it is important to you to know that in Europe/Simferopool (Ukraine) the UTC offset before 1924 was +2.67, sorry, this script will not help you. 30 | 31 | Time zones are a screwed up thing, generally speaking, and the scope of this script is to solve problems concerning modern time zones, in this case from 2010 and forward. 32 | 33 | ## Demo 34 | 35 | There is an updated demo running on: [http://pellepim.bitbucket.org/jstz/][2]. 36 | 37 | ## Contribute? 38 | 39 | If you want to contribute to the project (perhaps fix a bug, or reflect a change in time zone rules), please simply issue a Pull Request. Don't worry about [Grunt][4] builds etc, all you need to modify is the jstz.js file and I'll take care of the testing/minifying etc. 40 | 41 | ## Credits 42 | 43 | Thanks to 44 | 45 | - [Josh Fraser][5] for the original idea 46 | - [Brian Donovan][6] for making jstz CommonJS compliant 47 | - [Ilya Sedlovsky][7] for help with namespacing 48 | - [Jordan Magnuson][9] for adding to cdnjs, documentation tags, and for reporting important issues 49 | 50 | Other contributors: 51 | [Gilmore Davidson][8] 52 | 53 | [1]: http://www.iana.org/time-zones 54 | [2]: http://pellepim.bitbucket.org/jstz/ 55 | [3]: https://bitbucket.org/pellepim/jstimezonedetect/src 56 | [4]: https://github.com/gruntjs/grunt 57 | [5]: http://www.onlineaspect.com/about/ 58 | [6]: https://bitbucket.org/eventualbuddha 59 | [7]: https://bitbucket.org/purebill 60 | [8]: https://bitbucket.org/gdavidson 61 | [9]: https://github.com/JordanMagnuson 62 | [10]: http://cdnjs.com 63 | -------------------------------------------------------------------------------- /test/smoke_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This file is basically the documenation of the timezones that jstz 4 | # can successfully detect. Exluding the ambigous DST zones. 5 | # 6 | # Goes through all basic timezones (not ambiguated) and checks that they 7 | # evaluate correctly. Take note that all russian timezones are excluded 8 | # (even though they still exist in jstz.js to be compliant with computers 9 | # that have not been updated). 10 | # 11 | # Evaluates jstz.js by running it through node.js after having manually changed 12 | # the timezone of the system by copying the timezone to /etc/localtime. 13 | # 14 | 15 | timezones=('Pacific/Pago_Pago' 16 | 'America/Adak' 17 | 'Pacific/Honolulu' 18 | 'Pacific/Marquesas' 19 | 'Pacific/Gambier' 20 | 'America/Anchorage' 21 | 'America/Los_Angeles' 22 | 'Pacific/Pitcairn' 23 | 'America/Phoenix' 24 | 'America/Denver' 25 | 'America/Guatemala' 26 | 'America/Chicago' 27 | 'Pacific/Easter' 28 | 'America/Bogota' 29 | 'America/New_York' 30 | 'America/Caracas' 31 | 'America/Halifax' 32 | 'America/Santo_Domingo' 33 | 'America/Santiago' 34 | 'America/St_Johns' 35 | 'America/Godthab' 36 | 'America/Argentina/Buenos_Aires' 37 | 'America/Montevideo' 38 | 'America/Noronha' 39 | 'Atlantic/Azores' 40 | 'Atlantic/Cape_Verde' 41 | 'UTC' 42 | 'Europe/London' 43 | 'Europe/Berlin' 44 | 'Africa/Lagos' 45 | 'Africa/Windhoek' 46 | 'Asia/Beirut' 47 | 'Africa/Johannesburg' 48 | 'Asia/Baghdad' 49 | 'Asia/Tehran' 50 | 'Asia/Dubai' 51 | 'Asia/Baku' 52 | 'Asia/Kabul' 53 | 'Asia/Karachi' 54 | 'Asia/Kolkata' 55 | 'Asia/Kathmandu' 56 | 'Asia/Dhaka' 57 | 'Asia/Rangoon' 58 | 'Asia/Jakarta' 59 | 'Asia/Shanghai' 60 | 'Australia/Eucla' 61 | 'Asia/Tokyo' 62 | 'Australia/Darwin' 63 | 'Australia/Adelaide' 64 | 'Australia/Brisbane' 65 | 'Australia/Sydney' 66 | 'Pacific/Noumea' 67 | 'Pacific/Norfolk' 68 | 'Pacific/Auckland' 69 | 'Pacific/Tarawa' 70 | 'Pacific/Chatham' 71 | 'Pacific/Tongatapu' 72 | 'Pacific/Apia' 73 | 'Pacific/Kiritimati') 74 | 75 | ambigous_zones=('America/Mazatlan' 76 | 'America/Mexico_City' 77 | 'America/Asuncion' 78 | 'America/Campo_Grande' 79 | 'America/Sao_Paulo' 80 | 'Asia/Gaza' 81 | 'Europe/Helsinki' 82 | 'Asia/Damascus' 83 | 'Asia/Jerusalem' 84 | 'Pacific/Fiji' 85 | 'America/Santa_Isabel' 86 | 'America/Havana' 87 | 'America/Goose_Bay' 88 | 'America/Miquelon' 89 | 'Europe/Moscow' 90 | 'Asia/Yekaterinburg' 91 | 'Asia/Omsk' 92 | 'Asia/Krasnoyarsk' 93 | 'Asia/Irkutsk' 94 | 'Asia/Yakutsk' 95 | 'Asia/Vladivostok' 96 | 'Asia/Kamchatka' 97 | 'Europe/Minsk' 98 | 'Australia/Perth') 99 | 100 | failure_count=0 101 | for tz in "${timezones[@]}" 102 | do 103 | cp "/usr/share/zoneinfo/$tz" "/etc/localtime" 104 | test_result=$(node run.js) 105 | if [[ "$test_result" != "$tz" ]] 106 | then 107 | echo "Failure: $tz wrongly evaluates to $test_result." 108 | failure_count=$((failure_count + 1)) 109 | fi 110 | done 111 | 112 | for tz in "${ambigous_zones[@]}" 113 | do 114 | cp "/usr/share/zoneinfo/$tz" "/etc/localtime" 115 | test_result=$(node run.js) 116 | if [[ "$test_result" != "$tz" ]] 117 | then 118 | echo "Failure: $tz wrongly evaluates to $test_result." 119 | failure_count=$((failure_count +1)) 120 | fi 121 | done 122 | echo "$failure_count failures" 123 | -------------------------------------------------------------------------------- /jstz.min.js: -------------------------------------------------------------------------------- 1 | /*! jsTimezoneDetect - v1.0.5 - 2013-04-01 */ 2 | (function(e){var t=function(){"use strict";var e="s",n=2011,r=function(e){var t=-e.getTimezoneOffset();return t!==null?t:0},i=function(e,t,n){var r=new Date;return e!==undefined&&r.setFullYear(e),r.setDate(n),r.setMonth(t),r},s=function(e){return r(i(e,0,2))},o=function(e){return r(i(e,5,2))},u=function(e){var t=e.getMonth()>7?o(e.getFullYear()):s(e.getFullYear()),n=r(e);return t-n!==0},a=function(){var t=s(n),r=o(n),i=t-r;return i<0?t+",1":i>0?r+",1,"+e:t+",0"},f=function(){var e=a();return new t.TimeZone(t.olson.timezones[e])},l=function(e){var t=new Date(2010,6,15,1,0,0,0),n={"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),"Asia/Beirut":new Date(2011,2,27,1,0,0,0),"Europe/Helsinki":new Date(2011,2,27,4,0,0,0),"Europe/Istanbul":new Date(2011,2,28,5,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),"Asia/Gaza":new Date(2009,2,28,0,30,0,0),"Africa/Cairo":new Date(2009,3,25,0,30,0,0),"Pacific/Auckland":new Date(2011,8,26,7,0,0,0),"Pacific/Fiji":new Date(2010,10,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),"Europe/Moscow":t,"Asia/Yekaterinburg":t,"Asia/Omsk":t,"Asia/Krasnoyarsk":t,"Asia/Irkutsk":t,"Asia/Yakutsk":t,"Asia/Vladivostok":t,"Asia/Kamchatka":t,"Europe/Minsk":t,"Pacific/Apia":new Date(2010,10,1,1,0,0,0),"Australia/Perth":new Date(2008,10,1,1,0,0,0)};return n[e]};return{determine:f,date_is_dst:u,dst_start_for:l}}();t.TimeZone=function(e){"use strict";var n={"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/Beirut","Europe/Helsinki","Europe/Istanbul","Asia/Damascus","Asia/Jerusalem","Asia/Gaza"],"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/Tongatapu":["Pacific/Apia"],"Africa/Johannesburg":["Asia/Gaza","Africa/Cairo"],"Asia/Baghdad":["Europe/Minsk"]},r=e,i=function(){var e=n[r],i=e.length,s=0,o=e[0];for(;s 7, 64 | base_offset = is_southern ? get_june_offset(date.getFullYear()) : 65 | get_january_offset(date.getFullYear()), 66 | date_offset = get_date_offset(date), 67 | is_west = base_offset < 0, 68 | dst_offset = base_offset - date_offset; 69 | 70 | if (!is_west && !is_southern) { 71 | return dst_offset < 0; 72 | } 73 | 74 | return dst_offset !== 0; 75 | }, 76 | 77 | /** 78 | * This function does some basic calculations to create information about 79 | * the user's timezone. It uses REFERENCE_YEAR as a solid year for which 80 | * the script has been tested rather than depend on the year set by the 81 | * client device. 82 | * 83 | * Returns a key that can be used to do lookups in jstz.olson.timezones. 84 | * eg: "720,1,2". 85 | * 86 | * @returns {String} 87 | */ 88 | 89 | lookup_key = function () { 90 | var january_offset = get_january_offset(), 91 | june_offset = get_june_offset(), 92 | diff = january_offset - june_offset; 93 | 94 | if (diff < 0) { 95 | return january_offset + ",1"; 96 | } else if (diff > 0) { 97 | return june_offset + ",1," + HEMISPHERE_SOUTH; 98 | } 99 | 100 | return january_offset + ",0"; 101 | }, 102 | 103 | /** 104 | * Uses get_timezone_info() to formulate a key to use in the olson.timezones dictionary. 105 | * 106 | * Returns a primitive object on the format: 107 | * {'timezone': TimeZone, 'key' : 'the key used to find the TimeZone object'} 108 | * 109 | * @returns Object 110 | */ 111 | determine = function () { 112 | var key = lookup_key(); 113 | return new jstz.TimeZone(jstz.olson.timezones[key]); 114 | }, 115 | 116 | /** 117 | * This object contains information on when daylight savings starts for 118 | * different timezones. 119 | * 120 | * The list is short for a reason. Often we do not have to be very specific 121 | * to single out the correct timezone. But when we do, this list comes in 122 | * handy. 123 | * 124 | * Each value is a date denoting when daylight savings starts for that timezone. 125 | */ 126 | dst_start_for = function (tz_name) { 127 | 128 | 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 :) 129 | dst_starts = { 130 | 'America/Denver': new Date(2011, 2, 13, 3, 0, 0, 0), 131 | 'America/Mazatlan': new Date(2011, 3, 3, 3, 0, 0, 0), 132 | 'America/Chicago': new Date(2011, 2, 13, 3, 0, 0, 0), 133 | 'America/Mexico_City': new Date(2011, 3, 3, 3, 0, 0, 0), 134 | 'America/Asuncion': new Date(2012, 9, 7, 3, 0, 0, 0), 135 | 'America/Santiago': new Date(2012, 9, 3, 3, 0, 0, 0), 136 | 'America/Campo_Grande': new Date(2012, 9, 21, 5, 0, 0, 0), 137 | 'America/Montevideo': new Date(2011, 9, 2, 3, 0, 0, 0), 138 | 'America/Sao_Paulo': new Date(2011, 9, 16, 5, 0, 0, 0), 139 | 'America/Los_Angeles': new Date(2011, 2, 13, 8, 0, 0, 0), 140 | 'America/Santa_Isabel': new Date(2011, 3, 5, 8, 0, 0, 0), 141 | 'America/Havana': new Date(2012, 2, 10, 2, 0, 0, 0), 142 | 'America/New_York': new Date(2012, 2, 10, 7, 0, 0, 0), 143 | 'Europe/Helsinki': new Date(2013, 2, 31, 5, 0, 0, 0), 144 | 'Pacific/Auckland': new Date(2011, 8, 26, 7, 0, 0, 0), 145 | 'America/Halifax': new Date(2011, 2, 13, 6, 0, 0, 0), 146 | 'America/Goose_Bay': new Date(2011, 2, 13, 2, 1, 0, 0), 147 | 'America/Miquelon': new Date(2011, 2, 13, 5, 0, 0, 0), 148 | 'America/Godthab': new Date(2011, 2, 27, 1, 0, 0, 0), 149 | 'Europe/Moscow': ru_pre_dst_change, 150 | 'Asia/Amman': new Date(2013, 2, 29, 1, 0, 0, 0), 151 | 'Asia/Beirut': new Date(2013, 2, 31, 2, 0, 0, 0), 152 | 'Asia/Damascus': new Date(2013, 3, 6, 2, 0, 0, 0), 153 | 'Asia/Jerusalem': new Date(2013, 2, 29, 5, 0, 0, 0), 154 | 'Asia/Yekaterinburg': ru_pre_dst_change, 155 | 'Asia/Omsk': ru_pre_dst_change, 156 | 'Asia/Krasnoyarsk': ru_pre_dst_change, 157 | 'Asia/Irkutsk': ru_pre_dst_change, 158 | 'Asia/Yakutsk': ru_pre_dst_change, 159 | 'Asia/Vladivostok': ru_pre_dst_change, 160 | 'Asia/Baku': new Date(2013, 2, 31, 4, 0, 0), 161 | 'Asia/Yerevan': new Date(2013, 2, 31, 3, 0, 0), 162 | 'Asia/Kamchatka': ru_pre_dst_change, 163 | 'Asia/Gaza': new Date(2010, 2, 27, 4, 0, 0), 164 | 'Africa/Cairo': new Date(2010, 4, 1, 3, 0, 0), 165 | 'Europe/Minsk': ru_pre_dst_change, 166 | 'Pacific/Apia': new Date(2010, 10, 1, 1, 0, 0, 0), 167 | 'Pacific/Fiji': new Date(2010, 11, 1, 0, 0, 0), 168 | 'Australia/Perth': new Date(2008, 10, 1, 1, 0, 0, 0) 169 | }; 170 | 171 | return dst_starts[tz_name]; 172 | }; 173 | 174 | return { 175 | determine: determine, 176 | date_is_dst: date_is_dst, 177 | dst_start_for: dst_start_for 178 | }; 179 | }()); 180 | 181 | /** 182 | * Simple object to perform ambiguity check and to return name of time zone. 183 | */ 184 | jstz.TimeZone = function (tz_name) { 185 | 'use strict'; 186 | /** 187 | * The keys in this object are timezones that we know may be ambiguous after 188 | * a preliminary scan through the olson_tz object. 189 | * 190 | * The array of timezones to compare must be in the order that daylight savings 191 | * starts for the regions. 192 | */ 193 | var AMBIGUITIES = { 194 | 'America/Denver': ['America/Denver', 'America/Mazatlan'], 195 | 'America/Chicago': ['America/Chicago', 'America/Mexico_City'], 196 | 'America/Santiago': ['America/Santiago', 'America/Asuncion', 'America/Campo_Grande'], 197 | 'America/Montevideo': ['America/Montevideo', 'America/Sao_Paulo'], 198 | 'Asia/Beirut': ['Asia/Amman', 'Asia/Jerusalem', 'Asia/Beirut', 'Europe/Helsinki','Asia/Damascus'], 199 | 'Pacific/Auckland': ['Pacific/Auckland', 'Pacific/Fiji'], 200 | 'America/Los_Angeles': ['America/Los_Angeles', 'America/Santa_Isabel'], 201 | 'America/New_York': ['America/Havana', 'America/New_York'], 202 | 'America/Halifax': ['America/Goose_Bay', 'America/Halifax'], 203 | 'America/Godthab': ['America/Miquelon', 'America/Godthab'], 204 | 'Asia/Dubai': ['Europe/Moscow'], 205 | 'Asia/Dhaka': ['Asia/Yekaterinburg'], 206 | 'Asia/Jakarta': ['Asia/Omsk'], 207 | 'Asia/Shanghai': ['Asia/Krasnoyarsk', 'Australia/Perth'], 208 | 'Asia/Tokyo': ['Asia/Irkutsk'], 209 | 'Australia/Brisbane': ['Asia/Yakutsk'], 210 | 'Pacific/Noumea': ['Asia/Vladivostok'], 211 | 'Pacific/Tarawa': ['Asia/Kamchatka', 'Pacific/Fiji'], 212 | 'Pacific/Tongatapu': ['Pacific/Apia'], 213 | 'Asia/Baghdad': ['Europe/Minsk'], 214 | 'Asia/Baku': ['Asia/Yerevan','Asia/Baku'], 215 | 'Africa/Johannesburg': ['Asia/Gaza', 'Africa/Cairo'] 216 | }, 217 | 218 | timezone_name = tz_name, 219 | 220 | /** 221 | * Checks if a timezone has possible ambiguities. I.e timezones that are similar. 222 | * 223 | * For example, if the preliminary scan determines that we're in America/Denver. 224 | * We double check here that we're really there and not in America/Mazatlan. 225 | * 226 | * This is done by checking known dates for when daylight savings start for different 227 | * timezones during 2010 and 2011. 228 | */ 229 | ambiguity_check = function () { 230 | var ambiguity_list = AMBIGUITIES[timezone_name], 231 | length = ambiguity_list.length, 232 | i = 0, 233 | tz = ambiguity_list[0]; 234 | 235 | for (; i < length; i += 1) { 236 | tz = ambiguity_list[i]; 237 | 238 | if (jstz.date_is_dst(jstz.dst_start_for(tz))) { 239 | timezone_name = tz; 240 | return; 241 | } 242 | } 243 | }, 244 | 245 | /** 246 | * Checks if it is possible that the timezone is ambiguous. 247 | */ 248 | is_ambiguous = function () { 249 | return typeof (AMBIGUITIES[timezone_name]) !== 'undefined'; 250 | }; 251 | 252 | if (is_ambiguous()) { 253 | ambiguity_check(); 254 | } 255 | 256 | return { 257 | name: function () { 258 | return timezone_name; 259 | } 260 | }; 261 | }; 262 | 263 | jstz.olson = {}; 264 | 265 | /* 266 | * The keys in this dictionary are comma separated as such: 267 | * 268 | * First the offset compared to UTC time in minutes. 269 | * 270 | * Then a flag which is 0 if the timezone does not take daylight savings into account and 1 if it 271 | * does. 272 | * 273 | * Thirdly an optional 's' signifies that the timezone is in the southern hemisphere, 274 | * only interesting for timezones with DST. 275 | * 276 | * The mapped arrays is used for constructing the jstz.TimeZone object from within 277 | * jstz.determine_timezone(); 278 | */ 279 | jstz.olson.timezones = { 280 | '-720,0' : 'Pacific/Majuro', 281 | '-660,0' : 'Pacific/Pago_Pago', 282 | '-600,1' : 'America/Adak', 283 | '-600,0' : 'Pacific/Honolulu', 284 | '-570,0' : 'Pacific/Marquesas', 285 | '-540,0' : 'Pacific/Gambier', 286 | '-540,1' : 'America/Anchorage', 287 | '-480,1' : 'America/Los_Angeles', 288 | '-480,0' : 'Pacific/Pitcairn', 289 | '-420,0' : 'America/Phoenix', 290 | '-420,1' : 'America/Denver', 291 | '-360,0' : 'America/Guatemala', 292 | '-360,1' : 'America/Chicago', 293 | '-360,1,s' : 'Pacific/Easter', 294 | '-300,0' : 'America/Bogota', 295 | '-300,1' : 'America/New_York', 296 | '-270,0' : 'America/Caracas', 297 | '-240,1' : 'America/Halifax', 298 | '-240,0' : 'America/Santo_Domingo', 299 | '-240,1,s' : 'America/Santiago', 300 | '-210,1' : 'America/St_Johns', 301 | '-180,1' : 'America/Godthab', 302 | '-180,0' : 'America/Argentina/Buenos_Aires', 303 | '-180,1,s' : 'America/Montevideo', 304 | '-120,0' : 'America/Noronha', 305 | '-120,1' : 'America/Noronha', 306 | '-60,1' : 'Atlantic/Azores', 307 | '-60,0' : 'Atlantic/Cape_Verde', 308 | '0,0' : 'UTC', 309 | '0,1' : 'Europe/London', 310 | '60,1' : 'Europe/Berlin', 311 | '60,0' : 'Africa/Lagos', 312 | '60,1,s' : 'Africa/Windhoek', 313 | '120,1' : 'Asia/Beirut', 314 | '120,0' : 'Africa/Johannesburg', 315 | '180,0' : 'Asia/Baghdad', 316 | '180,1' : 'Europe/Moscow', 317 | '210,1' : 'Asia/Tehran', 318 | '240,0' : 'Asia/Dubai', 319 | '240,1' : 'Asia/Baku', 320 | '270,0' : 'Asia/Kabul', 321 | '300,1' : 'Asia/Yekaterinburg', 322 | '300,0' : 'Asia/Karachi', 323 | '330,0' : 'Asia/Kolkata', 324 | '345,0' : 'Asia/Kathmandu', 325 | '360,0' : 'Asia/Dhaka', 326 | '360,1' : 'Asia/Omsk', 327 | '390,0' : 'Asia/Rangoon', 328 | '420,1' : 'Asia/Krasnoyarsk', 329 | '420,0' : 'Asia/Jakarta', 330 | '480,0' : 'Asia/Shanghai', 331 | '480,1' : 'Asia/Irkutsk', 332 | '525,0' : 'Australia/Eucla', 333 | '525,1,s' : 'Australia/Eucla', 334 | '540,1' : 'Asia/Yakutsk', 335 | '540,0' : 'Asia/Tokyo', 336 | '570,0' : 'Australia/Darwin', 337 | '570,1,s' : 'Australia/Adelaide', 338 | '600,0' : 'Australia/Brisbane', 339 | '600,1' : 'Asia/Vladivostok', 340 | '600,1,s' : 'Australia/Sydney', 341 | '630,1,s' : 'Australia/Lord_Howe', 342 | '660,1' : 'Asia/Kamchatka', 343 | '660,0' : 'Pacific/Noumea', 344 | '690,0' : 'Pacific/Norfolk', 345 | '720,1,s' : 'Pacific/Auckland', 346 | '720,0' : 'Pacific/Tarawa', 347 | '765,1,s' : 'Pacific/Chatham', 348 | '780,0' : 'Pacific/Tongatapu', 349 | '780,1,s' : 'Pacific/Apia', 350 | '840,0' : 'Pacific/Kiritimati' 351 | }; 352 | 353 | if (typeof exports !== 'undefined') { 354 | exports.jstz = jstz; 355 | } else { 356 | root.jstz = jstz; 357 | } 358 | })(this); 359 | --------------------------------------------------------------------------------