How do I determine the system's Olson zoneinfo in JavaScript?
Asked Answered
S

5

4

I'm interested in retrieving the current zoneinfo string ("America/Los Angeles", "Europe/London", etc.) that the user currently has set for their OS in JavaScript. I've found how to get the current offset in seconds, offsets at specific dates, and less exact time zones (PST, etc.) but not the Olson zoneinfo. Is this possible?

Sr answered 3/3, 2009 at 22:9 Comment(0)
H
3

I worked on this very issue a couple of months back and the result is this: http://site.pageloom.com/automatic-timezone-detection-with-javascript. The script will not give you the most precise result possible. For example, it will return Europe/Berlin regardless of where in the Central European timezone you are.

Basically all it does it check for known dates when daylight saving transitions take place.

Hopefully it will help.

Homeric answered 21/8, 2011 at 19:8 Comment(0)
C
2

See fleegix.js's date.Date plugin. You can probably hack out just the parts you need:

  function getRegionForTimezone(tz) {
    var exc = regionExceptions[tz];
    if (exc) {
      return exc;
    }
    else {
      reg = tz.split('/')[0];
      return regionMap[reg];
    }
  }
Cytokinesis answered 3/3, 2009 at 22:22 Comment(0)
S
1

Nope. Sorry! You might be able to get it via a Java applet using TimeZone, but from JavaScript all you have is the offset from UTC. (Guessing from the timezone name isn't reliable as the names are locale-dependent. You could detect a few common cases by matching with the UTC offset, perhaps, but it'd be a lot of work.)

Generally if you want to support timezones to a level as fine-grained as Olson you'd give the user an explicit selectable timezone control.

Shoe answered 3/3, 2009 at 22:20 Comment(0)
N
1

I made a bit simpler script using some ideas of Jon Nylander's awesome detector (which is based on script by Josh Fraser, http://www.onlineaspect.com ). Nylander's script (as well as it's jQuery counterpart in https://github.com/scottwater/jquery.detect_timezone ) uses ambiquities list and DST start times are as local times. My script has only one list and all the dates are in UTC to make it easy to add or modify timezones, if needed.

Usage:
- Save as .js and include in html header section
- Call get_timezone_id() and user's timezone is returned eg. "Europe/Helsinki"

This script can detect 90 timezones, but if you need more, you have to use GeoLocation API or some server side library (geoIP). Depending on purpose, consider also adding user selectable list of timezones.

Also note that because we don't know how future browsers and systems preserve transition data of year 2011, may be some tweaks have to be done some day in the future. (I tested dates on 1970-80 and the results varied greatly across browsers in the same system(!)) But luckily year 2011 has gone, and nearly all the systems in the world have hopefully updated their tz-databases and the detection should be pretty good now.

/*
This script (Javascript Timezone Detection) detects Olson timezone  
ID of user's system's timezone using getTimezoneOffset(). Detection
is tested and passed 100% in the following conditions:

* Windows 7,Opera 11.00
* Windows 7,Firefox 3.6.13
* Windows 7,Safari 5.0.3
* Windows 7,Google Chrome 8.0.552.237
* Windows 7,Internet Explorer 8.0.7600.16385

* Mac OS X,Google Chrome 8.0.552.237
* Mac OS X,Firefox 3.6.13
* Mac OS X,Opera 11.01
* Mac OS X,Safari Version 5.0.3

* Centos 5,Firefox 3.6.13
* Centos 5,Safari
* Centos 5,Opera 11.00

The script has ability to detect 90 timezones.

Every row in zones-array consist of
0: Olson timezone ID,
1-6: Transition start time in UTC (usually summer time start and sometimes winter time start) 
7: Utc offset in minutes
8: 1 = has transition,0 = has not transition


Timezones are listed in zones-array this way:  
- first comes section of timezones, that have transitions and then section of timezones that have no transitions  
- Both sections are then ordered by offset  
- Finally the has transitions section is ordered by the transition start time.    
If you add more timezones or replaces some, please be sure to maintain this order, otherwise the detection fails in some cases.

Minified size: about 4.46KB  
*/    
var zones = new Array(
// FIRST DST TIMEZONES
    [ 'Pacific/Apia',                    2011,3,3,11,0,0,      -660, 1 ]/* For Opera Linux. Unexpectedly winter-offset. */,

    [ 'Pacific/Apia',                    2010,8,26,11,0,0,     -600, 1 ]/* STD: -660 */,

    [ 'America/Adak',                    2011,2,13,12,0,0,     -540, 1 ]/* STD: -600 */,

    [ 'America/Anchorage',               2011,2,13,11,0,0,     -480, 1 ]/* STD: -540 */,

    [ 'America/Los_Angeles',             2011,2,13,10,0,0,     -420, 1 ]/* STD: -480 */,
    [ 'America/Santa_Isabel',            2011,3,3,10,0,0,      -420, 1 ]/* STD: -480 */,

    [ 'America/Denver',                  2011,2,13,9,0,0,      -360, 1 ]/* STD: -420 */,
    [ 'America/Mazatlan',                2011,3,3,9,0,0,       -360, 1 ]/* STD: -420 */,

    [ 'America/Chicago',                 2011,2,13,8,0,0,      -300, 1 ]/* STD: -360 */,
    [ 'America/Mexico_City',             2011,3,3,8,0,0,       -300, 1 ]/* STD: -360 */,
    [ 'Pacific/Easter',                  2011,9,9,4,0,0,       -300, 1 ]/* STD: -360 */,

    [ 'America/Havana',                  2011,2,13,5,0,0,      -240, 1 ]/* STD: -300 */,
    [ 'America/New_York',                2011,2,13,7,0,0,      -240, 1 ]/* STD: -300 */,

    [ 'America/Goose_Bay',               2011,2,13,4,1,0,      -180, 1 ]/* STD: -240 */,
    [ 'America/Halifax',                 2011,2,13,6,0,0,      -180, 1 ]/* STD: -240 */,
    [ 'Atlantic/Stanley',                2011,8,4,6,0,0,       -180, 1 ]/* STD: -240 */,
    [ 'America/Asuncion',                2011,9,2,4,0,0,       -180, 1 ]/* STD: -240 */,
    [ 'America/Santiago',                2011,9,9,4,0,0,       -180, 1 ]/* STD: -240 */,
    [ 'America/Campo_Grande',            2011,9,16,4,0,0,      -180, 1 ]/* STD: -240 */,

    [ 'America/St_Johns',                2011,2,13,3,31,0,     -150, 1 ]/* STD: -210 */,

    [ 'America/Miquelon',                2011,2,13,5,0,0,      -120, 1 ]/* STD: -180 */,
    [ 'America/Godthab',                 2011,2,27,1,0,0,      -120, 1 ]/* STD: -180 */,
    [ 'America/Montevideo',              2011,9,2,5,0,0,       -120, 1 ]/* STD: -180 */,
    [ 'America/Sao_Paulo',               2011,9,16,3,0,0,      -120, 1 ]/* STD: -180 */,

    [ 'Atlantic/Azores',                 2011,2,27,1,0,0,      0, 1 ]/* STD: -60 */,
    [ 'Atlantic/Azores',                 2010,2,28,3,0,0,      0, 1 ], /* Windows fix */

    [ 'Europe/London',                   2011,2,27,1,0,0,      60, 1 ]/* STD: 0 */,

    [ 'Europe/Berlin',                   2011,2,27,1,0,0,      120, 1 ]/* STD: 60 */,
    [ 'Africa/Windhoek',                 2011,8,4,1,0,0,       120, 1 ]/* STD: 60 */,

    [ 'Asia/Gaza',                       2011,2,25,22,1,0,     180, 1 ]/* STD: 120 */,
    [ 'Asia/Beirut',                     2011,2,26,22,0,0,     180, 1 ]/* STD: 120 */,
    [ 'Europe/Minsk',                    2011,2,27,0,0,0,      180, 1 ]/* STD: 120 */,
// Istanbul and Helsinki are the same, please select which one to use
//  [ 'Europe/Istanbul',                 2011,2,27,1,0,0,      180, 1 ]/* STD: 120 */,
    [ 'Europe/Helsinki',                 2011,2,27,1,0,0,      180, 1 ]/* STD: 120 */,
    [ 'Asia/Jerusalem',                  2011,3,1,0,0,0,       180, 1 ]/* STD: 120 */,
    [ 'Africa/Cairo',                    2011,3,28,22,0,0,     180, 1 ]/* STD: 120 */,
    [ 'Asia/Damascus',                   2011,9,27,21,0,0,     120, 1 ]/* Unexpectedly here winter-offset */,
    [ 'Asia/Amman',                      2011,9,27,22,0,0,     120, 1 ]/* Unexpectedly here winter-offset */,

    [ 'Europe/Moscow',                   2011,2,26,23,0,0,     240, 1 ]/* STD: 180 */,

    [ 'Asia/Tehran',                     2009,2,21,20,30,0,    270, 1 ]/* STD: 210 */,

    [ 'Asia/Yerevan',                    2011,2,26,22,0,0,     300, 1 ]/* STD: 240 */,
    [ 'Asia/Baku',                       2011,2,27,0,0,0,      300, 1 ]/* STD: 240 */,

    [ 'Asia/Yekaterinburg',              2011,2,26,21,0,0,     360, 1 ]/* STD: 300 */,

    [ 'Asia/Omsk',                       2011,2,26,20,0,0,     420, 1 ]/* STD: 360 */,

    [ 'Asia/Krasnoyarsk',                2011,2,26,19,0,0,     480, 1 ]/* STD: 420 */,

    [ 'Asia/Irkutsk',                    2011,2,26,18,0,0,     540, 1 ]/* STD: 480 */,

    [ 'Asia/Yakutsk',                    2011,2,26,17,0,0,     600, 1 ]/* STD: 540 */,

    [ 'Australia/Adelaide',              2011,9,1,16,30,0,     630, 1 ]/* STD: 570 */,

    [ 'Asia/Vladivostok',                2011,2,26,16,0,0,     660, 1 ]/* STD: 600 */,
    [ 'Australia/Lord_Howe',             2011,9,1,15,30,0,     660, 1 ]/* STD: 630 */,
    [ 'Australia/Sydney',                2011,9,1,16,0,0,      660, 1 ]/* STD: 600 */,

    [ 'Pacific/Fiji',                    2011,2,5,14,0,0,      720, 1 ]/* STD: 660 */,
    [ 'Pacific/Fiji',                    2011,2,26,14,0,0,     720, 1 ]/* STD: 660 */,
    [ 'Asia/Kamchatka',                  2011,2,26,15,0,0,     720, 1 ]/* STD: 660 */,

    [ 'Pacific/Auckland',                2011,8,24,14,0,0,     780, 1 ]/* STD: 720 */,

    [ 'Pacific/Chatham',                 2011,8,24,14,0,0,     825, 1 ]/* STD: 765 */,

// AND THEN NON-DST TIMEZONES: 

    [ 'Etc/GMT+12',                      2011,0,1,0,0,0,       -720, 0 ]/* STD: -720 */,

    [ 'Pacific/Pago_Pago',               2011,0,1,0,0,0,       -660, 0 ]/* STD: -660 */,

    [ 'Pacific/Kiritimati',              2010,0,1,0,0,0,        840, 0, '(LINT)' ], /* To prevent Firefox detecting Pacific/Kiritimati as Pacific Honolulu */
    [ 'Pacific/Honolulu',                2011,0,1,0,0,0,       -600, 0 ]/* STD: -600 */,

    [ 'Pacific/Marquesas',               2011,0,1,0,0,0,       -570, 0 ]/* STD: -570 */,

    [ 'Pacific/Gambier',                 2011,0,1,0,0,0,       -540, 0 ]/* STD: -540 */,

    [ 'Pacific/Pitcairn',                2011,0,1,0,0,0,       -480, 0 ]/* STD: -480 */,

    [ 'America/Phoenix',                 2011,0,1,0,0,0,       -420, 0 ]/* STD: -420 */,

    [ 'America/Guatemala',               2011,0,1,0,0,0,       -360, 0 ]/* STD: -360 */,

    [ 'America/Bogota',                  2011,0,1,0,0,0,       -300, 0 ]/* STD: -300 */,

    [ 'America/Caracas',                 2011,0,1,0,0,0,       -270, 0 ]/* STD: -270 */,

    [ 'America/Santo_Domingo',           2011,0,1,0,0,0,       -240, 0 ]/* STD: -240 */,

    [ 'America/Argentina/Buenos_Aires',  2011,0,1,0,0,0,       -180, 0 ]/* STD: -180 */,

    [ 'America/Noronha',                 2011,0,1,0,0,0,       -120, 0 ]/* STD: -120 */,

    [ 'Atlantic/Cape_Verde',             2011,0,1,0,0,0,       -60, 0 ]/* STD: -60 */,

    [ 'Africa/Casablanca',               2011,0,1,0,0,0,       0, 0 ]/* STD: 0 */,

    [ 'Africa/Lagos',                    2011,0,1,0,0,0,       60, 0 ]/* STD: 60 */,

    [ 'Africa/Johannesburg',             2011,0,1,0,0,0,       120, 0 ]/* STD: 120 */,

    [ 'Asia/Baghdad',                    2011,0,1,0,0,0,       180, 0 ]/* STD: 180 */,

    [ 'Asia/Dubai',                      2011,0,1,0,0,0,       240, 0 ]/* STD: 240 */,

    [ 'Asia/Kabul',                      2011,0,1,0,0,0,       270, 0 ]/* STD: 270 */,

    [ 'Asia/Karachi',                    2011,0,1,0,0,0,       300, 0 ]/* STD: 300 */,

    [ 'Asia/Kolkata',                    2011,0,1,0,0,0,       330, 0 ]/* STD: 330 */,

    [ 'Asia/Kathmandu',                  2011,0,1,0,0,0,       345, 0 ]/* STD: 345 */,

    [ 'Asia/Dhaka',                      2011,0,1,0,0,0,       360, 0 ]/* STD: 360 */,

    [ 'Asia/Rangoon',                    2011,0,1,0,0,0,       390, 0 ]/* STD: 390 */,

    [ 'Asia/Jakarta',                    2011,0,1,0,0,0,       420, 0 ]/* STD: 420 */,

    [ 'Asia/Shanghai',                   2011,0,1,0,0,0,       480, 0 ]/* STD: 480 */,

    [ 'Australia/Eucla',                 2011,0,1,0,0,0,       525, 0 ]/* STD: 525 */,

    [ 'Asia/Tokyo',                      2011,0,1,0,0,0,       540, 0 ]/* STD: 540 */,

    [ 'Australia/Darwin',                2011,0,1,0,0,0,       570, 0 ]/* STD: 570 */,

    [ 'Australia/Brisbane',              2011,0,1,0,0,0,       600, 0 ]/* STD: 600 */,

    [ 'Pacific/Noumea',                  2011,0,1,0,0,0,       660, 0 ]/* STD: 660 */,

    [ 'Pacific/Norfolk',                 2011,0,1,0,0,0,       690, 0 ]/* STD: 690 */,

    [ 'Pacific/Tarawa',                  2011,0,1,0,0,0,       720, 0 ]/* STD: 720 */,

    [ 'Pacific/Tongatapu',               2011,0,1,0,0,0,       780, 0 ]/* STD: 780 */,

    [ 'Pacific/Kiritimati',              2011,0,1,0,0,0,       840, 0 ]/* STD: 840 */
)

function get_timezone_id()
{
    var tz="";
    for (var i in zones)
    {
        olson_name = zones[i][0];
        has_transitions = zones[i][8];

        date_1 = new Date(Date.UTC(zones[i][1],zones[i][2],zones[i][3],zones[i][4],zones[i][5],zones[i][6]));
        date_1_offset_data = zones[i][7];
        date_1_offset_user = -date_1.getTimezoneOffset();

        date_2 = new Date(Date.UTC(zones[i][1],zones[i][2],zones[i][3],zones[i][4],zones[i][5],zones[i][6]) - 1000);
        date_2_offset_user = -date_2.getTimezoneOffset();

        var patt1=/\([^)]+\)/g;
        if (zones[i][9] != undefined) var abbr = zones[i][9]; // To determine Pacific/Kiritimati in Firefox
        else var abbr = "";

        if
        (   
            abbr == date_1.toString().match(patt1)
            // Detect timezones that has transitions
            || (has_transitions &&  date_1_offset_user == date_1_offset_data && date_2_offset_user != date_1_offset_data)
            // Detect timezones that has not transitions
            || (!has_transitions && date_1_offset_data == date_1_offset_user)
        )
        {
            tz = olson_name;
            return tz;
        }
    }
}
Nibbs answered 1/10, 2012 at 23:18 Comment(0)
S
0

You'd have to set up an array or hash of the zoneinfo data in Javascript and determine the name based on the time you pick up.

Setting answered 3/3, 2009 at 22:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.