Skip to content

Instantly share code, notes, and snippets.

@superdav42
Created September 7, 2018 18:22
Show Gist options
  • Select an option

  • Save superdav42/a8a2428baf1e47f53d97af222c3dd2b1 to your computer and use it in GitHub Desktop.

Select an option

Save superdav42/a8a2428baf1e47f53d97af222c3dd2b1 to your computer and use it in GitHub Desktop.
old timezone detection script
/*
* Original script by Josh Fraser (http://www.onlineaspect.com)
* Continued by Jon Nylander, (jon at pageloom dot com)
* According to both of us, you are absolutely free to do whatever
* you want with this code.
*
* This code is maintained at bitbucket.org as jsTimezoneDetect.
*/
/**
* Namespace to hold all the code for timezone detection.
*/
var jzTimezoneDetector = new Object();
jzTimezoneDetector.HEMISPHERE_SOUTH = 'SOUTH';
jzTimezoneDetector.HEMISPHERE_NORTH = 'NORTH';
jzTimezoneDetector.HEMISPHERE_UNKNOWN = 'N/A';
jzTimezoneDetector.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.
* @param {string} abbreviation - first character of timezone abbreviation.
*/
jzTimezoneDetector.TimeZone = function (offset, olson_tz, uses_dst, abbreviation) {
this.utc_offset = offset;
this.olson_tz = olson_tz;
this.uses_dst = uses_dst;
if(abbreviation) {
this.abbreviation = abbreviation;
}
}
/**
* Prints out the result.
* But before it does that, it calls this.ambiguity_check.
*/
jzTimezoneDetector.TimeZone.prototype.display = function() {
this.ambiguity_check();
var response_text = '<b>UTC-offset</b>: ' + this.utc_offset + '<br/>';
response_text += '<b>Zoneinfo key</b>: ' + this.olson_tz + '<br/>';
response_text += '<b>Zone uses DST</b>: ' + (this.uses_dst ? 'yes' : 'no') + '<br/>';
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.
*/
jzTimezoneDetector.TimeZone.prototype.ambiguity_check = function() {
var local_ambiguity_list = jzTimezoneDetector.olson.ambiguity_list[this.olson_tz];
if (typeof(local_ambiguity_list) == 'undefined') {
return;
}
var length = local_ambiguity_list.length;
for (var i = 0; i < length; i++) {
var tz = local_ambiguity_list[i]
if (jzTimezoneDetector.date_is_dst(jzTimezoneDetector.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}
*/
jzTimezoneDetector.date_is_dst = function (date) {
var base_offset = ( (date.getMonth() > 5 ? jzTimezoneDetector.get_june_offset() : jzTimezoneDetector.get_january_offset()) )
var date_offset = jzTimezoneDetector.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}
*/
jzTimezoneDetector.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}
*/
jzTimezoneDetector.get_timezone_info = function () {
var january_offset = jzTimezoneDetector.get_january_offset();
var june_offset = jzTimezoneDetector.get_june_offset();
var diff = january_offset - june_offset;
var current_offset = jzTimezoneDetector.get_current_offset();
var equal = false;
if(june_offset == current_offset) {
equal = true;
}
if (diff < 0) {
return {'utc_offset' : january_offset,
'dst': 1,
'currentdst': equal,
'hemisphere' : jzTimezoneDetector.HEMISPHERE_NORTH}
}
else if (diff > 0) {
return {'utc_offset' : june_offset,
'dst' : 1,
'currentdst': equal,
'hemisphere' : jzTimezoneDetector.HEMISPHERE_SOUTH}
}
return {'utc_offset' : january_offset,
'dst': 0,
'currentdst': equal,
'hemisphere' : jzTimezoneDetector.HEMISPHERE_UNKNOWN}
}
jzTimezoneDetector.get_current_offset = function () {
return jzTimezoneDetector.get_date_offset(new Date());
}
jzTimezoneDetector.get_january_offset = function () {
return jzTimezoneDetector.get_date_offset(new Date(2011, 0, 1, 0, 0, 0, 0));
}
jzTimezoneDetector.get_june_offset = function () {
return jzTimezoneDetector.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
*/
jzTimezoneDetector.determine_timezone = function () {
var timezone_key_info = jzTimezoneDetector.get_timezone_info();
var hemisphere_suffix = ''
if (timezone_key_info.hemisphere == jzTimezoneDetector.HEMISPHERE_SOUTH) {
hemisphere_suffix = ',s';
}
var tz_key = timezone_key_info.utc_offset + ',' + timezone_key_info.dst + hemisphere_suffix
var tz = jzTimezoneDetector.olson.timezones[tz_key];
var abbreviation;
if(tz.abbreviation) {
abbreviation = tz.abbreviation + (timezone_key_info.currentdst ? 'D': 'S' ) + 'T';
} else {
abbreviation = tz.olson_tz;
}
return {'timezone' : tz, 'key' : tz_key, 'currentdst': timezone_key_info.currentdst, 'abbreviation': abbreviation}
}
/**
* 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.
*/
jzTimezoneDetector.olson.timezones = {
'-720,0' : new jzTimezoneDetector.TimeZone('-12:00','Etc/GMT+12', false),
'-660,0' : new jzTimezoneDetector.TimeZone('-11:00','Pacific/Pago_Pago', false, 'S'),
'-600,1' : new jzTimezoneDetector.TimeZone('-11:00','America/Adak',true, 'H'),
'-660,1,s' : new jzTimezoneDetector.TimeZone('-11:00','Pacific/Apia', true),
'-600,0' : new jzTimezoneDetector.TimeZone('-10:00','Pacific/Honolulu', false, 'H'),
'-570,0' : new jzTimezoneDetector.TimeZone('-10:30','Pacific/Marquesas',false),
'-540,0' : new jzTimezoneDetector.TimeZone('-09:00','Pacific/Gambier',false),
'-540,1' : new jzTimezoneDetector.TimeZone('-09:00','America/Anchorage', true, 'AK'),
'-480,1' : new jzTimezoneDetector.TimeZone('-08:00','America/Los_Angeles', true, 'P'),
'-480,0' : new jzTimezoneDetector.TimeZone('-08:00','Pacific/Pitcairn',false),
'-420,0' : new jzTimezoneDetector.TimeZone('-07:00','America/Phoenix', false, 'M'),
'-420,1' : new jzTimezoneDetector.TimeZone('-07:00','America/Denver', true, 'M'),
'-360,0' : new jzTimezoneDetector.TimeZone('-06:00','America/Guatemala', false, 'C'),
'-360,1' : new jzTimezoneDetector.TimeZone('-06:00','America/Chicago', true, 'C'),
'-360,1,s' : new jzTimezoneDetector.TimeZone('-06:00','Pacific/Easter',true),
'-300,0' : new jzTimezoneDetector.TimeZone('-05:00','America/Bogota', false),
'-300,1' : new jzTimezoneDetector.TimeZone('-05:00','America/New_York', true, 'E'),
'-270,0' : new jzTimezoneDetector.TimeZone('-04:30','America/Caracas', false),
'-240,1' : new jzTimezoneDetector.TimeZone('-04:00','America/Halifax', true),
'-240,0' : new jzTimezoneDetector.TimeZone('-04:00','America/Santo_Domingo', false),
'-240,1,s' : new jzTimezoneDetector.TimeZone('-04:00','America/Asuncion', true),
'-210,1' : new jzTimezoneDetector.TimeZone('-03:30','America/St_Johns', true),
'-180,1' : new jzTimezoneDetector.TimeZone('-03:00','America/Godthab', true),
'-180,0' : new jzTimezoneDetector.TimeZone('-03:00','America/Argentina/Buenos_Aires', false),
'-180,1,s' : new jzTimezoneDetector.TimeZone('-03:00','America/Montevideo', true),
'-120,0' : new jzTimezoneDetector.TimeZone('-02:00','America/Noronha', false),
'-120,1' : new jzTimezoneDetector.TimeZone('-02:00','Etc/GMT+2', true),
'-60,1' : new jzTimezoneDetector.TimeZone('-01:00','Atlantic/Azores', true),
'-60,0' : new jzTimezoneDetector.TimeZone('-01:00','Atlantic/Cape_Verde', false),
'0,0' : new jzTimezoneDetector.TimeZone('00:00','Etc/UTC', false),
'0,1' : new jzTimezoneDetector.TimeZone('00:00','Europe/London', true),
'60,1' : new jzTimezoneDetector.TimeZone('+01:00','Europe/Berlin', true),
'60,0' : new jzTimezoneDetector.TimeZone('+01:00','Africa/Lagos', false),
'60,1,s' : new jzTimezoneDetector.TimeZone('+01:00','Africa/Windhoek',true),
'120,1' : new jzTimezoneDetector.TimeZone('+02:00','Asia/Beirut', true),
'120,0' : new jzTimezoneDetector.TimeZone('+02:00','Africa/Johannesburg', false),
'180,1' : new jzTimezoneDetector.TimeZone('+03:00','Europe/Moscow', true),
'180,0' : new jzTimezoneDetector.TimeZone('+03:00','Asia/Baghdad', false),
'210,1' : new jzTimezoneDetector.TimeZone('+03:30','Asia/Tehran', true),
'240,0' : new jzTimezoneDetector.TimeZone('+04:00','Asia/Dubai', false),
'240,1' : new jzTimezoneDetector.TimeZone('+04:00','Asia/Yerevan', true),
'270,0' : new jzTimezoneDetector.TimeZone('+04:30','Asia/Kabul', false),
'300,1' : new jzTimezoneDetector.TimeZone('+05:00','Asia/Yekaterinburg', true),
'300,0' : new jzTimezoneDetector.TimeZone('+05:00','Asia/Karachi', false),
'330,0' : new jzTimezoneDetector.TimeZone('+05:30','Asia/Kolkata', false),
'345,0' : new jzTimezoneDetector.TimeZone('+05:45','Asia/Kathmandu', false),
'360,0' : new jzTimezoneDetector.TimeZone('+06:00','Asia/Dhaka', false),
'360,1' : new jzTimezoneDetector.TimeZone('+06:00','Asia/Omsk', true),
'390,0' : new jzTimezoneDetector.TimeZone('+06:30','Asia/Rangoon', false),
'420,1' : new jzTimezoneDetector.TimeZone('+07:00','Asia/Krasnoyarsk', true),
'420,0' : new jzTimezoneDetector.TimeZone('+07:00','Asia/Jakarta', false),
'480,0' : new jzTimezoneDetector.TimeZone('+08:00','Asia/Shanghai', false),
'480,1' : new jzTimezoneDetector.TimeZone('+08:00','Asia/Irkutsk', true),
'525,0' : new jzTimezoneDetector.TimeZone('+08:45','Australia/Eucla', true),
'525,1,s' : new jzTimezoneDetector.TimeZone('+08:45','Australia/Eucla', true),
'540,1' : new jzTimezoneDetector.TimeZone('+09:00','Asia/Yakutsk', true),
'540,0' : new jzTimezoneDetector.TimeZone('+09:00','Asia/Tokyo', false),
'570,0' : new jzTimezoneDetector.TimeZone('+09:30','Australia/Darwin', false),
'570,1,s' : new jzTimezoneDetector.TimeZone('+09:30','Australia/Adelaide', true),
'600,0' : new jzTimezoneDetector.TimeZone('+10:00','Australia/Brisbane', false),
'600,1' : new jzTimezoneDetector.TimeZone('+10:00','Asia/Vladivostok', true),
'600,1,s' : new jzTimezoneDetector.TimeZone('+10:00','Australia/Sydney', true),
'630,1,s' : new jzTimezoneDetector.TimeZone('+10:30','Australia/Lord_Howe', true),
'660,1' : new jzTimezoneDetector.TimeZone('+11:00','Asia/Kamchatka', true),
'660,0' : new jzTimezoneDetector.TimeZone('+11:00','Pacific/Noumea', false),
'690,0' : new jzTimezoneDetector.TimeZone('+11:30','Pacific/Norfolk', false),
'720,1,s' : new jzTimezoneDetector.TimeZone('+12:00','Pacific/Auckland', true),
'720,0' : new jzTimezoneDetector.TimeZone('+12:00','Pacific/Tarawa', false),
'765,1,s' : new jzTimezoneDetector.TimeZone('+12:45','Pacific/Chatham', true),
'780,0' : new jzTimezoneDetector.TimeZone('+13:00','Pacific/Tongatapu', false),
'840,0' : new jzTimezoneDetector.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.
*/
jzTimezoneDetector.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.
*/
jzTimezoneDetector.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']
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment