JavaScript Timezone using Vanilla JavaScript

While many blog posts refer to using third-party libraries to handle timezones in JavaScript, we'll find out how to GET and SET timezones using just Vanilla JavaScript.

I'll also include a cool trick on how to get hours based on the timezone, so keep reading πŸ§‘πŸ½β€πŸ’».

Using Date class

The best and most straightforward way to convert a date to a specific timezone in vanilla js is to use some new Date() methods:

// Returns date and time
new Date('2022-01-01').toLocaleString('en-US', { timeZone: 'Pacific/Funafuti' })
// "1/1/2022, 12:00:00 PM"

// Returns only date
new Date('2022-01-01').toLocaleDateString('en-US', { timeZone: 'Pacific/Funafuti' })
// "1/1/2022"

// Returns only hour
new Date('2022-01-01').toLocaleTimeString('en-US', { timeZone: 'Pacific/Funafuti' })
// "12:00:00 PM"
Get the Date and Time based on Timezone

In this example, new Date() will convert 2022-01-01 from the user timezone to Pacific/Funafuti timezone. However, if we want to convert a date from a specific timezone, we must send a more detailed date to Date constructor.

new Date('Wed Jan 11 2023 06:14:57 GMT+0200').toLocaleString('en-US', { timeZone: 'Pacific/Funafuti' })
// 1/11/2023, 4:14:57 PM
Convert the date to a different timezone

To see how Date works and what other methods it contains, check this MDN documentation page.

Using Intl.DateTimeFormat

Intl.DateTimeFormat is a built-in JavaScript object that allows you to create a date and time formatter. It is part of the ECMAScript Internationalization API, which provides language-sensitive string formatting and parsing.

With Intl.DateTimeFormat, you can define the desired format for a date and time string and then apply that format to a given JavaScript Date object.

const options = { year: 'numeric', month: 'long', day: 'numeric' };
const formatter = new Intl.DateTimeFormat('en-US', options);
const date = new Date();
// January 11, 2023
Format a date with Intl.DateTimeFormat

You can set the time zone for a Intl.DateTimeFormat object by providing a timeZone property in the options object when you create a new instance of the object.

For example, to create a date and time formatter for the Pacific Standard Time (PST) time zone, you can do something like this:

const options = { 
  year: 'numeric', 
  month: 'long', 
  day: 'numeric',
  timeZone : 'America/Los_Angeles' 
const formatter = new Intl.DateTimeFormat('en-US', options);
const date = new Date();
// January 10, 2023

You can give timeZone as an IANA time zones like 'America/Los_Angeles' or 'Asia/Kolkata'.

Please make sure that the time zone you provide is a valid one. The full list of valid time zones is available from the IANA Time Zone Database, which can be found at the following link:

Another way to get the full list of time zones is to use Intl.supportedValuesOf('timeZone') - check this link for more details.

It is important to note that the Date object in JavaScript does not have a time zone associated with it. It represents an instant in time in the form of a number of milliseconds since January 1, 1970, 00:00:00 UTC.

When you display a Date object in a specific time zone using Intl.DateTimeFormat, it will be converted to that time zone, but the underlying value of the Date object is not changed.

When using Intl.DateTimeFormat, it is essential to validate any user input or other external data before passing it to the formatter.

For example, if you are expecting the user to provide a time zone and you're going to use it for formatting, it should be checked for the validity of the time zone and if it is not a valid one then use a default time zone or throw an error.

Overall, Intl.DateTimeFormat is a safe and reliable way to format dates and times in JavaScript, as long as you properly validate any external data before passing it to the formatter.

The cool trick

As I said from the beginning, I'll show you a cool trick about how to get the hours, minutes and seconds from a converted to a specific timezone date.

I'll be short, and include the function straightaway:

function getTimeZoneTime(time: string | Date, timeZone: string | null) {
    // We convert the date to a specific locale time format
    const localeTime = new Date(time).toLocaleTimeString('ro-MD', {timeZone});
    // Use match to get hour, minutes and seconds
    const [hour, minutes, seconds] = localeTime.match(/\d+/gi).map(d => parseInt(d));
    return {hour, minutes, seconds}

I used ro-MD locale as it returns the time in the format I need - 06:39:53, so it's easy for me to match it and get formatted time.

You can use other locales, for example en-US but in this case, you'll have a return of 6:39:53 AM, and the function will return only digits, so you'll need to figure out to get also AM and PM.

This is not a problem actually, you can just check if the returned time includes either AM or PM, or just do another match. In my case, is not necessary so I'll leave ro-MD as it returns the format I need.

If you need more help with how to get AM or PM, ask me in the comments, and I'll come up with a solution for you.

Let's see the result of the function:

// -> {hour: 20, minutes: 55, seconds: 8}
getTimeZoneTime(new Date(), 'America/Los_Angeles')
getTimeZoneTime function

The function returns an object {hour: 20, minutes: 55, seconds: 8} which contains all we need at a specific timezone.

You can still use some third-party libraries to work with dates in javascript, but if you feel you won't use dates heavily in your applications, much better to use solutions like this with just Vanilla JS. This will make your bundle smaller, which is extremely important.