JavaScript has a built-in object Date
which stores date and time, and provides methods for their management.
It was based on Java's java.util.Date
class, which was replaced in the early 2010s, but for backwards compatibility, JavaScript's Date
sticks around.
Because of how hard it is to work with Dates in general and because of how bad or non-existing timezone handling is, many libraries exist such as moment.js
, day.js
, date-fns
and luxon
.
None of these are available on Exercism.
In your own projects, do not use a deprecated / unmaintained package such as moment.js
but rely on more modern alternatives like luxon
, or the not yet widely available Temporal.
This exercise focusses on Date
, which will remain relevant until the end of JavaScript.
A Date
object is an instance of the Date
class.
It can be created without passing any arguments to the constructor function.
This results in a Date
object that represents the current date and time:
const now = new Date();
// => Thu Apr 14 2022 11:46:08 GMT+0530 (India Standard Time)
// Shows current day, date and time (in your time zone).
If a number is passed in, this will be interpreted as a timestamp
.
A timestamp is an integer number representing the number of milliseconds that has passed since 1 January 1970 UTC+0.
const epoch = new Date(0);
// Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)
const another = new Date(1749508766627);
// Tue Jun 10 2025 00:39:26 GMT+0200 (Central European Summer Time)
One may expect new Date(0)
to generate the "earliest" date object, but JavaScript will convert the date to your local timezone, which means that only those around GMT / with an UTC+0 timezone will actually get the Unix epoch value.
You can pass a string value representing a date to the Date
constructor.
The only format that is consistent across implementations is the simplified version of the internationally recognized and standardized so-called ISO 8601 timestamp strings.
A moment in time at UTC looks like this:
YYYY-MM-DDTHH:MM:SSZ
YYYYMMDDTHHMMSSZ
Where the following substitutions take place:
Key | Description |
---|---|
YYYY | The calendar year, represented in 4 digits |
MM | The calendar month, represented in 2 digits |
DD | The calendar day, represented in 2 digits |
HH | The hours in a 24-hour clock, 2 digits |
MM | The minutes, 2 digits |
SS | The seconds, 2 digits |
The letter T
separates the date from the time.
The letter Z
indicates UTC (no timezone, no Day Light Savings).
Other formats that are accepted by Date.parse
may or may not work.
When working with Dates in JavaScript, always use an ISO 8601 timestamp when converting from a string
to a Date
.
Date-only forms are allowed, but not all ISO 8601 formats are supported. Consult the simplified version explanation page on MDN.
If the timestamp does not end in Z
, and it does not end with +HH:MM
or -HH:MM
, indicating a timezone offset, because of historical reasons, the following applies:
When the time zone offset is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time. The interpretation as a UTC time is due to a historical spec error that was not consistent with ISO 8601 but could not be changed due to web compatibility. See Broken Parser β A Web Reality Issue.
An existing date object can also be used as a constructor argument.
This makes a copy of the existing Date
object with the same date and time.
const t1 = new Date();
const t2 = new Date(t1);
// Values of t1 and t2 will be the same.
A date representing a date can be created by passing three numbers. A date representing a date and time can be created by passing in 6 numbers.
const date1 = new Date(95, 11, 17);
// Creates Date for Dec 17 1995 00:00 if your local timezone is equivalent to UTC.
const date2 = new Date(2013, 12, 5, 13, 24, 0);
// Creates Date for Jan 5 2014 13:24 if your local timezone is equivalent to UTC.
The second value is the month
, which starts at 0
for January, up to 11
for December.
Date.parse()
You may find mentions of or references to a date parsing function Date.parse
.
Because there are only a few invariants (truths) for this function and because the rest of the implementation is not specified (and thus not standard), one should not use it.
Date
componentsThere are various methods on date objects that return the components of the date:
getFullYear(); // Get the year (4 digits)
getMonth(); // Get the month, from 0 to 11.
getDate(); // Get the day of month, from 1 to 31.
getHours(); // Get the hour in a 24 clock, from 0 to 23
getMinutes(); // Get the minutes, from 0 to 59
getSeconds(); // Get the seconds, from 0 to 59
getMilliseconds(); // Get the milliseconds, from 0 and 999
getDay(); // Get the day of week, from 0 (Sunday) to 6 (Saturday).
Each of these has an applicable set
variant (e.g. setFullYear
) to update the value.
Any overflowing value rolls over to the next component:
const date = new Date('2025-02-28T12:42:00Z');
// => Fri Feb 28 2025 13:42:00 GMT+0100 (Central European Standard Time)
date.setDate(29);
// there was no February 29th in 2025.
date.getDate();
// => 1
date.toString();
// => Sat Mar 01 2025 13:42:00 GMT+0100 (Central European Standard Time)
There are UTC variants for all the methods that disregard the local timezone.
Date objects have a method getTime()
that returns the UNIX timestamp in milliseconds, ie. amount of milliseconds the midnight at the beginning of January 1, 1970, UTC.
Additionally, a method toISOString()
is available to convert from a date object to a ISO 8601 timestamp string.
Greater than (>
) and greater than or equals (>=
) as well as less than (<
) and less than or equals (<=
) can be used directly between two dates or a date and a number.
This works because JavaScript will try to coerce the date to a primitive.
When doing a comparison between two dates or date and a number, JavaScript calls [Symbol.toPrimitive]("number")
which internally calls date.valueOf()
.
The latter is the same as calling date.getTime()
.
If you do not want to rely on this behaviour, convert to a number using getTime()
first.
Dates cannot be compared using equality (==
, and ===
), but the result of .getTime()
can.
In this exercise you will work on some functions in order to manage appointments. The system stores everything in ISO 8601 formatted strings, but that's not how people use the calendar. Various functions are necessary to convert between the various formats.
Create an appointment n
days from now at current time.
The function takes n
days and return the appointment time of n
days from now.
createAppointment(4, now);
// Given now is Sun Oct 05 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
// => Sun Oct 09 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
If the second parameter now
is unused, the current time should be used instead.
Various tools only work with the internationally standardized ISO 8601 format.
Write the function getAppointmentTimestamp
to take a date and return a string in that format.
const appointment = new Date(Date.UTC(2010, 6, 16, 12, 42, 0, 0));
getAppointmentTimestamp(appointment);
// => '2010-07-16T12:42:00.000Z'
Timestamps are hard to read; a function to get the appointment details should help with that.
The function getAppointmentDetails
takes a timestamp in the ISO 8601 format, and returns the year, month, date, hour, and minute.
getAppointmentDetails('2022-04-24T08:15:00.000');
// => { year: 2022, month: 3, date: 24, hour: 8, minute: 15 }
The function will receive first argument as appointment time and second argument of object of some options. You have to update the appointment according to the options in the object and return the new appointment date. The options object could have multiple options.
updateAppointment('2022-02-09T09:20:00.000', { month: 6 });
// => { year: 2022, month: 6, date: 9, hour: 10, minute: 20 }
The function will receive two appointments (timestamps) as arguments. You have to return the difference between those two times in seconds.
Because half a second is almost meaningless, round the number before returning it.
timeBetween('2022-12-12T09:20:00.000', '2022-12-18T08:30:00.000');
// => 515400
Finally, when the appointment is made, the system needs to check if it's valid. In other words, the appointment must be in the future, and not the past.
Write the function isValid
which takes two arguments, an appointment timestamp (string), and the current time as a timestamp (string) and returns true
if the appointment is in the future, given the current time.
isValid('2022-02-11T23:00:00.000', '2022-02-08T23:00:00.000');
// => true
Sign up to Exercism to learn and master JavaScript with 35 concepts, 152 exercises, and real human mentoring, all for free.