Hướng dẫn nodejs get client timezone

As others have mentioned, getting the client-side browser/OS timezone offset is not available via HTTP, so you need to send this data from the client side.

In my case I have an app that requires login...so I can store a user's preferences. The default is to use browser timezone, but the user can also configure a specific timezone to use all the time instead which is stored in their user profile (e.g. America/Dallas or Europe/Amsterdam).

I don't trust browser time to be correct. The user may have also screwed up their OS timezone setting...so timezone offset may also not be correct. However most modern OSes set timezone automatically based on Geo-IP implied location...so for many users the convenience of being able to travel around the world and login to the app and see date/time in whatever local timezone they happen to be in is worth the effort for the user experience. Users that always want to see a specific timezone can configure that and we will use that preference instead.

The way I do this is the following... on the login form add a hidden field and set the value with javascript. When the user logs in, store this timezone offset in the session. If the user hasn't set a preferred timezone, then we use this offset when rendering date/time. This means that if you have long sessions and a user can travel around between countries...they will still show the old timezone offset until the next logout/login. You can of course get this data more frequently or even on every request if you want...but for my purposes getting this on login is enough. My sessions are expired on IP address change anyway...so yeah. Of course if their session crosses a daylight savings switch then the offset won't be accurate until the next login (assuming their OS/browser TZ is correct in the first place).

Client Side




Note that I multiple it by -1 because I am going to use moment.js for formatting on the express end and the offset is backwards (utc offset from local vs local offset from utc). You could also do this on the server end. You should probably validate this number as well before using it...just minimal example code here.

Server Side

Then on the server side (express) if there is a successful login, I stick that tzOffset value in the session.

Then when formatting dates in express with moment-timezone I can do something like the following. This function is a "formatter" which I can expose to pug/views and then format any random date object with the right timezone/formats for the user.

function formatDateTimeForUser (date) {
    var userTZ,     // user specified TZ like Europe/Berlin
        userTZoffset, // tzOffset we got from login form
        userDateFormat,  // user specified date format (or default)
        userTimeFormat; // user specified time format (or default)

    if (userTZ)
        return moment(date).tz(userTZ).format(userDateFormat+' '+userTimeFormat+' zz');
    else
        return moment(date).utcOffset(userTZoffset).format(userDateFormat+' '+userTimeFormat+' ZZ');
}

The ZZ format is for showing timezone in numeric offset format (relevant when we use a fixed numeric offset from client.

The zz format is for showing timezone in character format (e.g. PDT, PST, EST, etc) which is relevant when we have a timezone like Europe/Berlin instead of a fixed numerical offset.

Another approach

Push raw dates to client and do client-side formatting. Downside is less control and consistency and more js to push to the browser. moment will also run client side if you like.

I just configure my formatters server-side based on user locale and user prefs and then expose those formatters for use in my pug templates in express. So far it works pretty well for me.

Funny Story

I had a co-worker that manually set the wrong timezone on their computer and so the time was wrong. Instead of fixing the timezone they disabled network time and manually set the time to be the "correct" time.

Then they got grumpy when everyone was showing up to meetings they scheduled an hour late.

So yeah...no guarantees the client-side time or timezone offset will be correct.

I've been having this issue for months and I've finally made some headway. I'm writing an app the sends me a message at specific times, 9 am and 9 pm eastern time. When I ran it locally it worked perfectly but when I deploy it, I get nothing. I was messing around and then I saw this Heroku Logs. My guess is that my app is located on a server that is in a different time zone and when this code below runs. The conditions are never met and nothing gets sent. My question now is, is there a way I can get the current time of and compare regardless of what time zone the server is located?

Nội dung chính

  • Return value
  • Description
  • Negative values and positive values
  • Varied results in Daylight Saving Time (DST) regions
  • Using getTimezoneOffset()
  • getTimezoneOffset() and DST
  • getTimezoneOffset() and historical data
  • Specifications
  • Browser compatibility

const sendMessage = require('./sms-api.js');

const send = () =>{

    setInterval(()=>{

        var x = new Date().toLocaleTimeString();
        console.log(x);
    
       if(x === '11:00:10 AM')
       {
           console.log('match');
           return sendMessage('6178032176', 'Good Morning');
       }
       else if(x === '9:50:20 PM')
       {
           console.log('match');
           sendMessage('6178032176', 'Good Evening');
       }
    },1000)
}

send();

asked Jul 24, 2021 at 7:54

When working with different timezones, it is better to work in UTC and then offset it according to required timezone.

Get the time in UTC and then offset it according to required timezone.

You can also use dedicated libraries like moment-timezone.
https://momentjs.com/timezone/docs/

answered Jul 24, 2021 at 8:04

Suyash GaurSuyash Gaur

1,9852 gold badges8 silver badges18 bronze badges

0

Like Suyash said above, your best option is to work entirely in UTC, and only convert when displaying times to users. Rather than dealing with offsets, you can append your dates and times with a 'Z' to indicate they are universal.

The best way I've found to do that is with moment.js and moment-timezone.js. Here is an example of an implementation that will allow you to convert times and dates: https://github.com/aidanjrauscher/browser-timezone-conversions. These libraries also make it very convenient to convert any date or time related user input back from their local time zone to UTC.

answered Jul 24, 2021 at 16:25

thank you for your help. I ended up figuring it out. I used this instead const time = new Date().toLocaleTimeString('en-US', { timeZone: 'America/New_York' });.

answered Mar 26 at 8:11

The getTimezoneOffset() method returns the difference, in minutes, between a date as evaluated in the UTC time zone, and the same date as evaluated in the local time zone.

Nội dung chính

  • Return value
  • Description
  • Negative values and positive values
  • Varied results in Daylight Saving Time (DST) regions
  • Using getTimezoneOffset()
  • getTimezoneOffset() and DST
  • getTimezoneOffset() and historical data
  • Specifications
  • Browser compatibility

Nội dung chính

  • Return value
  • Description
  • Negative values and positive values
  • Varied results in Daylight Saving Time (DST) regions
  • Using getTimezoneOffset()
  • getTimezoneOffset() and DST
  • getTimezoneOffset() and historical data
  • Specifications
  • Browser compatibility

Try it

Syntax

Return value

The difference, in minutes, between the date as evaluated in the UTC time zone and as evaluated in the local time zone. The actual local time algorithm is implementation-defined, and the return value is allowed to be zero in runtimes without appropriate data.

Description

date.getTimezoneOffset() returns the difference, in minutes, between date as evaluated in the UTC time zone and as evaluated in the local time zone — that is, the time zone of the host system in which the browser is being used (if the code is run from the Web in a browser), or otherwise the host system of whatever JavaScript runtime (for example, a Node.js environment) the code is executed in.

Negative values and positive values

The number of minutes returned by getTimezoneOffset() is positive if the local time zone is behind UTC, and negative if the local time zone is ahead of UTC. For example, for UTC+10, -600 will be returned.

Varied results in Daylight Saving Time (DST) regions

In a region that annually shifts in and out of Daylight Saving Time (DST), as date varies, the number of minutes returned by calling getTimezoneOffset() can be non-uniform.

Note: getTimezoneOffset()'s behavior will never differ based on the time when the code is run — its behavior is always consistent when running in the same region. Only the value of date affects the result.

In most implementations, the IANA time zone database (tzdata) is used to precisely determine the offset of the local timezone at the moment of the date. However, if such information is unavailable, an implementation may return zero.

Examples

Using getTimezoneOffset()

// Create a Date instance for the current time
const currentLocalDate = new Date();
// Create a Date instance for 03:24 GMT-0200 on May 1st in 2016
const laborDay2016at0324GMTminus2 = new Date('2016-05-01T03:24:00Z-02:00');
currentLocalDate.getTimezoneOffset() === laborDay2016at0324GMTminus2.getTimezoneOffset();
// true, always, in any timezone that doesn't annually shift in and out of DST
// false, sometimes, in any timezone that annually shifts in and out of DST

getTimezoneOffset() and DST

In regions that use DST, the return value may change based on the time of the year date is in. Below is the output in a runtime in New York, where the timezone is UTC-05:00.

const nyOffsetSummer = new Date('2022-02-01').getTimezoneOffset(); // 300
const nyOffsetWinter = new Date('2022-08-01').getTimezoneOffset(); // 240

getTimezoneOffset() and historical data

Due to historical reasons, the timezone a region is in can be constantly changing, even disregarding DST. For example, below is the output in a runtime in Shanghai, where the timezone is UTC+08:00.

const shModernOffset = new Date('2022-01-27').getTimezoneOffset(); // -480
const shHistoricalOffset = new Date('1943-01-27').getTimezoneOffset(); // -540

This is because during the Sino-Japanese War when Shanghai was under Japanese control, the timezone was changed to UTC+09:00 to align with Japan's (in effect, it was a "year-round DST"), and this was recorded in the IANA database.

Specifications

Specification
ECMAScript Language Specification
# sec-date.prototype.gettimezoneoffset

Browser compatibility

BCD tables only load in the browser

See also