Many thanks to Romek Zylla and E minor for giving some valuable advice on dates in JavaScript.
This page describes the basics of date and time scripting and explains the millennium problem.
The problem with date and time scripting is that the human calendar is not very logical (to put it mildly). Therefore we have to write large scripts to accurately perform our calculations and to give user friendly output afterwards. All this is made more difficult by the millennium problem. Fortunately there is a simple solution for this problem.
Date and time scripting uses the date and time according to the system the browser is on. If this system time is wrong, there's nothing you can do about it and all scripts in this section will give wrong output.
First I describe Epoch Time, followed by the Date object and its methods, then I continue with the Millennium problem and its solution.
First of all you need to know the concept Epoch Time. It is the basis of date and time calculation on computers.
Epoch Time is the time elapsed since 1 January 1970 00:00:00. This is usually expressed in seconds, but browsers use milliseconds.
This way of dating will end somewhere in 2038 because then the 32 bits number used for keeping track of the time passes its maximum. What happens then to date and time calculations is anyone's guess. Probably a 64 bits number will be installed as its successor somewhere before 2038. This will allow us to go on with date and time calculations for the next 292 billion years or so, comfortably longer than the human race (or, indeed, the universe) will exist.
To access a date and create user friendly output, you need to create a Date object that contains a certain date. For each Date object, JavaScript creates several methods that we can use to extract useful data, like the day of the month, the time in seconds, minutes and hours etc. The main trouble is calculating the year. (I'll treat this in detail below.)
To create a Date object, do
var thisdate = new Date();
If you don't fill in anything between the brackets (), the browser takes the current date (system date of the computer the browser is on) and puts this in thisdate.
The current date is .
Since this output is browser dependent and not particularly user friendly, we need to start using the methods that JavaScript has prepared for us. For instance, do
thisdate.getMinutes()
to get the minutes of the current date: (I list these methods below).
To take any other date than the current one, fill in something between the brackets (), like:
var thisdate = new Date(document.lastModified);
This takes the string document.lastModified (last modification date of the document) and converts it to a Date object so we can start reading out things in the way described above.
Each Date object has methods that you can use to read out certain details and make the output more user friendly or to construe your own dates.
The basic syntax for getting information about the date is thisDate.getSomething(). You can get the following information:
getTime() | Get the number of milliseconds since 01/01/1970 00:00:00 |
---|---|
getSeconds() | Get the number of seconds (0-59) |
getMinutes() | Get the number of minutes (0-59) |
getHours() | Get the number of hours (0-23) |
getDay() | Get the day of the week (0 = Sunday, 6 = Saturday) |
getDate() | Get the day of the month (1-31) |
getMonth() | Get the month number (0 = January, 11 = December) |
getYear() | Described below in great detail |
For a practical example of these methods, see the date and time script.
If you want to construe your own date, you'll have to use the methods setSeconds(), setMinutes() etc. These methods exactly match the get methods listed above, except that you say set instead of get.
So if you want to set the date to 1 January 1999, do:
var thisDate = new Date(); thisDate.setYear(1999); thisDate.setMonth(0); thisDate.setDate(1);
and thisDate contains the date 1 January 1999 00:00:00.
I use both the setSomething() methods and the UTC method in the week number script.
The UTC() method converts a comma-separated list of values to milliseconds since 01/01/1970 00:00:00. The syntax is
date.UTC(year,month,date,hours,minutes,seconds);
There are two methods that have to do with time zones. Both convert a date to a string:
Note that the result of one of these functions is a string, not a Date object. Unfortunately you cannot make the string a Date object again, if you do
var theDate = new Date(); // create Date object with the current date; var temp = theDate.toGMTString(); // convert date to a GMT string; var theSecondDate = new Date(temp); // convert string to a Date object
theSecondDate once again holds the same date as theDate. Very, very annoying.
The Date.parse() method is for reading in strings like October, 4 2000 07:04:11 and translating them to a Date object. To set a date like this, do
var today = new Date(); today.setTime(Date.parse('October, 4 2000 07:04:11'));
Now you can use the usual methods on today. Note that the syntax of this string is very strict:
'MonthName, DayNr Year Hrs:Min:Sec'
Some things I discovered while playing with this method:
I need to do more research on this method.
The Date.getTimezoneOffset() method gives the difference between the local timezone on the computer and GMT in minutes. (Why minutes? I have no idea).
I use this method in the Internet Beat script.
The millennium problem is well known: the writers of older programs didn't really know what to do about the new century. Netscape devised a complex solution that even Netscape itself doesn't completely follow.
When using the method date.getYear(), the Netscape system doesn't give the full year but uses an abbreviated version of the year. In this system, 1997 becomes 97 and 2000 is represented by 100.
Microsoft did not entirely agree: before 2000 Explorer did the same as Netscape, but now that 2000 has come Explorer 4 and 5 give 2000 as the Year.
Just to keep you on your toes, Netscape 3 (and only 3) follows Explorer. As to the minor browsers: they all follow the orginial Netscape system, except for WebTV.
To make the matter even more complex, date.getYear() is deprecated nowadays and you should use date.getFullYear(), which, in turn, is not supported by the older browsers. If it works, however, it should always give the full year, ie. 2000 instead of 100.
Your browser gives the following years with these two methods:
Below I give compatibility info for both getYear() and getFullYear() in 24 browsers.
Finally, Netscape has one grave bug in the implementation of document.lastModified. I have found out that if you use getYear() on this date, Netscape gives 0 instead of 100 and if you use getFullYear() you get 1900 instead of 2000.
Many thanks to E minor for providing this formula.
Fortunately there is a simple solution to this extremely complex problem. Since it is supported by all browsers, always use getYear(). Divide the outcome by 100 and take the modulus, so that now we have a number from 0 to 99. If this number is smaller than 38, add 2000, if it's larger add 1900. This always gives the correct year. (Why 38? Because Epoch Time will end in 2038. You can also use 70, because in the Epoch Time system no date can be before 1970).
So always use the function below when you have to calculate a year:
function takeYear(theDate) { x = theDate.getYear(); var y = x % 100; y += (y < 38) ? 2000 : 1900; return y; }
and send the Date object to the function, like
var today = new Date(); Year = takeYear(today);
Now Year contains the right year: and we have succesfully solved the millennium problem.
Below you see browser compatibility with date.getYear() and date.getFullYear() when reading out the year 2000. When the year is 1998, all browsers return 98, not 1998.
Browser | getYear() 1998 | getYear() 2000 | getFullYear() |
---|---|---|---|
Netscape 2 Windows | 98 | 100 | Not supported |
Netscape 2 Mac | 98 | 100 | Not supported |
Netscape 3 Windows | 98 | 2000 | Not supported |
Netscape 3 Mac | 98 | 2000 | Not supported |
Netscape 3 Linux | 2000 | Not supported | |
Explorer 3 Windows | 98 | 100 | Not supported |
Explorer 3 Mac | 98 | 2000 | 2000 |
Hotjava 3 Windows | 98 | 100 | 2000 |
Hotjava 3 Mac | 100 | 2000 | |
Opera 3 Windows | 98 | 100 | Not supported |
WebTV | untestable | 2000 | Not supported |
iCab | untestable | 100 | 2000 |
Netscape 4 Windows | 98 | 100 | 2000 |
Netscape 4 Mac | 98 | 100 | 2000 |
Netscape 4 Linux | 98 | 100 | 2000 |
Netscape 4 Solaris | 98 | 100 | 2000 |
Explorer 4 Windows | 98 | 2000 | 2000 |
Explorer 4 Mac | 98 | 2000 | 2000 |
Opera 4 Windows | 98 | 100 | 2000 |
Opera 4 Linux | 98 | 100 | 2000 |
Konqueror | 100 | 2000 | |
Explorer 5 Windows | 98 | 2000 | 2000 |
Explorer 5 Mac | 98 | 2000 | 2000 |
Explorer 5 Solaris | 2000 | 2000 | |
Netscape 6 Windows | 98 | 100 | 2000 |
Netscape 6 Mac | 98 | 100 | 2000 |
Netscape 6 Linux | 98 | 100 | 2000 |