JavaScript provides a built-in Date
object that allows you to work with dates and times in your code. The Date
object handles dates similarly to how the Number
and String
objects handle numbers and strings.
One common use case when working with dates in JavaScript is parsing ISO formatted date strings into Date
objects that you can then manipulate. ISO date strings provide a standardized way to represent dates that is widely used in web APIs and other data formats.
In this comprehensive guide, we‘ll cover everything you need to know about converting ISO formatted strings into Date
objects in JavaScript.
What is an ISO Date String?
An ISO date string is a string that represents a date formatted according to the ISO 8601 standard. Some examples:
"2023-02-15T13:30:00Z"
"2023-02-15T13:30:00.000Z"
"20230215"
The ISO 8601 standard lays out specific guidelines for representing dates, times and durations in a consistent machine-readable way. Some key aspects:
- Dates are formatted as
YYYY-MM-DD
- Times include hours, minutes, seconds and fractional seconds
- Timezones are denoted with a
Z
for UTC or an offset like+05:00
- Compact forms without separators are also allowed
Using an ISO formatted string makes it unambiguous what the numbers represent and data from any locale can be consistently parsed.
Why Convert ISO Strings to Date Objects?
There are two main reasons you may want to convert an ISO date string into a JavaScript Date
object:
-
To access built-in date methods: The
Date
object has many useful instance methods likegetTime()
,setFullYear()
, etc that allow you to work with dates. Parsing the ISO string into aDate
gives you access to those helpful methods. -
To display the date in locale format: The
Date
object overrides thetoString()
method to display the date in a locale-appropriate human-readable format. So parsing before display handles the formatting for you.
Some examples of things you can do with a Date
object that you wouldn‘t be able to do with just the raw ISO string:
// Get the year
const date = new Date("2023-05-15T12:30:00Z");
const year = date.getFullYear(); // 2023
// Display in locale format
date.toString(); // "Mon May 15 2023 07:30:00 GMT-0500"
// Calculate difference between dates
const now = new Date();
const diffTime = now - date; // difference in milliseconds
So in summary, converting to a JavaScript Date
object unlocks useful functionality for manipulating dates.
Converting an ISO String to a Date with Date() Constructor
The easiest way to convert an ISO formatted string into a Date
object is to use the Date
constructor and pass the ISO string directly:
new Date(isoString);
For example:
const isoDateStr = "2023-02-15T13:30:00Z";
const date = new Date(isoDateStr);
This creates a new Date
instance using the ISO string and parses it into the underlying date value that the Date
object then wraps.
Some things to note about using the Date
constructor:
- It will automatically parse ISO formatted strings and IS0-like formats
- Other formats like
"02/15/2023"
may be parsed but results can be browser-dependent - Invalid strings will return
Invalid Date
instead of failing - Times without timezone info are treated as local time instead of UTC
Let‘s look at some examples:
// ISO string
new Date("2023-02-01"); // Wed Feb 01 2023 00:00:00 GMT-0800
// ISO-like format
new Date("2023/02/01"); // Wed Feb 01 2023 00:00:00 GMT-0800
// Non-ISO string
new Date("02/01/2023"); // Wed Feb 01 2023 00:00:00 GMT-0800
// Works but browser-dependent
// Invalid date
new Date("2023-02-31"); // Invalid Date
So in summary, the Date
constructor makes it super simple to parse ISO date strings into usable Date
objects in one step.
The rest of this guide will explore some more advanced topics when working with ISO strings and Date
objects in JavaScript.
Dealing with Timezones and UTC Offset
A complexity that arises when parsing ISO date strings is handling differences in timezones and UTC offsets.
For example, consider the string "2023-02-15T13:30:00-05:00"
:
- The date is February 15th, 2023
- The time is 1:30 pm
- The timezone is UTC-5 (EST)
If we parse this into a Date
instance:
new Date("2023-02-15T13:30:00-05:00");
// Wed Feb 15 2023 13:30:00 GMT-0500
// (Eastern Standard Time)
Notice the parsed Date
retains the offset of UTC-5 rather than converting to local system time. This allows us to handle timezone differences predictably.
However, strings without any timezone like "2023-02-15T13:30:00"
are treated as local:
// No timezone defaults to system local time
new Date("2023-02-15T13:30:00");
// Wed Feb 15 2023 13:30:00 GMT-0800
// (Local system Pacific time)
This can trip people up sometimes. To avoid confusion, best practice is to:
- Always use ISO strings with timezones for unambiguous parsing
- Convert dates to UTC if you need to handle multiple timezones
We‘ll look at some examples next.
Converting to UTC Time
A common practice is to parse ISO date strings into Date
instances then convert them to UTC using getTime()
and Date.UTC()
:
const isoStr = "2023-02-15T13:30:00-05:00";
// Parse ISO string
const date = new Date(isoStr);
// Convert to UTC
const utcDate = new Date(Date.UTC(
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds()
));
Now utcDate
represents the same absolute point in time but in the UTC+0 timezone.
Going the opposite way, you can also display a UTC date into a specific timezone using the timezone offset:
// Start with UTC date
const utcDate = new Date(Date.UTC(2023, 1, 15));
// Display as Eastern Standard Time (UTC-5)
const estDate = new Date(
utcDate.getUTCFullYear(),
utcDate.getUTCMonth(),
utcDate.getUTCDate(),
utcDate.getUTCHours() - 5,
utcDate.getUTCMinutes(),
utcDate.getUTCSeconds()
);
estDate.toLocaleString(); // "2/14/2023, 8:00:00 PM"
This converts the UTC date to show the date and time as it would appear in Eastern Standard Time (UTC-5).
Using Timezone Library
Doing timezone calculations manually can get complicated quickly. If you need to handle multiple timezones, it‘s better to use a library like date-fns-tz or timezone-js:
import { zonedTimeToUtc } from "date-fns-tz";
const isoStr = "2023-02-15T13:30:00-05:00";
// Convert ISO string with timezone to UTC
const date = zonedTimeToUtc(isoStr, "America/New_York");
// Or format UTC for a specific timezone
const laDate = formatInTimeZone(date, "America/Los_Angeles", "MM/dd/yyyy HH:mmXXX");
These libraries handle daylight savings, historical data, and other complexities of working across timezones.
Validating ISO Date Strings
When getting ISO date strings from unknown sources, it‘s a good idea to validate them before parsing to catch invalid formats.
For example, consider the string "2023-02-31T13:30:00Z"
. February only goes up to the 28th or 29th day.
If we naively parse this into a Date
:
new Date("2023-02-31T13:30:00Z");
// Invalid Date, silent failure 😞
We just get an invalid Date
instance without any errors. To catch these early, we can use a regex to validate the format first:
// Regex to match YYYY-MM-DD format
const isoDateRegex = /^\d{4}-\d{2}-\d{2}$/;
function isValidIsoDate(str) {
return isoDateRegex.test(str);
}
isValidIsoDate("2023-02-31"); // false, invalid date
isValidIsoDate("2023-02-15"); // true, valid
Here are some other common validations:
Check year range
function isValidYear(year) {
return year >= 1900 && year <= 9999;
}
Check month & day ranges
function isValidMonth(month) {
return month >= 1 && month <= 12;
}
function isValidDay(year, month, day) {
const daysInMonth = new Date(year, month, 0).getDate();
return day >= 1 && day <= daysInMonth;
}
Chaining together different validation checks provides safety before parsing and inserting into databases.
There are also robust validation libraries like validator.js and js-isodate that have battle-tested functions to validate dates, times and ISO 8601 strings.
Alternative Parsing Options
We‘ve mainly looked at the Date
constructor for parsing ISO strings since it‘s simple and built-in. But there are also a couple alternative approaches:
Date.parse()
The Date.parse()
static method can parse an ISO format date string and returns the number of milliseconds since the Unix Epoch (Jan 1, 1970 00:00:00 UTC).
For example:
Date.parse("2023-02-15T13:30:00Z");
// 1676451400000
// Can then construct date from milliseconds
new Date(1676451400000);
The nice part about Date.parse()
is error handling – invalid formats return NaN
rather than failing silently:
Date.parse("2023-02-31"); // NaN
However, support for ISO strings varies across browsers so construction via the Date
constructor is preferable in most cases.
Moment.js Library
For more advanced date wrangling, the Moment.js library provides robust parsing of ISO strings and handy methods like formatting and manipulating dates:
// Parse ISO string
const moment = require(‘moment‘);
const date = moment("2023-02-15T13:30:00Z");
// Format to locale
date.format(‘LLLL‘); // "Wednesday, February 15, 2023 1:30 PM"
// Calculate difference
const now = moment();
now.diff(date, ‘days‘); // 7
In particular, Moment.js handles invalid ISO strings more elegantly by returning an invalid moment object instead of failing.
So in summary, Moment.js is great when doing more complex application logic with dates.
Summary
Working with dates in JavaScript can be tricky, but thankfully ISO 8601 gives us a standardized string format that can be reliably parsed into the built-in Date
object.
We learned:
- ISO strings provide an unambiguous machine-readable date format
- The JavaScript
Date
object handles date manipulation - The Date constructor parses ISO strings automatically
- Timezones should be handled explicitly with UTC conversions
- Validating ISO strings catches errors before parsing
- Alternative parsing options exist like Date.parse() and Moment.js
Converting ISO date strings into Date
instances unlocks the ability to display localized dates, calculate date differences, handle timezones, and leverage other built-in date methods.
ISO date handling is a key skill for any intermediate JavaScript developer. Hopefully this guide gives you confidence working with dates across client and server code! Let me know if you have any other questions.