How to Handle Time Zones using DateTime and Luxon

Jul 7, 2021 · 5 minutes read · [JavaScript] [TypeScript]

Raise your hand if you ever had issues dealing with time zones or even if you asked about “How to convert a Date object to another timezone in JavaScript”.

In my personal experience, this kind of requirement can become a big problem for developers if the date-handling-related concepts are not clearly understood or the right tools are not used.

Using Dates and Time Zones in JavaScript

Let’s suppose you got a date representation from an external API and you need to convert the date to any desired time zone.

The best option for this is using a representation that meets the ISO 8601 standard. As an example of this, we can set a date like 2021/06/10 02:20:50 in UTC. Then, the standard notation for this date will be 2021-06-10T02:20:50+00:00.

On other hand, the JavaScript language provides a Date object that represents a single moment in time. You can create a Date object in different ways:

let date;
date = new Date(); // Get the current date

date = new Date('2021-06-10T02:20:50+00:00'); // An object representation of given string date

date = new Date(new Date()); // Creates an object representation from another one

Also, we can set a time zone value to any given Date object as follows:

let stringInput = '2021-06-10T02:20:50+00:00';
let timeZone = 'America/Los_Angeles';
const dateObject = new Date(stringInput).toLocaleString('en-US', {
  timeZone,
});

console.log(dateObject); // Prints: 6/9/2021, 7:20:50 PM

The toLocaleString method returns a string with a language-sensitive representation of the Date object. At the same time, this method supports optional arguments where you can configure the time zone. Find more information about this method here.

As you can see, the output date matches the configured time zone(GMT-7). However, we got a string representation of the date and it would be much better if we work with a JavaScript object instead all the time.

Luxon

Luxon is considered as an evolution of Moment.js, a very popular library for date handling in the JavaScript ecosystem.

As the Luxon project says:

Luxon is a powerful, modern, and friendly wrapper for JavaScript dates and times.

Indeed, this library solves most of the common problems related to Date handling:

  • Date internationalization
  • Time zones and Offsets
  • Calendars support
  • Dates Formatting
  • Dates Parsing
  • Dates Math(Add/Subtract days, months, etc)
  • Dates Validation
  • and More…

The DateTime Object

The most important part of the Luxon library is the DateTime object. It can be considered as a wrapper of the native Date object along with a time zone and a locale configuration.

The simplest way of creating a DateTime object is as follows.

import { DateTime } from 'luxon';

let dateTime = DateTime.local();
console.log('Current Date', dateTime.toISO()); // 2021-06-22T21:11:45.638-04:00

The method toISO() will return an ISO 8601-compliant string representation of the DateTime object.

Also, you can create a DateTime in a specific time zone.

// Create a DateTime in a Specific Timezone
let zone = 'America/Denver';
let dateTime = DateTime.fromObject({
  zone,
});
console.log('Current Date', dateTime.toISO()); // 2021-06-22T19:11:45.640-06:00

As you can compare with the previous example, the time output is different because of the use of America/Denver as the time zone.

Of course, there is a way to create a custom date in a specific time zone:

let dateTime = DateTime.fromObject({
  'America/Denver',
}).set({
  day: 1,
  month: 5,
  year: 2021,
});
console.log("Custom date", dateTime.toISO()); //2021-05-01T19:11:45.641-06:00

The set method allows overriding specific properties such as year, month, day, etc.

Converting a DateTime to a different Time Zone

Now let’s suppose we have a DateTime object and we need to convert it to a different time zone.

let dateTime = DateTime.fromObject({
  'America/Denver',
}).set({
  day: 1,
  month: 5,
  year: 2021,
});

// Convert existing date to another Timezone
dateTime = dateTime.setZone("America/La_Paz");
console.log("Custom date, America/La_Paz", dateTime.toISO()); //2021-05-01T21:11:45.641-04:00

Configuring the Default Time Zone

What happens when the whole application needs to run every date in a specific time zone? Just suppose you have defined a configuration within your app to allow the selection of a time zone at any time.

To solve this problem, you don’t need to use the time zone string here and there. The Settings class comes to the rescue:

import { Settings } from 'luxon';

// Configure the time zone
Settings.defaultZoneName = 'America/Denver';

console.log(Settings.defaultZoneName); // Reading the configured time zone.

The defaultZoneName can be used as a set or get method for the default time zone when you’re working with the library.

In the same way, the Settings class contains other methods to configure Luxon’s behavior.

Then, when you’re creating a new DateTime object again, it will take the configured time zone by default

dateTime = DateTime.local();
console.log('Configured defaultZoneName', dateTime.toISO()); //2021-06-22T19:21:54.362-06:00

Pay attention to the offset value, which corresponds now with America/Denver.

Validate a Time Zone

In case you define a user entry point to configure the time zone globally, it is important to validate the text before causing problems with the DateTime objects.

A useful way to do it is through, again, a DateTime object:

const timeZone = 'America/Not_Defined_TZ';
const myDateTime = DateTime.local().setZone(timeZone);
console.log('timeZone valid', myDateTime.isValid); // Prints 'false'

Now try again with a valid time zone, for example, America/Los_Angeles.

Live Demo

Wanna play around with this code? Just open the embedded CodeSandbox editor:

Conclusion

In this article, I described a couple of useful methods to use Luxon for Time Zone handling using either JavaScript or TypeScript. Personally, I consider it a very useful library and it also avoids rewriting and testing your own code for handling dates and time zones, which could save you a lot of time.


Feel free to reach out on Twitter if you have any questions. Follow me on GitHub to see more about my work.

tweet Share