Purposeful Objects: Date and Math

The JavaScript Date and Math objects provide access to the type of functionality you might not think about—until the moment you need it and say to yourself, “I wonder how to...”. They are created for specific purposes—to work with dates or math. No more, no less.

The Date

The Date object can create a date and then access any aspect of it—year, day, second, and so on. Creating a date without passing in any parameters produces a date based on the client machine’s date and time:

var dtNow = new Date(  );

Right at the moment I’m reading this, in St. Louis, Missouri, at 9 p.m. on a Friday (authors have no lives), equals out to:

Fri Apr 07 2006 21:09:14 GMT-0500 (CDT)

You can also pass in parameters to create a specific date. You can enter the number of milliseconds since January 1, 1970 at 12:00:00:

var dtMilliseconds = new Date(5999000920);
document.writeln(dtMilliseconds.toUTCString(  ));

This results in the following date written to the page:

Wed, 11 Mar 1970 10:23:20 GMT

You can also use a string to create a date, if you use the proper format:

var nowDt = new Date("March 12, 1980 12:20:25");

You can forgo the time and just get a date with times set to zeros. You can also pass in each value of the date as integers, in order of year, month (as 0 to 11), day, hour, minutes, seconds, and milliseconds:

var newDt = new Date(1977,12,23);
var newDt = new Date(1977,11,24,19,30,30,30);

Once you have a date, there are several methods you can access, including a few static methods and several that allow you to manipulate every last bit of the date.

Static methods are accessed directly off of the shared Date object, rather than an instance. Date.now returns the current date and time; Date.parse returns the number of milliseconds since January 1, 1970; and Date.UTC also returns the number of milliseconds given the longest form of the constructor, described earlier:

var numMs = Date.UTC(1977,16,24,30,30,30);

The Date object methods get and set specific components of the date, and there are several. Each of the following get specific values from the date according to local times:

  • getFullYear

  • getHours

  • getMilliseconds

  • getMinutes

  • getMonth

  • getSeconds

  • getYear

The UTC equivalents are:

  • getUTCFullYear

  • getUTCHours

  • getUTCMilliseconds

  • getUTCMinutes

  • getUTCMonth

  • getUTCSeconds

Most of the get methods have equivalent set methods that set a component’s value within a Date. An example would be setYear to set the year, or setUTCMonth to set a UTC month.

Of those methods that might not be quite as obvious, the getDate method returns the numeric day of the month for a date, while the getDay returns the day of week, starting with zero (0) for Sunday:

var dtNow = new Date(  );
alert(dtNow.getDay(  ));

The getTimezoneOffset returns the number of minutes (+ or -) of the offset of the local computer from UTC. Because I’m writing this in St. Louis, which is UTC-5, I would get a value of 300 when calling this method against a local time date.

Six methods convert the date to a formatted string:

toString

Outputs the string in local time

toGMTString

Formats the string using GMT standards

toLocaleDateString and toLocaleTimeString

Output the date and the time, respectively, using the locale

toLocaleString

Converts the string using current locale

toUTCString

Formats the string using UTC standards

Example 4-8 demonstrates these, as well as some of the other date methods already discussed.

Example 4-8. Several string setting and formatting Date methods

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>A Dated Example</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head></body>
<script type="text/javascript">
//<![CDATA[

var dtNow = new Date(  );

// set day, month, year
dtNow.setDate(18);
dtNow.setMonth(10);
dtNow.setYear(1954);
dtNow.setHours(7);
dtNow.setMinutes(2);

// output formatted 
document.writeln(dtNow.toString(  ) + "<br />");
document.writeln(dtNow.toLocaleString(  ) + "<br />");
document.writeln(dtNow.toLocaleDateString(  ) + "<br />");
document.writeln(dtNow.toLocaleTimeString(  ) + "<br />");
document.writeln(dtNow.toGMTString(  ) + "<br />");
document.writeln(dtNow.toUTCString(  ));
  
//]]>
</script>
</body>
</html>

Given so many date options, it might be puzzling to figure out which specific locale to use in an application. I’ve found a good rule of thumb is to reference everything in the web-page reader’s local time if her actions are isolated—such as when placing an order at an online store. However, if the person’s actions are in relation to others, especially within an international audience (such as a weblog for comments), I would recommend setting times to UTC in order to maintain a consistent framework for all of your readers.

Warning

The Date object is managed the same between the major browsers except for one method: getYear. This method was not Y2K-compliant, and would return the year minus 1900 rather than the full year. The ECMA specification created a new method, getFullYear, that is Y2K-compliant, and Firefox and other ECMAScript Version 3 browsers support this. IE 6.x, though, has redefined getYear to be Y2K, making it functionally equivalent to getFullYear.

Math

Arithmetic isn’t math, at least in JavaScript, where the operators for basic arithmetic described in Chapter 2 are not associated with the Math object. The Math object provides mathematical properties and methods, such as LN10, which is the logarithm of 10, and log(x), which returns the natural logarithm of x. It doesn’t participate in simple arithmetic, such as addition and subtraction.

Tip

I’ll provide examples of the properties and functions for the Math object—you’ll need to supply the math skills.

Unlike the other JavaScript objects, all of Math’s properties and methods are static. What this means is that you don’t create a new instance of Math to get access to the functionality; you access the methods and properties directly on the shared object itself:

var newValue = Math.SQRT1;

As with other object properties, Math’s properties are accessed by attaching the property to the object, using the period operator:

Math.property

The following are the Math properties, as numbers and listed in the order they’re found in ECMA-262:

E

Value of e, the base of the natural logarithms

LN10

The natural logarithm of 10

LN2

The natural logarithm of 2

LOG2E

The approximate reciprocal of LN2—the base-2 logarithm of e

LOG10E

The approximate reciprocal of LN10—the base-10 logarithm of e

PI

The value of PI

SQRT1_2

The square root of 1/2

SQRT2

The square root of 2

Math in programming is somewhat dependent on the underlying architecture, and this includes how some of the math functions are implemented by each browser that provides a JavaScript engine, as well as the operating system, machine, and so on. As such, there may be minor variations in the results of the trigonometric functions, but hopefully not so many as to make the functions unusable within this context.

The Math Methods

The Math methods are relatively straightforward. Regardless of variable type, all arguments passed to the Math functions are converted to numbers first. You don’t have to do any conversion in your code.

The abs function takes an argument representing a numeric value and returns the absolute value of that number. If the number is negative, the positive value is returned. The following two lines of code return a value of 3.45:

var nVal = -3.45;
var pVal = Math.abs(nVal);

There are several trigonometric methods available through Math: sin, cos, tan, acos, asin, atan, and atan2. These provide, respectively, the sine, cosine, tangent, arc cosine, arc sine, arc tangent, and the computation of the angle between an x-point and the origin. Each takes a specific type of numeric argument and returns a result meaningful to the method:

Math.sin(x)

A specific angle, in radians

Math.cos(x)

A specific angle, in radians

Math.tan(x)

An angle, in radians

Math.acos(x)

A number between –1 and 1

Math.asin(x)

A number between –1 and 1

Math.atan(x)

Any number

Math.atan2(py,px)

The y- and x-coordinates of a point

The Math.ceil method rounds a number to the next highest whole number. The following two lines of JavaScript return a value of 4.00:

var nVal = 3.45;
var pVal = Math.ceil(nVal);

The following lines of JavaScript result in a value of –3:

var nVal = -3.45;
var pVal = Math.ceil(nVal);

The Math.floor method, on the other hand, rounds a number down—returning the next lowest whole number. The following JavaScript generates a value of 3:

var nVal = 3.45;
var pVal = Math.floor(nVal);

The following lines of JS results in a value of –4:

var nVal = -3.45;
var pVal = Math.floor(nVal);

The Math.round method rounds to the nearest integer; whether this is higher or lower depends on the value. A value of 3.45 rounds to 3, while a value of 3.85 rounds to 4. The result is the nearest integer regardless of whether the value is negative or positive.

Math.exp(x) calculates a number equivalent to e, the base of natural logarithms, raised to the value of the argument passed to the method:

var nVal = Math.exp(4) // equivalent to e4

Math.pow raises any number to a given power:

var nVal = Math.pow(3,2) // 32 or 9

Math.min and Math.max compare two or more numbers and return either the minimum or the maximum:

var nVal = 1.45;
var nVal2 = 4.5;
var nVal3 = -3.33;
var nResult = Math.min(nVal, nVal2, nVal3) // returns -3.33
var nResult2 = Math.max(nVal, nVal2, nVal3) // returns 4.5

The last method, Math.random, generates a number between 0 (inclusive) and 1 (exclusive):

var nValue = Math.random(  );

The limitations on the method could discourage you from using Math.random. However, you can multiply this value by 10 or 100, or any value, to generate random numbers beyond a value of 1. Unfortunately, you can’t set limits to generate a random number within a range of values. You can emulate this behavior, though, using a loop, as demonstrated in Example 4-9.

Example 4-9. A quirky but accurate random-number generator

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Random Quote</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
//<![CDATA[

var quoteArray = new Array(5);
quoteArray[0] = "Quote one";
quoteArray[1] = "Quote two";
quoteArray[2] = "Quote three";
quoteArray[3] = "Quote four";
quoteArray[4] = "Quote five";

function getQuote(  ) {
   do {
     iValue = Math.random(  ); // random number between 0 and 1
     alert(iValue);
     iValue *= 10; // multiply by 10 to move the decimal
     alert(iValue);
     iValue = Math.floor(iValue); // round to nearest integer
     alert(iValue);
     }
   while (iValue > 4) 
   alert(quoteArray[iValue]);
}

//]]>
</script>
</head>
<body onload="getQuote(  );">
</body>
</html>

An array is created with five quotes. A function is called when the page loads, which uses a loop and several Number and Math functions to generate an application number (between 0 and 4, inclusive). Once found, the number is used to access an array element, which is then printed out (as are the interim steps in the random-number generator, as demonstrated).

This isn’t the prettiest approach to random-number generation (or the most efficient), but it is accurate and does the job. Sometimes that’s enough—at least until you have time to explore other options.

Developing with JavaScript is a trade-off between finding the absolute best possible solution, and having to get the job finished within a specific period of time.

Tip

JavaScript Best Practice: There are no perfect solutions in JavaScript, only the most accurate and best implementations that can be managed within a given time frame—allowing time for documentation, of course.

Get Learning JavaScript now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.