# The definitive guide to JavaScript Dates

> Learn how to work with dates in JavaScript using the Date object, from creating instances with new Date() to milliseconds since 1970 and UNIX timestamps.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2018-07-07 | Updated: 2026-07-18 | Topics: [JavaScript](https://flaviocopes.com/tags/js/) | Canonical: https://flaviocopes.com/javascript-dates/

JavaScript's `Date` object represents one moment in time as milliseconds since January 1, 1970, UTC.

You can use it to create timestamps, read or change date parts, compare moments, and format dates for a locale.

Working with dates can be _complicated_. Time zones and daylight saving time make apparently simple operations tricky.

![Three social media posts from developers complaining about JavaScript date handling being difficult and frustrating](https://flaviocopes.com/images/javascript-dates/Screen_Shot_2018-07-06_at_07.20.58.png)

[JavaScript](https://flaviocopes.com/javascript/) offers date handling through the built-in [`Date` object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date).

## The Date object

A `Date` object instance represents a single point in time.

Despite being named `Date`, it also handles **time**.

It does not store a time zone. Local getter and formatting methods interpret the timestamp using the runtime's current time zone.

## Initialize the Date object

We initialize a Date object by using

```js
new Date()
```

This creates a Date object pointing to the current moment in time.

Internally, dates are expressed in milliseconds since January 1, 1970 at 00:00:00 UTC.

You might be familiar with the UNIX timestamp: that represents the number of _seconds_ that passed since that famous date.

> Important: Unix timestamps are commonly expressed in seconds. JavaScript timestamps use milliseconds.

If we have a UNIX timestamp, we can instantiate a JavaScript Date object by using

```js
const timestamp = 1530826365
new Date(timestamp * 1000)
```

If the timestamp already uses milliseconds, don't multiply it.

Make sure you pass a number:

```js
new Date(Number(timestamp) * 1000)
```

If we pass 0 we'd get a Date object that represents the time at Jan 1st 1970 (UTC):

```js
new Date(0)
```

You can pass a string in JavaScript's standard date-time format:

```js
new Date('2018-07-22T07:22:13Z')
new Date('2018-07-22T07:22:13+02:00')
```

`Z` means UTC. The second example includes an explicit offset from UTC.

Avoid formats such as `07/22/2018` or `July 22, 2018` in data exchanged between systems. Parsing non-standard strings is implementation-dependent and can differ between browsers.

One detail can surprise you:

```js
new Date('2018-07-22') // midnight UTC
new Date('2018-07-22T07:22:13') // local time
```

A date-only standard string is interpreted as UTC. A date and time without an offset is interpreted as local time.

`Date.parse()` accepts the same string format and returns a timestamp in milliseconds:

```js
Date.parse('2018-07-22T07:22:13Z')
```

Read the [MDN `Date.parse()` reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse) before parsing external input.

You can also pass a set of ordered values that represent each part of a date: the year, the month (starting from 0), the day, the hour, the minutes, seconds and milliseconds:

```js
new Date(2018, 6, 22, 7, 22, 13, 0)
new Date(2018, 6, 22)
```

When you pass two or more numeric parameters, JavaScript uses them as local date parts. Omitted parts use defaults:

```js
new Date(2018, 6) //Sun Jul 01 2018 00:00:00 GMT+0200 (Central European Summer Time)
```

Months start at 0, so month 6 is July. Days start at 1.

The numeric component form uses the local time zone. Two computers in different time zones can therefore create different timestamps from the same components.

So, summarizing, you can create a new Date object in 4 ways

- passing **no parameters**, creates a Date object that represents "now"
- passing a **number**, which represents the milliseconds from 1 Jan 1970 00:00 GMT
- passing a **standard date-time string**
- passing **two or more numeric parameters**, which represent local date parts

## Timezones

Include `Z` or a numeric offset in a standard date-time string when the moment must be unambiguous:

```js
new Date('2018-07-22T07:22:13Z')
new Date('2018-07-22T07:22:13+07:00')
```

Don't rely on abbreviations such as `CET` or `EST`. They are not part of the standard date-time string format and can be ambiguous.

## Date conversions and formatting

Given a Date object, there are lots of methods that will generate a string from that date:

```js
const date = new Date('2018-07-22T07:22:13+02:00')

date.toString() // local date and time
date.toTimeString() // local time
date.toUTCString() //"Sun, 22 Jul 2018 05:22:13 GMT"
date.toDateString() // local date
date.toISOString() //"2018-07-22T05:22:13.000Z" (ISO 8601 format)
date.toLocaleString() // localized date and time
date.toLocaleTimeString() // localized time
date.getTime() //1532236933000
```

Locale-formatted output depends on the runtime's locale and time zone. Don't compare it to a hardcoded string.

## The Date object getter methods

A Date object offers several methods to check its value. These depend on the current time zone of the computer.

On a computer using UTC+2, this example returns:

```js
const date = new Date('2018-07-22T07:22:13+02:00')

date.getDate() //22
date.getDay() //0 (0 means sunday, 1 means monday..)
date.getFullYear() //2018
date.getMonth() //6 (starts from 0)
date.getHours() //7
date.getMinutes() //22
date.getSeconds() //13
date.getMilliseconds() //0 (not specified)
date.getTime() //1532236933000
date.getTimezoneOffset() //-120 (the difference from UTC, in minutes)
```

There are equivalent UTC versions of these methods, that return the UTC value rather than the values adapted to your current timezone:

```js
date.getUTCDate() //22
date.getUTCDay() //0 (0 means sunday, 1 means monday..)
date.getUTCFullYear() //2018
date.getUTCMonth() //6 (starts from 0)
date.getUTCHours() //5 (not 7 like above)
date.getUTCMinutes() //22
date.getUTCSeconds() //13
date.getUTCMilliseconds() //0 (not specified)
```

## Editing a date

A Date object offers several methods to edit a date value:

```js
const date = new Date(2018, 6, 22, 7, 22, 13)

date.setDate(newValue)
date.setFullYear(newValue) //note: avoid setYear(), it's deprecated
date.setMonth(newValue)
date.setHours(newValue)
date.setMinutes(newValue)
date.setSeconds(newValue)
date.setMilliseconds(newValue)
date.setTime(newValue)
```

`setMonth()` uses zero-based months, so March is month 2. `setDate()` uses the day of the month, starting at 1.

Example:

```js
const date = new Date(2018, 6, 22, 7, 22, 13)

date.setDate(23)
date.toString() //local time on July 23, 2018 at 07:22:13
```

Fun fact: those methods "overlap", so if you, for example, set `date.setHours(48)`, it will increment the day as well.

Good to know: you can add more than one parameter to `setHours()` to also set minutes, seconds and milliseconds: `setHours(0, 0, 0, 0)` - the same applies to `setMinutes` and `setSeconds`.

Most local setter methods also have a UTC equivalent:

```js
const date = new Date('2018-07-22T05:22:13Z')

date.setUTCDate(newValue)
date.setUTCFullYear(newValue)
date.setUTCMonth(newValue)
date.setUTCHours(newValue)
date.setUTCMinutes(newValue)
date.setUTCSeconds(newValue)
date.setUTCMilliseconds(newValue)
```

## Get the current timestamp

If you want to get the current timestamp in milliseconds, you can use the shorthand

```js
Date.now()
```

instead of

```js
new Date().getTime()
```

## Date values overflow into adjacent units

Pay attention. If you overflow a month with the days count, there will be no error, and the date will go to the next month:

```js
new Date(2018, 6, 40) //local time on August 9, 2018
```

The same goes for months, hours, minutes, seconds and milliseconds.

## Format dates according to the locale

The [Internationalization API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) formats dates for a locale and time zone.

It's exposed by the `Intl` object, which also helps localizing numbers, strings and currencies.

We're interested in `Intl.DateTimeFormat()`.

Here's how to use it.

Format a date according to the computer default locale:

```js
const date = new Date(2018, 6, 22, 7, 22, 13)
new Intl.DateTimeFormat().format(date) //"22/07/2018" in my locale
```

Format a date according to a different locale:

```js
new Intl.DateTimeFormat('en-US').format(date) //"7/22/2018"
```

`Intl.DateTimeFormat` method takes an optional parameter that lets you customize the output. To also display hours, minutes and seconds:

```js
const options = {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
}

new Intl.DateTimeFormat('en-US', options).format(date) //"7/22/2018, 7:22:13 AM"
new Intl.DateTimeFormat('it-IT', options).format(date) //"22/7/2018, 07:22:13"
```

You can also try different options and locales in my free [date formatting tool](https://flaviocopes.com/tools/js-date-format/), which generates the code for you.

## Compare two dates

You can calculate the difference between two dates using `Date.getTime()`:

```js
const date1 = new Date('2018-07-10T07:22:13Z')
const date2 = new Date('2018-07-22T07:22:13Z')
const diff = date2.getTime() - date1.getTime() //difference in milliseconds
```

In the same way you can check if two dates are equal:

```js
const date1 = new Date('2018-07-10T07:22:13Z')
const date2 = new Date('2018-07-10T07:22:13Z')
if (date2.getTime() === date1.getTime()) {
  //dates are equal
}
```

Keep in mind that `getTime()` compares exact moments, including the time.

If you only care about calendar dates, decide which time zone defines that date before resetting or comparing the time. Midnight in one time zone can be the previous day in another.
