JS Quiz: 14 Date Time Questions in JavaScript

Gotchas every developer will encounter ✨

updated 12 days ago

quiz (2)
date (1)
gotchas (1)

How well do you know the Date class?

  • Prove your JavaScript skillz! 🚀
  • No login or signup required. ✨
  • Multiple choice. 🤖 … How difficult can it be, eh?

Outline

The Date class in JavaScript has a notoriously difficult API. It was inherited from Java…

This situation leads many developers to use 3rd party libraries without question. While often a safe and reliable choice, these libraries are rarely needed for formatting dates or localization!

This quiz is designed to test (and deepen) your knowledge of the native Date API. Use the green buttons for hints & explanations! Hopefully by the end of the challenge you’ll have solidified your understanding of Date’s in JavaScript.

If you get stuck

  1. Read the Hints (Green button, lower right corner). Some include a few animated answers w/ detailed annotations, while others offer only a few clues. I can’t give away all the answers so easy!
    Seriously though, this is intentional, the answers are there. Skip ahead or try the code snippets out, then change it, and play some more.
  2. Try the code in your browser’s Console (try shortcut F12 on Windows, or Command + Option + J on Mac).
  3. Please feel free to Tweet at me @justsml. I’d love to hear your thoughts!

NOTE: Assume all examples run with GMT-7 timezone offset.

Loading...
A few more seconds...

Date Constructor Part 1

const d1 = new Date(2020, 1, 1)
console.log(d1)

What will the output include?

  • Jan 01 2020
  • Feb 01 2020
  • RangeError: Invalid argument.

The Month argument is zero-based. With a range of 0-11 (using western calendars.)

‘February’ has an index value of one. (Think of it like an array lookup.)

Date Constructor Part 2

const d2 = new Date(2020, 0, 1)
console.log(d2)

What will the output include?

  • Jan 01 2020
  • Feb 01 2020
  • RangeError: Invalid argument.

The Month argument is zero-based. With a range of 0-11 (using western calendars.)

‘January’ has an index value of zero. (Think of it like an array lookup.)

Date Constructor Part 3

const d3 = Date('Thu, 01 Jan 1970 00:00:00 GMT')
console.log(d3)

What will the output include?

  • 01 Jan 1970
  • Unix Epoch of 0
  • Current Date, in UTC/GMT
  • Current Date
  • NaN

This is a common gotcha that’s easy to overlook, even in code review.

A Date instance created with Date([args]) will always return today’s date. In other words, the arguments are ignored. Date('blah') is an alias for new Date().

The missing piece is the new keyword: new Date(dateString).

Date String Parsing

Assume all examples run with GMT-7 timezone offset.

const dateOnlyString = new Date('2020-01-01')
const dateZeroTime   = new Date('2020-01-01T00:00')
console.log(dateOnlyString.getFullYear(), dateZeroTime.getFullYear())

What value will print to the console?

  • 2019 2020
  • 2020 2021
  • 2020 2020
  • 2020 2019

The Date constructor parses date strings using either UTC/GMT or local time.

The trick is knowing if your local timezone will be used… The T00:00 causes it to use UTC/GMT time.

Formatting

Given the following date…

const date = new Date('2020-01-01T00:00')

Select an incorrect formatting method:

  • date.toLocaleFormat('en-US', { timeZone: 'UTC', timeZoneName: 'short' })
  • date.toLocaleDateString('en-US', { timeZone: 'UTC', timeZoneName: 'short' })
  • date.toLocaleTimeString('en-GB', { timeZone: 'UTC' })
  • new Intl.DateTimeFormat('en-US').format(date)

The method Date.toLocaleFormat() is not standard, or well supported.

Before I reach for a 3rd party library, I prefer to use the native toLocaleDateString method. It’s behavior is documented under Intl.DateTimeFormat.

Formatting

const date = new Date(2020)
console.log(date.getFullYear())

What will the output include?

  • 1969
  • 1970
  • 2019
  • 2020
  • 2021

A Date instance cannot be created with a single integer as an argument. It is invalid, and will default to the start of ‘computer time’ (milliseconds since Jan 1st, 1970.)

The reason the answer is not 1970 is because you’d need to use .getUTCFullYear() to get the year without timezone offset (for these questions, GMT-7 is assumed.)

You won’t observe this effect if you live at GMT-0 (or greater than GMT+1.)

UTC Dates Part 1

var date = new Date(Date.UTC(2020, 0, 1))
console.log(date.getUTCFullYear(), date.getFullYear())

What will the output include?

  • 2020 2020
  • 2020 2019
  • 2019 2020
  • 2019 2019

The getFullYear() method is based off a local offset of GMT-07:00. Which means it will give the previous year, as the date is represented locally is Dec 31 2019 17:00:00.

UTC Dates Part 2

const d = Date.UTC(2020, 0, 1)
console.log(d)

What will the output include?

  • A UTC-based date instance
  • A date instance adjusted for local time-zone
  • Milliseconds since Jan 1st, 1970
  • An error

The helper method Date.UTC doesn’t return a date instance. It returns an integer in milliseconds.

UTC Dates Part 3

// Assume local TZ is -07:00
const d = new Date(Date.UTC(2020, 0, 1))
console.log(d.getTimezoneOffset())

What will the output include?

  • 0
  • 420
  • 700
  • 1400
  • null

Date instances do not store original timezone data, at least after it’s been parsed.

Date’s will be implicitly presented in local time, with an unchanging .getTimezoneOffset().

screenshots/timezones-ex1.jpg

Date Setters Part 1

const d = new Date(2020, 0, 1)
d.setDate(1)
console.log(d)

What will the output include?

  • Jan 01 2020
  • Feb 01 2020
  • RangeError: Invalid argument.

The .setDate() method sets the day of the month, based on the given instance’s current month.

If a value is provided outside of the number of days available, the date instance month value will be adjusted (e.g. A setDate(32) in January will calculate as February 1st.)

Date Setters Part 2

const d = new Date(2020, 0, 1)
d.setDate(0)
console.log(d)

What will the output include?

  • Jan 01 2020
  • Jan 00 2020
  • Feb 01 2020
  • Dec 31 2019
  • RangeError: Invalid argument.

The setDate method sets the day of the month, based on the given instance’s current month.

If you invoke setDate(0) the date instance will adjust to the last day of the previous month.

Date Setters Part 3

const d = new Date(2020, 0, 1)
d.setDate(32)
console.log(d)

What will the output include?

  • Jan 01 2020
  • Jan 32 2020
  • Feb 01 2020
  • RangeError: Invalid argument.

If a positive integer is provided to setDate outside of the number of days available, the date instance’s month and day will be adjusted as necessary. (e.g. A setDate(32) in January will calculate as February 1st.)

Date Setters Part 4

const d = new Date(2020, 1, 1)
d.setDate(100)
console.log(d)
  • Jan 01 2020
  • Feb 01 2020
  • May 01 2020
  • May 10 2020
  • RangeError: Invalid argument.

Hint: Setting the date with setDate(X) isn’t the same as adding X days.

Date Setters Part 5

const d = new Date(2020, 1, 1)
d.setDate(100)
d.setDate(-100)
console.log(d)
  • Feb 01 2020
  • Feb -100 2020
  • Jan 21 2020
  • Jan 01 2020
  • RangeError: Invalid argument.

This is perhaps a strange bit of code, and hopefully you don’t find this in your code base.

Every senior developer I’ve shown this to guessed the wrong answer.

Hint: Setting the date with setDate(X) isn’t the same as adding X days. Nor is it the same using negative integers.

screenshots/date-setters.ex1.jpg

Unless otherwise noted, all content is copyright Dan Levy 2014-1019.