Master the art of handling time in JavaScript with this guide to creating, formatting, and calculating time data using the powerful Date object and custom extensions.
The Date object in JavaScript provides numerous options for calculating and outputting date and time information. The point of origin for the Date object is January 1, 1970, at 00:00 Greenwich Mean Time (GMT), although today, we use Coordinated Universal Time (UTC). Date objects had negative values before that point in time and positive values afterward. The times are calculated in milliseconds.
In this section, you’ll see various options for creating a new Date object:
The numbering of months starts at 0, which is why there are values from 0 (January) to 11 (December). If you enter a parameter with a value that is too large or too small, it will automatically be converted (e.g., January 32 becomes February 1).
Here’s the program:
...
<body><p>
<script>
const timeA = new Date();
document.write("Current date: " + timeA + "<br>");
const timeB = new Date(2024, 6, 10);
document.write("Date from day, month, year: " + timeB + "<br>");
const timeC = new Date(2024, 6, 10, 17, 8, 3);
document.write("Hour, minute, second in addition: " + timeC + "<br>");
const timeD = new Date(2024, 1, 30, 17, 68, -3);
document.write("From values for conversion: " + timeD + "<br>");
const timeE = new Date(2 * 60 * 1000);
document.write("Date from milliseconds: " + timeE + "<br>");
const timeF = new Date(-1.5 * 24 * 60 * 60 * 1000);
document.write("Negative value: " + timeF);
</script></p>
</body></html>
The result is shown in this figure.
The Date objects created are output in the default format, which contains the abbreviated English name of the day of the week and the month, as well as the day of the month, the year, and the time. Further output options can be found in the next section.
GMT+0100 means that the local time is one hour ahead of GMT, due to a time difference of one hour compared to London-Greenwich. In the case of a further time difference of one hour due to daylight saving time, GMT+0200 would appear. The names Central European Standard Time (CET) and Central European Summer Time (CEST) are also displayed.
The other time specifications are generated using transferred values. The entries 2024, 6, 10 become July 10, 2024, and the time is set to 00:00:00 or 17:08:03.
Here are some values to convert: February 30, 2024, becomes March 1, 2024, and 17:68 becomes 18:08. If we subtract 3 seconds, it becomes 18:07:57.
The value 2 × 60 × 1,000 milliseconds corresponds to a difference of two minutes from the point of origin. The result is 01.01.1970 00:02 GMT, and due to the time difference, this corresponds to 01:02 for CET.
The negative value –1.5 × 24 × 60 × 60 × 1,000 corresponds to a difference of 1.5 days, and the result is 30.12.1969 12:00 GMT. Due to the time difference, this corresponds to 13:00 for CET.
In this section, you’ll get to know various options for outputting a Date object. I will explain this using the current period as an example:
When calling the dateFormat() method, you can pass a string with format specifications that provide the following information:
The two-digit values are output with a leading zero if necessary. Other characters, such as : (colon) or . (dot), are not converted but are simply output at the relevant position.
Here’s the program:
... <head> ...
<script src="number.js"></script>
<script src="date.js"></script>
</head>
<body><p>
<script>
const time = new Date();
const output = "Time object: " + time + "<br>"
+ "Local format: " + time.toLocaleString() + "<br>"
+ "UTC format: " + time.toUTCString() + "<br>"
+ "Local offset from UTC: "
+ (time.getTimezoneOffset()/60) + " hour(s)<br>"
+ "Default format: " + time.dateFormat("M/d/y h:m:s") + "<br>"
+ "With weekday: " + time.dateFormat("w, M/d/y") + "<br>"
+ "With milliseconds: " + time.dateFormat("h:m:s,i") + "<br>";
document.write(output);
</script></p>
</body></html>
Two extensions are integrated: first, the extension of the Number object from the number.
js file, and second, the extension of the Date object from the date.js file. Internally, the dateFormat() method uses the format() method from the number.js file to output the leading zeros.
When you use the toLocaleString() and toUTCString() methods, the name of the day of the week and the name of the month are also listed. The toUTCString() method specifies the time in UTC.
The getTimezoneOffset() method returns an indication in minutes, which are converted into hours here. Three different outputs follow as examples of dateFormat().
The result is shown here.
The separate dateFormat() method is used to extend the Date object and provides a convenient way to output different time specifications.
First, here’s the code:
Date.prototype.dateFormat = function(formatcharacter)
{
const wday = ["Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday"];
let output = "";
for(let i=0; i<formatcharacter.length; i++)
switch(formatcharacter[i])
{
case "w": output += wday[this.getDay()]; break;
case "d": output += this.getDate().format(2); break;
case "M": output += (this.getMonth()+1).format(2); break;
case "y": output += this.getFullYear(); break;
case "h": output += this.getHours().format(2); break;
case "m": output += this.getMinutes().format(2); break;
case "s": output += this.getSeconds().format(2); break;
case "i": output += this.getMilliseconds(); break;
default: output += formatcharacter[i];
}
return output;
}
An anonymous function is assigned to the dateFormat property of the Date.prototype object, and this turns dateFormat() into a method. You pass a string with the required format details as a parameter, and this string is run through character by character in a for loop to assemble and return the formatted time specification.
In preparation, an array is created with the weekdays spelled out. The getDay() method of the Date object returns the number of the day of the week: the value 0 represents Sunday, the value 1 represents Monday, and so on up to the value 6 for Saturday. These values are used as an index for the array.
You can access the Date object for which the method is called via this. Within the for loop, each individual character is examined using a switch branch. The different format characters lead to calls of various methods of the Date object: getDay(), getDate(), get- Month(), getFullYear(), getHours(), getMinutes(), getSeconds(), and getMilliseconds(). There are a few special features you should note:
If a character doesn’t correspond to any of the format characters, it gets immediately added to the formatted time specification without further conversion. This applies, for example, to colons, dots, or spaces.
You can also use the Date object to offset times against each other. The following program contains four examples:
The last method is defined in the external date.js file, just like the separate dateFormat() method.
Here’s the first part of the program:
... <head> ...
<script src="number.js"></script>
<script src="date.js"></script>
</head>
<body><p>
<script>
let timeA = new Date(2024, 6, 15, 23, 59, 20);
let timeB = new Date(2024, 6, 16, 0, 1, 50);
document.write("1: " + timeA.dateFormat("M/d/y h:m:s") + "<br>");
document.write("2: " + timeB.dateFormat("M/d/y h:m:s") + "<br>");
let difference = timeB - timeA;
document.write("Difference in minutes: "
+ (difference / 60000) + "<br><br>");
...
Two Date objects are created, each with predefined data for date and time. To calculate the date and time difference between them, you can simply subtract one from another. A time specification in a Date object is stored internally as the number of milliseconds since the point of origin (i.e., since January 1, 1970, 00:00). Consequently, the difference is a number as well. To represent it in minutes, divide it by 60,000.
The result is shown below.
Here’s the second part of the program:
...
const msecA = new Date();
let a = 1;
for(let i=0; i<5e7; i++)
a = a * -1;
const msecB = new Date();
difference = msecB - msecA;
document.write("Computing time in milliseconds: "
+ difference + "<br><br>");
...
The program queries the current system time twice, once before a program section and once after. In this way, the program calculates the amount of time the computer needs to process a program section in which a for loop is run very frequently. The period depends on the performance and the current utilization of the computer.
You can see this result in the previous figure as well.
Let’s now look at the third part of the program:
...
timeA = new Date(1979, 7, 16);
timeB = new Date();
difference = timeB.getFullYear() - timeA.getFullYear();
if(( timeB.getMonth() < timeA.getMonth() )
|| ( timeB.getMonth() == timeA.getMonth()
&& timeB.getDate() < timeA.getDate() ) )
difference--;
document.write("1: " + timeA.dateFormat("M/d/y") + "<br>");
document.write("2: " + timeB.dateFormat("M/d/y") + "<br>");
document.write("Age: " + difference + "<br><br>");
...
The program generates two time specifications, one with a date of birth and one with the current system time. It calculates the age as follows: The age of a person initially corresponds to the difference in years between the two times. Then the program compares the months from the two times, and if the month of birth has not yet been reached or if it’s currently the month of birth and the birthday has not yet been reached, the program deducts the value 1.
Note: The parentheses within the linked condition are not necessary and are for clarification purposes only. The logical AND operator takes precedence over the logical OR operator.
The result is shown here.
The fourth and final part of the program reads as follows:
...
timeA = new Date(2024, 6, 31, 17, 55, 30);
timeB = timeA.dateAdd(0, 0, 3, 6, 10, 0);
document.write("1: " + timeA.dateFormat("M/d/y h:m:s") + "<br>");
document.write("3 days, 6 hours and 10 minutes later:<br>");
document.write("2: " + timeB.dateFormat("M/d/y h:m:s"));
</script></p>
</body></html>
First, the program generates a single time entry, and then, it creates the second Date object using the dateAdd() method. This is another self-written extension of the Date object. Internally, a number of predefined methods are used.
When you initiate the call, you can transfer a time value with a total of six partial values that will be added or subtracted. The six partial values represent the year, month, day, hour, minute, and second in sequence.
You can see this result in the last figure as well.
The custom dateAdd() method is used to extend the Date object and provides the option of adding or subtracting a time value from an existing time.
First, here’s the code:
Date.prototype.dateAdd = function(year, month, day, hour, minute, second)
{
const time = new Date();
time.setFullYear(this.getFullYear() + year);
time.setMonth(this.getMonth() + month);
time.setDate(this.getDate() + day);
time.setHours(this.getHours() + hour);
time.setMinutes(this.getMinutes() + minute);
time.setSeconds(this.getSeconds() + second);
return time;
}
The program assigns an anonymous function to the dateAdd property of the Date.prototype object. This makes dateAdd() a method, and six partial values of a time value are transferred as parameters. You access the current Date object for which the method is called via this.
A new Date object (time) is also created, and a reference to this object is returned as the result of the calculation. A total of six of the predefined set methods are called to calculate the individual partial values for the new object, and to calculate each partial value, the corresponding parameter is added to the corresponding partial value of the current object. If the partial values are too large or too small, they’ll be converted accordingly. This applies, for example, to an entry such as –10 minutes or +50 days.
Editor’s note: This post has been adapted from a section of the book Getting Started with JavaScript by Thomas Theis.