Search justacoding.blog. [Enter] to search. Click anywhere to close.

October 5th, 2021

JavaScript Dates – Working With The Date Object

Working with JavaScript dates is something that most web developers will do at one time or another.

That’s because working with dates and times is very much a standard operation in web development in general. Both on the frontend and on the backend. We’ll often need to access, display or manipulate dates and times as per the requirement of our application.

Essentially, formatting and parsing dates makes up an integral part of the JavaScript developer’s toolkit.

Of course, there are lots of libraries and tools out there to help with this (a particular favourite of mine being date-fns) — however, this article will look specifically at the in-built Date object. We won’t be using any libraries here.

With that in mind, let’s get to the fun stuff. How do JavaScript dates work?

Creating a new date in JavaScript

To create a new date, you can instantiate a new Date object, like so:

const myDate = new Date()

So this simply creates a new instance of JavaScript’s in-built Date object.

It’s worth noting here that there are numerous ways this new date can be instantiated. This is controlled by the options (or arguments) we pass into the object during creation.

As you can see in the example above, we aren’t passing any arguments in. This will default our new date object to now, so the current date and time.

Let’s go over the different sets of arguments we can pass in to our new date object. There are 4 in total for you to consider.

1. Create a new date from a string (not recommended)

It’s possible to create a new date by passing in a string. However, it’s generally not recommended to take this approach. I’ll outline the reasons for this below. For now, though, this is how we’d use a date string to create a new date:

const myDate = new Date("2000-01-10")

Now, we can’t just pass any string here and expect it to work. We need to stick to the required format. In this case, the required format of our date string must conform to ISO 8601.

ISO 8601 format looks as follows:

YYYY-MM-DDTHH:mm:ss.sssZ

So we must adhere to this structure when passing in our string. If we don’t, we’ll simply get an Invalid Date error upon instantiation.

It’s probably clear what the letters and symbols in the ISO 8601 format above represent, but for clarity’s sake, let’s break it down:

// ISO 8601 format
{ year }-{ month }-{ day }
{ T for start of time }{ hours }:{ minutes }:{ seconds }.{ milliseconds }
{ Z for UTC format, otherwise local time if Z is omitted }

The - and : characters are simply delimiters between each portion of the format.

Why this approach isn’t recommended

In short, if you create a new date without the time portion (so you don’t supply the hours and minutes, as a minimum) — you’ll see inconsistent results across different timezones. Without setting the hours and minutes, your returned date will be in UTC format.

So to force a local time date, the hours and minutes must be stipulated when passing a string.

This can be confusing and can lead to otherwise unnecessary bugs or undesired behaviour.

In general, it’s best to just avoid this approach entirely. When working with JavaScript dates, there are better ways to go about creating these objects. We’ll get into these alternative approaches next.

2. Create a new date by passing in various arguments

This approach is a lot more foolproof.

// The 10th of January, 2020 with a time of 12:15:20 
// (and 0 milliseconds, for good measure)
// 0 = January, the months are zero-indexed :)
const myDate = new Date(2020, 0, 10, 12, 15, 20, 00)

There are 7 (optional) arguments you can feed in to the date object here.

If we omit any of the optional arguments, the date portion will “default” to the initial value as appropriate.

Here are a few more examples to better explain what this means:

// The 10th of January, 2020 with a time of 12:00:00
const myDate = new Date(2020, 0, 10, 12)

// The 10th of January, 2020 with a time of 00:00:00
const myDate = new Date(2020, 0, 10)

// The 1st of January, 2020 with a time of 00:00:00
const myDate = new Date(2020, 0)

However, if you supply only one argument, in this case, only the year:

// The 1st of January, 1970 with a time of 01:00:02 (???)
const myDate = new Date(2020)

We’ll get some (seemingly) odd behaviour. That’s because Date thinks we’re passing in a timestamp here.

In JavaScript, a timestamp is the amount of milliseconds elapsed since January the 1st, 1970 (this is known as epoch time in Unix). So as you can see, in our case, it’s setting the date to 2020 milliseconds passed this epoch time. Hence the output!

3. Create a new date by passing in a timestamp

As we’ve just briefly covered, you can see that it’s possible to pass in a timestamp when creating your date.

This may not seem especially useful upon first inspection. And it’s correct to say that generally you won’t be creating dates in this manner.

However, creating dates with timestamps does have it’s uses. In particular, when making date-based comparisons. We’ll go into details on this a little later on.

4. Create a new date with no arguments at all

As with our initial example, we can instantiate a new date object without passing in anything at all. This gives us a date defaulting to the current date and time, or as it’s commonly known, now.

The date will be in local time, as expected.

With that said, now is a good time for us to briefly consider some aspects regarding timezones when working with JavaScript dates in general.

Timezone considerations when working with JavaScript dates

Generally speaking, and in almost every case when working with the various date methods — we’ll receive our JavaScript dates in local time.

timezones - globe
Timezones are always a consideration when working with dates

It’s possible to receive UTC dates in place of this, but that must be specified during creation.

So to keep it fairly brief: just remember that our dates will be in local time. This local time configuration will be retrieved directly from your browser settings.

Formatting JavaScript dates

Surprisingly, it’s not an especially smooth process to format JavaScript dates.

Granted, there are a lot of options out there to handle all of this for you. Libraries and tools to make working with dates generally much easier. However, using JavaScript alone, it’s likely you’ll need to do some “manual” work yourself in order to appropriately format your dates.

Now, there are methods to assist with formatting. These are somewhat useful, but if you rely solely on these methods, you are fairly limited with regards to what formats you can use.

Out of the box JavaScript date formatting options

Here are some examples of the various formatting methods you have at your disposal out of the box:

const myDate = new Date(2020, 0, 10, 12, 15, 20, 00)

// 'Fri Jan 10 2020 12:15:20 GMT+0000 (Greenwich Mean Time)'
myDate.toString()

// 'Fri Jan 10 2020'
myDate.toDateString()

// '10/01/2020, 12:15:20'
myDate.toLocaleString()

// '10/01/2020'
myDate.toLocaleDateString()

// 'Fri, 10 Jan 2020 12:15:20 GMT'
myDate.toGMTString()

// 'Fri, 10 Jan 2020 12:15:20 GMT'
myDate.toUTCString()

// '2020-01-10T12:15:20.000Z'
myDate.toISOString()

So there are some default JavaScript date formatting methods you can use, as demonstrated above. However, it’s fairly likely that you’ll want to use some other, different formats within your own applications.

For those, you’ll need to create custom formats.

Creating your own custom JavaScript date format

JavaScript doesn’t supply a quick and easy, out of the box way to supply your own date format. For that, you’ll need to use a library, as mentioned prior.

It is possible to create your own JavaScript date formats though, it just takes a little bit more work.

Let’s go through how to do this:

const myDate = new Date(2020, 0, 10, 12, 15, 20, 00)

// '10/0/2020'
const formattedDate = `${myDate.getDate()}/${myDate.getMonth()}/
${myDate.getFullYear()}`

As you can see, there are methods you can use on the date object itself to extract the relevant pieces of information that you’ll need. In this case, you can see I’m using getDate, getMonth and getFullYear. There are other methods like this, including ones which retrieve the “time” portion of the date object.

It’s also worth noting there are equivalent set methods for each of these get methods. So for instance you can set the hours on a date object using setHours and so on.

In the example above, I’m extracting the date (10), month (0) and year (2020) in turn.

But wait.. that doesn’t look right?

You’ll notice getMonth() is returning a 0 here. That’s because the months in JavaScript’s Date object are zero-indexed. If we want to display the month of January in an appropriate format (ie. 1, not 0) — we’ll need to manually handle that ourselves.

In this case, it’s as simple as just incrementing the value of getMonth() by 1.

If you want 01 instead of just 1 however, you’d need to “pad” the value manually accordingly:

// 1 => "01"
// 9 => "09"
// 10 => "10"
const pad = (number) => { 
    return (number < 10 ? "0" : "") + number
}

We can do the same thing for any other portions of our date that need padding, for instance the day in the month.

This is what we refer to when we say that working with JavaScript dates (specifically, date formats) requires a little bit more work than expected. You’ll often require these kind of “utility” methods to assist your development process.

I want more date formatting options…

So you may be wondering how you can extract the day of the week, for instance “Friday” from our date object.

There’s no method on the object to specifically do this for us, however, we do have access to the day of the week as an integer:

// 5
myDate.getDay()

This is useful, but there’s no pre-existing mechanism to access “Friday” from this integer. For that, we’ll need to create a mechanism to simply map the days of the week (in a nice human-readable, textual form) to each relevant integer:

const days = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday"
]

Now we can use this map to further format our date to our required format:

// Friday
days[myDate.getDay()]

We can do the exact same kind of mapping for our months:

const months = [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December"
]

And as with the previous example, we can output a “human-readable” month like so:

// January
months[myDate.getMonth()]

A full example – format a complete JavaScript date

Given the above, here’s an example of how we can create a fully formatted JavaScript date using our custom implementation along with the simple pad utility function above:

// '05 (Friday) - January 2020'
const formattedDate = `${pad(myDate.getDay())} (${days[myDate.getDay()]}) - 
${months[myDate.getMonth()]} ${myDate.getFullYear()}`

So as you can see, with some manual intervention, it’s possible to create custom formats when using JavaScript dates. It just takes a little bit of leg work!

Formatting JavaScript times

We can use the same kind of process to appropriately format the date object into whatever time we’d like.

As with the date examples above, methods exist to access the “time” portion of our date object.

Here’s an example:

// '12:15:20'
const formattedTime = `${pad(myDate.getHours())}:${pad(myDate.getMinutes())}:
${pad(myDate.getSeconds())}`

We can obviously combine any pieces together to create a “full” date time representation in our desired format!

Piecing it all together – a function to format JavaScript dates

As the very last example with regards to JavaScript date formatting, let’s create a full implementation with a reusable function:

// we could optionally use an object here to store the day/month names
// and other utility methods (like pad())
// but a basic reusable function may look like so
const toMyCustomFormat = (myDate) => {
    if (Object.prototype.toString.call(myDate) !== '[object Date]') {
        console.error("Invalid date passed!")
        return null
    }
    return `${pad(myDate.getDay())} (${days[myDate.getDay()]}) - 
    ${months[myDate.getMonth()]} ${myDate.getFullYear()}
    ${pad(myDate.getHours())}:
    ${pad(myDate.getMinutes())}:${pad(myDate.getSeconds())}`
}

// 06 (Saturday) - April 2020 00:00:00
toMyCustomFormat(new Date(2020, 3, 4))

// 01 (Monday) - February 2021 13:25:20
toMyCustomFormat(new Date(2021, 1, 8, 13, 25, 20, 45))

There is a lot more you can do here, but this just about wraps up the basics of formatting JavaScript dates.

Now let’s look at how we can compare one date to another.

Comparing JavaScript dates

There may be times when you’ll need to compare two JavaScript dates.

For this, the method that you can use depends on what type of comparison you need.

Check if one date comes before or after another date

This one’s easy, you can just use the relevant operator.

const firstDate = new Date(2020, 3, 10, 12)
const secondDate = new Date(2022, 6, 8, 30)

firstDate < secondDate // true

It’s a little different when you want to check if two dates are equal or not.

Check if two dates are equal

In this case, you’ll need to use the getTime() method on the date objects.

const firstDate = new Date(2020, 3, 10, 12)
const secondDate = new Date(2020, 3, 10, 12)

firstDate === secondDate // false
firstDate.getTime() === secondDate.getTime() // true

That’s because firstDate and secondDate are distinct objects. And as such, when checking for equality, we need to compare the relevant “property” on each object to get the value we are expecting, instead. We don’t want to compare the actual objects themselves.

getTime() returns the number of milliseconds that have passed since epoch time (so the 1st of January, 1970, 00:00:00 UTC). If we compare both of those values, we’d expect the same number for each of our distinct date objects. And as a result of that, our equality check should give the consistent and expected result we are hoping for.

The appropriate use of getTime() is definitely something to look out for when working with JavaScript date comparisons!

In conclusion

In this article we have looked at:

  • Creating dates
  • The impact of timezones when working with dates
  • Formatting dates with existing methods
  • Creating custom JavaScript date formats
  • JavaScript date comparisons and their nuances

With that, we’ll conclude the article. We’ve covered most of the basics with regards to working with JavaScript dates.

Please feel free to check out my other articles on JavaScript if you enjoyed this one.

I’ve also recently written an article specifically on the topic of getting better at JavaScript which may come in handy for some!

Thanks for reading!

Have any questions? Ping me over at @justacodingblog
← Back to blog