How to Handle Time Zones using DateTime and Luxon
Tags: javascript, typescript, webdev
Published: 2021-07-16 00:53:18

Raise your hand if you've ever had issues dealing with time zones, or even if you've asked, "How do I convert a Date object to another time zone 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 have 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](https://en.wikipedia.org/wiki/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:

```js
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:

```js
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString).

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

## Luxon

Luxon is considered an evolution of [Moment.js](https://momentjs.com/docs/#/-project-status/)- a very popular library for date handling in the JavaScript ecosystem.

As the [Luxon project](https://moment.github.io/luxon/) 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 a wrapper of the native `Date` object along with a timezone, and a local configuration.

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

```ts
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.

```ts
// 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:

```ts
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.

```ts
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, instead, comes to the rescue:

```ts
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](https://moment.github.io/luxon/docs/class/src/settings.js~Settings.html) to configure Luxon's behavior.

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

```ts
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:

```ts
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](https://codesandbox.io/s/typescript-luxon-9tq27?file=/src/index.ts) editor:

{% codesandbox typescript-luxon-9tq27 %}

## Conclusion

In this article, I described a couple of useful methods for using 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](https://twitter.com/luixaviles) if you have any questions. Follow me on [GitHub](https://github.com/luixaviles) to see more about my work.

---

_This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit [thisdotlabs.com](https://www.thisdotlabs.com)._

_This Dot Media is focused on creating an inclusive and educational web for all. We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit [thisdot.co](https://www.thisdot.co)._