Converting and Formatting Dates and Time Zones with JavaScript

June 30, 2022
Written by
Reviewed by

Managing times and dates in JavaScript has always been a bit of a mess.

For years, the only recourse for JavaScript developers has been to use incredibly large libraries such as moment-timezone, or the more recent and functional date-fns-tz. Thankfully, browsers and Node.js have stepped up, and now provide standard tools for handling time zones and formatting dates in JavaScript without needing external dependencies. Let’s see these tools in action!

Prerequisites

  • Node.js installed on your machine (version 14 or later)

Basic date functionality in JavaScript

To get started, you’ll need to first create a new JavaScript file. In your terminal or command prompt, navigate to your preferred directory and enter the following:

touch dates.js

This command creates a JavaScript file in your local file system named dates.js. You will use this file and Node.js to edit and run the code samples as you go.

Next, open the dates.js file in your editor, paste in the following code, and be sure to save the modified file:

const now = new Date();
console.log(now.toString());

In the code above, you’re creating a new Date object, converting it to a readable string, and printing it to the console.

Now that your code is ready, you can run it and see the output. Navigate back to your terminal and run the following command:

node dates.js

This command will run the dates.js file and display any logged values in your terminal. In this case, you will see something similar to the following, but dependent on the current date and time in your local time zone:

Wed Jun 22 2022 15:42:50 GMT-0700 (Pacific Daylight Time)

Date includes many more instance methods than just toString(), including methods for getting specific parts of the date or even modifying the date. To see some of these in action, add the following highlighted code:

const now = new Date();
console.log(now.toString());
console.log(now.getMinutes());
console.log(now.getDate());
now.setMonth(0);
now.setMinutes(42);
console.log(now.toString());

Run the code once again with node dates.js, and you will see some interesting results:

Wed Jun 22 2022 17:13:30 GMT-0700 (Pacific Daylight Time)
13
15
Sat Jan 22 2022 17:42:30 GMT-0800 (Pacific Standard Time)

It’s important to note that the time and time zone displayed are dependent on the location settings of the machine that is running the code. If you were to run this same code on a laptop or server in the United Kingdom, for example, you would see a very different output.

You can simulate running this code in another time zone by providing the TZ environment variable. Run the following command in your terminal:

env TZ='Etc/UTC' node dates.js

This command runs your code like before, but with the time zone modified to be UTC. This will result in very different output:

Thu Jun 23 2022 03:13:35 GMT+0000 (Coordinated Universal Time)
18
16
Sun Jan 23 2022 03:42:35 GMT+0000 (Coordinated Universal Time)

The hour, GMT offset, and time zone label are all different, even though this code was run very shortly after the first. Due to the difference between Pacific and UTC, the day even shifted from Wednesday to Thursday.

As you can imagine, this is definitely not a good basis for reliable code across time zones! It is especially important to keep this in mind when deploying projects to remote servers. You’ll often be developing application logic in your development environment in one time zone, but the server that hosts your code will almost invariably be running in UTC (or another time zone).

This gets even more complicated when you want to nicely format your dates and times for display on the web, in an app, or a text message. Sure, you could leverage methods like getDay() and a mapping of day numbers to labels, such as Wednesday, but that is tedious and extra work to maintain.

Problems with native Date objects in JavaScript such as these created the need for utility libraries like date-fns and the now deprecated Moment.js. Fortunately for developers, Node.js now ships with native utilities for handling formatting and time zone adjustments without the need to download any dependencies!

Meet Intl.Utils

Intl is the namespace for the Internationalization API in Node.js, and it contains a wealth of tools for language-sensitive string comparison, number formatting, and date and time formatting. It’s extremely powerful, and in particular, Intl.DateTimeFormat is perfect for handling your date needs natively.

To see this in action, delete the contents of dates.js and replace it with this new code:

const now = new Date();
const formatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  hour12: false,
  minute: 'numeric',
  weekday: 'long',
  timeZone: 'Asia/Tokyo',
});

console.log('Date string: ', now.toString());
console.log('Intl.DateTimeFormat string: ', formatter.format(now));

Run date.js once more and you will see some interesting changes:

Date string:  Wed Jun 22 2022 17:15:19 GMT-0700 (Pacific Daylight Time)
Intl.DateTimeFormat string:  Thursday 09:15

Without modifying your environment variables or adding a dependency, you just converted and formatted your local time to match that of our friends in Japan!

To verify the safety of the time conversion, let’s try to trick your code again by picking a different time zone from your console:

env TZ='Etc/UTC' node dates.js

In spite of your attempted shenanigans, you should see the exact same result for the Intl.DateTimeFormat output (give or take however long it’s been since the last run, of course). Success!

Thu Jun 22 2022 03:15:35 GMT+0000 (Coordinated Universal Time)
Intl.DateTimeFormat string:  Thursday 09:15

Now, it might seem like some information was lost in this new string, but that’s only because of the configuration provided to the formatter. Here, you’ve defined some specific settings:

  • Defining hour: 'numeric' makes sure that the output includes the hour value. You could provide '2-digit' instead of 'numeric', the only difference is that a time such as 3:00am would be returned as '03' instead of just '3'
  • Setting hour12: false ensures that the hour is returned as a number between 0 and 23, in case you want to mess with concepts like AM and PM
  • Including weekday: 'long' ensures that the weekday is included in the output as well, and by its full name, such as 'Monday' or 'Saturday'

This gives you very fine-grained control over how you format your dates and times, on top of the already handy time zone conversion aspect. If you just wanted the day of the week as a label, you could condense the code like so:

const now = new Date();
const formatter = new Intl.DateTimeFormat('en-US', {
  weekday: 'long',
  timeZone: 'Asia/Tokyo',
});

console.log('Intl.DateTimeFormat string: ', formatter.format(now));

Running dates.js once again would give you:

Intl.DateTimeFormat string:  Thursday

As you can imagine, this functionality can really come in handy for focusing your business logic around your intended time zone, perfectly formatting the contents of SMS messages, or making sure dates come across right in your application’s web UI.

A bonus nugget

So far you’ve used Intl.DateTimeFormat to, well, format dates. What about the localization aspect, which is the whole reason this lives under the Intl namespace?

To see some really cool linguistic magic, modify dates.js one more time by replacing its contents with the following:

const now = new Date();
const formatter = new Intl.DateTimeFormat('ja-JP', {
  hour: 'numeric',
  hour12: false,
  weekday: 'long',
  timeZone: 'America/Los_Angeles',
});

console.log('Date in Japanese: ', formatter.format(now));

As you can guess, the next step is to run dates.js yet again!

Depending on the day, you will see something like this as the output:

Date in Japanese:  水曜日 09時

Now you have today’s date localized for Japan, complete with Kanji!

Next Steps

To get a full sense for what’s possible, I encourage you to take a look at the excellent documentation of Intl.DateTimeFormat. To aid you on your journey, it’s also handy to know all the possible time zone strings that could come into play.

I hope that you’ve enjoyed this article and learned something new that could help your current or next project! To expand on your new knowledge and integrate it with Twilio, you could even try your hand at creating a time of day routing app in Twilio Functions.

I’d love to see what you build with this newfound knowledge, no matter the time zone or locale!

Shawn Stern is a Developer Educator at Twilio. Reach out to him at sstern [at] twilio [dot] com if you have a cool JavaScript or TypeScript idea you’d like to share on this blog!