GeneratInG dateS and tImeS
5. Get a reference to the paragraph for the output:
var output = document.getElementById(‘output’);
The paragraph that already exists in the HTML will be used to display the message.
ptg7799847 6. Update the appropriate property of the paragraph with the custom message:
if (output.textContent !== undefined) { output.textContent = message;
} else {
output.innerText = message;
}
This code was explained in Chapter 5, Using Control Structures. On some browsers, the textContent property will exist for HTML elements, and that property can be used to assign plain text to a paragraph. To confirm that this property exists, the condition checks that the property’s value does not equal undefined. If it does equal undefined, then the innerText property needs to be used instead. Again, see Chapter 5 for a slightly more thorough discussion.
7. Complete the function:
}
8. Tell the browser to call the init() function when the window has been loaded:
window.onload = init;
9. Save the file as today.js, in a js directory next to today.html, and test it in your Web browser (Figure 6.6).
You can reload the script to show the most current time, or view it in another browser to see it how the date might be displayed differently (Figure 6.7).
fiGURe 6 .7 In Safari (here), the day of the week is not shown (compare with Figure 6.6, which is Chrome).
generating dateS and tiMeS 179
ptg7799847 Working With tiMe zones
When working with the Date object, one thing to be wary of, especially with times, is the issue of the various time zones that exist in the world. By default, JavaScript represents dates and times using the client’s time zone setting. But there are situa-tions where it’s best to work with a “neutral” date and time: one that is consistently the same across all clients. For example, if you’re running an auction site, you can’t just set an auction to end at, say, 8:00 p.m., as my 8:00 p.m. is undoubtedly a different time than yours. The solution is to use a standardized time zone, such as UTC, which strangely stands for Coordinated Universal Time. UTC represents the same time zone as Greenwich Mean Time (GMT), but UTC is the preferred term to use anymore.
To establish a Date object using UTC, there are a couple of options. The first is to use a UTC-appropriate timestamp. For example, if the details of the hypotheti-cal auction come from a database, and that database stores the information using UTC, the server could provide the UTC timestamp to the JavaScript:
// JavaScript code.
var ending = new Date(<?php echo $timestamp; ?>);
This approach will work so long as that JavaScript code is being processed by a server-side technology (such as PHP in the above) before being sent to the client.
The second option is to use the string format for creating the date and time, as that format does allow you to identify the time zone, too:
var end = new Date(‘05 Jul 2012 13:30:00 UTC’);
Now when you fetch the local date and time, it will be adjusted for the user’s time zone, from the initial UTC time (Figure 6.8):
end.toTimeString();
fiGURe 6 .8 The standard get*
and to* methods return the local date and time, even if it was originally set using UTC.
ptg7799847 Another way of setting a date and time to Coordinated Universal Time is to
perform a calculation with the user’s time zone offset. You can find that informa-tion by calling the getTimeZoneOffset() method (Figure 6.9):
var now = new Date();
now.getTimezoneOffset();
The getTimezoneOffset() returns a numeric value that is the number of min-utes, plus or minus, that the user’s time zone is from UTC.
Just as you can start with a UTC date and time and then retrieve local date and time information (as in Figure 6.8), you can also start with the local date and time and retrieve UTC equivalents. To do that, use getUTC* methods instead of get*: getUTCHours() instead of getHours(), getUTCDate() instead of getDate(), and so forth. For each of the methods listed in Table 6.1, there’s a UTC equivalent. To return the entire date as a UTC string, there’s toUTCString():
var now = new Date();
var london = now.toUTCString();
Changing dates
Moving on, if you need to change the date being represented by a Date object, you can do so using several methods (Table 6.3).
TabLe 6 .3 Date Changing Methods
Method sets
setMonth() Month (starting with 0 for January)
setSeconds() Seconds
fiGURe 6 .9 The getTimezone Offset() method returns the user’s offset, in minutes, from UTC.
generating dateS and tiMeS 181
ptg7799847 Each of these is also available in a UTC-specific version, such as setUTCDate(),
setUTCFullYear(), and so forth. The setTime() method can be used to change both the date and the time. It takes a timestamp as its lone argument.
These methods are most useful when combined with date arithmetic.
date arithMetiC
The final thing you need to know about using the Date object is how to perform arithmetic. While you wouldn’t ever multiply dates and you certainly never divide them (I don’t even know what either would mean, although they are possible in JavaScript), being able to add and subtract dates and times is quite useful. For example, you may need to:
J Calculate the interval between two dates and/or times
J Add or subtract days or times from a date
J Time how long a process has taken
This is all easily done when you consider that dates can be represented as a timestamp.
tiMeStaMp arithMetic
A timestamp just being a number, you can perform any kind of arithmetic with it as you would any other number. For example, to find the date two weeks from now, you can start by getting the current timestamp. One way to do that would be to create a new Date object and invoke its getTime() method:
var now = Date();
var ts = now.getTime();
This can be cryptically shortened to just:
var ts = (new Date()).getTime();
The part within parentheses returns a new Date object and then the getTime() method is applied to the returned object. (After this line, the generated Date object is immediately forgotten.)
ptg7799847 revisiting eCmaSCrIpt 5
In Chapter 1, (Re-)Introducing JavaScript, you learned that JavaScript is derived from the ECMAScript standard. In this chapter, several new editions to ECMAScript 5 are mentioned, but you may wonder what this means to you as a Web developer. Some of the new methods have actually been around in browsers for years, and have just been made official as of ECMA-Script 5. Other new methods were formally introduced in ECMAECMA-Script 5 and will take some time to be widely supported by all browsers. Regardless of which came first—support or recognition—you can always test for a meth-od’s support prior to attempting to use it, as you see in the Date.now() code demonstrated in this section of the chapter.
New in ECMAScript 5 is the now() function, which can be called without creat-ing your own instance of a Date object:
var ts = Date.now();
That line returns the timestamp that represents the current moment, down to the precise millisecond. This is equivalent to the getTime() method called on a Date object variable, but is instead invoked from the Date object proper. This is the same premise as calling the various methods of the Math object (although, unlike with Date, you never create variables of the Math object type). This new method is well supported by modern browsers, but if you want to use code that’s 100 percent reliable for even older browsers, you could use:
if (Date.now) {
var now = Date.now() } else {
var now = (new Date()).getTime();
}
Returning to the example at hand—fetching the date and time two weeks from now—the goal is to find out how many milliseconds need to be added to the cur-rent moment. Two weeks from now is 1000 milliseconds times 60 seconds times 60 minutes times 24 hours times 14 days:
var interval = 1000 * 60 * 60 * 24 * 14;
generating dateS and tiMeS 183
ptg7799847 Now add the two values together:
var ts = now + interval;
Then, create a new Date object for that value:
var then = new Date(ts);
To get the resulting date, use one of the appropriate methods (Figure 6.10):
then.toString();
Subtraction, of course, would work much the same way.
uSing SetX() and getX()
You can also add an interval to a date and time, or subtract an interval from a date and time, via the setDate() method, providing the current date plus the interval as its new value. The generic syntax is:
var someday = new Date();
someday.setX(someday.getX() + Y);
For example, to add a week (seven days) to the current date, you would use the setDate() and getDate() methods (Figure 6.11):
var someday = new Date(); // Today!
someday.setDate(someday.getDate() + 7); // One week!
fiGURe 6 .10 Some basic arithmetic and the use of timestamps makes it easy to convert a date from one to another, some time later.
fiGURe 6 .11 Various other ways of changing a date or time by a certain interval.
ptg7799847 To add 6 hours, use setHours() and getHours():
someday.setHours(someday.getHours() + 6); // Six hours later!
To subtract a year, use setFullYear() and getFullYear():
someday.setFullYear(someday.getFullYear() - 1); // Last year!
Obviously, if you’re changing a date by a single interval—minutes, hours, days, years—using this latest code is the easiest solution. If you’re changing a date by a more complicated interval, you can either use the timestamp approach first explained, or use multiple executions of this last bit of code (i.e., first change the days, then the hours).
calculating intervalS
Sometimes, instead of finding the date that’s some interval from another date, you may want to find the interval between two dates. To do that, you can actually just subtract the one Date object from the other:
var now = new Date();
var then = new Date(‘07/07/2012 13:30’);
var diff = then - now;
The resulting value will be in milliseconds and will always be positive, regard-less of which Date object is “greater.”
Returning to the auction example, you could calculate the time remaining for the auction by subtracting the current time from the auction’s ending time, and then convert the milliseconds into minutes, hours, and days.
When needed, you can use comparative operators to see which date comes later:
if (now > then) { // then is in the past.
NOTE: You cannot directly add two Date objects as the result will be a concatenation of the two date strings, not an addition of the two underlying timestamps.
generating dateS and tiMeS 185
ptg7799847 putting it all together
Let’s use all this information to create a page that lets the user select a starting and ending date for an event. The script will then validate those dates, and calculate how many days they span (Figure 6.12). The HTML page, to be named event.html, uses two text inputs for the starting and ending dates. Just above the form is an empty DIV that will be updated by the JavaScript code, providing confirmation (Figure 6.12) or error messages (Figure 6.13).
<div id=”output”></div>
<p>Enter the starting and ending dates of the event.</p>
<div><label for=”start”>Start</label><input type=”text” name=”start”
p id=”start” placeholder=”MM/DD/YYYY” required></div>
<div><label for=”end”>End</label><input type=”text” name=”end”
p id=”end” placeholder=”MM/DD/YYYY” required></div>
The HTML page includes the event.js JavaScript file, to be written in the subsequent steps.
To work with dates:
1. Create a new JavaScript file in your text editor or IDE, to be named event.js. 2. Begin defining the process() function:
function process() { ‘use strict’;
fiGURe 6 .12 After validation, the particulars of the event are reported back to the user.
fiGURe 6 .13 Error messages are revealed to the user, too.
ptg7799847 3. Get references to the HTML elements:
var start = document.getElementById(‘start’);
var end = document.getElementById(‘end’);
var output = document.getElementById(‘output’);
The first two variables reference the two text inputs. The third is a reference to the DIV, where the output will be placed.
At this point, you could also consider validating that the start and end variables are good, and that both have value properties.