简体   繁体   中英

get timezone offset of another timezone in javascript without using Strings

I want to calculate the offset from 'users time' to 'WET/WEST'.

I get the users offset with new Date().getTimezoneOffset() .

But how do I get the offset for WET/WEST So that I can calcluate the combined offset of both?

For example, if the user is in central europe time (CET/CEST), in winter the combined offset would be -60 (CET) + 0 (WET) = -60. In summer, it would be -120 (CEST) + 60 (WEST) = -60. In this case it is always -60 but the user could also have a timezone without DST.

Is this possible without format it to a string and read out the new timezone from that string?

You can't use time zone abbreviations reliably for input, as they can be interpreted in many different ways. For example, CST might be either "Central Standard Time" in North America, or "China Standard Time", or "Cuba Standard Time". While some abbreviations like WET and WEST are unique, many are ambiguous. Refer to the list of time zone abbreviations here .

Instead, you need to know the IANA time zone identifier. One location that uses WET/WEST is Portugal, which as the IANA identifier of "Europe/Lisbon" . You can find a list of identifiers here . Picking the correct identifier is important, as time zones change over time. Each identifier reflects the particular history of each region.

One you know the IANA time zone identifier, then you have options for how to use it:

  1. In some modern browsers that fully support the time zone features of the ECMAScript Internationalization API (ECMA-402) , you can do the following:

     var d = new Date(); var s = d.toLocaleString(undefined, { timeZone: "Europe/Lisbon" })

    This will convert the provided date and time to the correct time zone during formatting. Passing undefined in the first parameter will use the current locale for formatting.

    There are a few downsides to this approach, as it is not yet implemented in all browsers, and there is no API for just retrieving the raw time zone offset of a particular point in time.

  2. You can consider using a library that implements this functionality. I list several of them here . My personal preference is for moment.js with the moment-timezone addon, which you can do the following:

     var m = moment.tz("Europe/Lisbon"); var s = m.format();

    You can pass parameters to the format method to display the output however you like. You can also convert an existing time, such as:

     var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon"); var s = m.format();

    You can also get the offset for a particular moment in time like so:

     var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon"); var offsetInMinutes = m.utcOffset(); var offsetAsString = m.format("Z");
  3. You can write your own code for handling a particular time zone. Though this can be error prone and I don't generally recommend it. Updates can be particularly difficult if you go down this route.

Do also keep in mind that the offset for a particular time zone will vary depending on the date and time in effect. Therefore, new Date() which represents "now" may or may not always be the correct input, depending on your scenario.

I wanted to do this without using a library, so I wrote this function that gives you the timezone offset between the given timezone and utc:

function getTimezoneOffsetFrom(otherTimezone) {
    if (otherTimezone === void 0) { otherTimezone = "Europe/Amsterdam"; }
    var date = new Date();
    function objFromStr(str) {
        var array = str.replace(":", " ").split(" ");
        return {
            day: parseInt(array[0]),
            hour: parseInt(array[1]),
            minute: parseInt(array[2])
        };
    }
    var str = date.toLocaleString(['nl-NL'], { timeZone: otherTimezone, day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
    var other = objFromStr(str);
    str = date.toLocaleString(['nl-NL'], { day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
    var myLocale = objFromStr(str);
    var amsterdamOffset = (other.day * 24 * 60) + (other.hour * 60) + (other.minute);
    var myLocaleOffset = (myLocale.day * 24 * 60) + (myLocale.hour * 60) + (myLocale.minute);
    return myLocaleOffset - amsterdamOffset + date.getTimezoneOffset();
}

Maybe it can be approved by using en-US as a locale string and then the str.replace maybe needs to filter a comma or something.

I wanted to without a library too, but even with moment it has a fixed amount of timezone data so will break after 30 years if you don't keep updating, just erks me a bit. although this does use strings, nothing more complicated than parsing a string which is just an number

function getTimezoneOffset(dt, timezone) {

     let getItem = function(format) {
         format.timeZone = timezone;
         return parseInt(dt.toLocaleString(
            'en-US', format));
     };
    
     let adjDate = new Date(
        getItem({year: 'numeric'}),
        getItem({month: 'numeric'}) - 1, // months are zero based
        getItem({day: 'numeric'}),
        getItem({hour: 'numeric',hour12: false}),
        getItem({minute: 'numeric'}));
     let noSecs = new Date(dt.getTime());
     noSecs.setSeconds(0, 0);
     let diff = Math.round((adjDate.getTime() - noSecs.getTime()) / 60000);
    
     return dt.getTimezoneOffset() - diff;
    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM