Chapter 2. Dates, Numbers, Timers, and Math

Introduction

JavaScript includes support for dates, numbers, and various mathematical operations. It also includes support for timers, which are essential for animations and other timed tasks.

Like the String, numbers can be both a literal and an object via the Number object. The Date object, though, has no literal representation—all dates have to be created using the Date constructor.

The Math object is unique in that there is only one Math object, and we access static methods and properties off this one object. And timers are actually not defined in ECMAScript, but are, instead, defined within the Web API section of the HTML5 specification.

It’s all a bit chaotic, but it comes together in the end.

The Number Object and Number Literal

Numbers in JavaScript are floating point, though there may not be a decimal component present. If no decimal is present, they act as if they’re integers:

var someValue = 10; // treated as integer 10, in base 10

Numbers can be defined in the range of –253 to 253. Most numbers in JavaScript are literal values, assigned as values to variables, and used in various computations:

var myNum = 3.18;
var newNum = myNum * someValue;

You can also construct a Number using a constructor method:

var newNum = new Number(23);

You can assign a literal number to a variable, but when you access a Number method on the variable, a Number object is created to wrap the literal value, which is discarded when the method is finished.

The Number object’s methods provide various display operations, such as providing an exponential notation:

var tst = .0004532;
alert(tst.toExponential()); // outputs 4.532e-4

In addition, there are several static Number properties, which can only be accessed via the Number object directly:

alert(Number.MAX_VALUE); // outputs 1.7976931348623157e+308

There’s a special Number static property, NaN, which is equivalent to the global NaN, and stands for Not a Number. Anytime you try to use a value in a number operation that can’t be parsed as a number, you’ll get a NaN error:

alert(parseInt("3.5")); // outputs 3
alert(parseInt("three point five")); // outputs NaN

The Date Object

The Date object contains a number representing the date and time, rather than a string representation. The numeric value for the Date object is the number of seconds since January 01, 1970 UTC. Leap seconds are ignored.

Strings used to create dates are parsed and converted into this numeric value. Both UTC (Coordinated Time Universal or Greenwich Mean Time) and ISO 8601 parsing are supported. You can create a date using a variety of techniques (see “Printing Out Today’s Date” for a discussion of different approaches), and modify the date using an extensive number of methods.

You can also access every aspect of a date: year, month, day of week, time, and so on, using specialized get and set methods, described in Tables Table 2-1 and Table 2-2.

Table 2-1. Date object get methods
Method Purpose

getDate

Returns day of the month (0–31)

getDay

Returns day of the week (0–6)

getFullYear

Returns 4-digit full year

getHours

Returns local hour (0–23)

getMilliseconds

Returns local milliseconds (0–999)

getMinutes

Returns local minute (0–59)

getMonth

Returns local month (0–11)

getSeconds

Returns local second (0–59)

getTime

Returns number of seconds since January 1, 1970 00:00:00 UTC

getTimezoneOffset

Returns time zone from UTC

getUTCDate

Returns day of month in UTC time (0–31) method (Date)

getUTCDay

Returns day of the week in UTC time (0–6)

getUTCFullYear

Returns 4-digit UTC year

getUTCHours

Returns UTC hours (0–23)

getUTCMilliseconds

Returns UTC milliseconds (0–999)

getUTCMinutes

Returns UTC minutes (0–59)

getUTCMonth

Returns UTC month (0–11)

getUTCSeconds

Returns UTC seconds (0–59)

Table 2-2. Date object set methods
Method Purpose

setDate

Sets the day of month (1–31)

setFullYear

Sets 4-digit full year

setHours

Sets the hour (0–23)

setMilliseconds

Sets the date’s milliseconds (0–999)

setMinutes

Sets the date’s minutes (0–59)

setMonth

Sets the month (0–11)

setSeconds

Sets the seconds (0–59)

setTime

Sets the date’s time as milliseconds since January 1, 1970 00:00:00 UTC

setUTCDate

Sets the date’s day of month in UTC

setUTCFullYear

Sets the full year in UTC

setUTCHours

Sets the date’s hours in UTC

setUTCMilliseconds

Sets the date’s milliseconds in UTC

setUTCMinutes

Sets the date’s minutes in UTC

setUTCMonth

Sets the month in UTC

setUTCSeconds

Sets the seconds in UTC

You can also calculate a future date by adding a number of days or weeks to any given date.

The Math Object

Unlike the Number object, the Math object does not have a constructor. All of the object’s functionality, its properties and methods, are static. If you try to instantiate a Math object:

var newMath = new Math();

You’ll get an error. Rather than create a new Math instance, access properties and methods directly on the object instead:

var topValue = Math.max(firstValue, secondValue); // returns larger number

The Math object has a considerable number of properties and methods, including several trigonometric methods. The precision of the methods is at the same level of precision that we would find using a language like C.

Table 2-3 provides a listing of the Math properties, and Table 2-4 contains a listing of the Math methods.

Table 2-3. Math object static properties
Property Purpose

E

The number value for e, the base of natural logarithms

LN2

Natural logarithm of 2

LN10

Natural logarithm of 10

LOG2E

Base 2 logarithm of e, and the reciprocal of LN2

LOG10E

Base 10 logarithm of e, and the reciprocal of LN10

PI

The number for π

SQRT1_2

Square root of 1/2, reciprocal of SQRT2

SQRT2

Square root of 2

Table 2-4. Math object static methods
Method Purpose

abs (x)

Returns absolute value of x; if x is NaN, returns NaN

acos (x)

Returns arc cosine of x; if x is greater than 1 or less than 0, returns NaN

asin (x)

Returns arc sine of x; if x is greater than 1 or less than –1, returns NaN

atan (x)

Returns the arc tangent of x

atan2 (x, y)

Returns the arc tangent of the quotient of x, y

ceil (x)

Returns the smallest integer equal to or greater than x

cos (x)

Returns the cosine of x

exp (x)

Returns Ex where E is the base of natural logarithms

floor (x)

Returns the largest integer equal to or less than x

log (x)

Returns logarithm of x

max (x1, x2, …, xn)

Returns largest of given arguments

min (x1, x2, …, xn)

Returns smallest of given arguments

pow (x,y)

Returns result of raising x to power of y

random ()

Returns random number greater than or equal to 0, and less than 1

round (x)

Rounds number to closest integer

sin (x)

Returns the sine of x

sqrt (x)

Returns the square root of x

JavaScript Timers

JavaScript also provides another way to work with time, through the use of recurring or one-time-only timers. I’ve always thought these should be a component of the Date object, but they’re actually Window object methods: setInterval and setTimeout.

The difference between the two is that setInterval creates a recurring timer that re-fires until canceled, while setTimeout creates a one-time-only timer. Both take a timer value, in milliseconds, as well as an expression to evaluate when the timer fires.

Numbers and numeric operations in JavaScript are managed by two different JavaScript objects: Number and Math.

Like the String and RegExp objects discussed in earlier chapters, numbers can be both a literal value and an object. No surprises there, but the Math object is different: it has no constructor, and all properties and methods are accessed directly from the object.

Printing Out Today’s Date

Problem

You want to print out the current date and time to a web page.

Solution

Create a new Date object, without any parameters, and output its value to the web page:

var dtElem = document.getElementById("date");
var dt = new Date();
dtElem.innerHTML = "<p>" + dt + "</p>";

The result is similar to:

Tue Jul 02 2013 11:13:28 GMT-0500 (Central Daylight Time)

Discussion

When you construct a new Date object, you can pass various parameters to the constructor to create a specific date:

var dt = new Date(milliseconds); // milliseconds since 1 January 1970 00:00:00 UTC
var dt2 = new Date(dateString); // string representing a valid date
var dt3 = new Date(year,month,date[,hour,minute,second,millisecond]);

If you don’t specify the time parameters of a date, they’re set to zero by default. If you don’t provide any form of a date string to the Date constructor, the Date object is set to the local date and time of the computer used to access the web page.

You can access components of the date using a variety of Date methods. You can directly print the entire date, as shown in the solution. If you prefer a different format, you can access the individual components of the Date, using methods such as getMonth, getFullYear, getTime, getDate, and then build the date string:

var dt = new Date();
var month = dt.getMonth();
month++;
var day = dt.getDate();
var yr = dt.getFullYear();
dtElem.innerHTML = "<p>" + month + "/" + day + "/" + yr;

The above outputs the following string to the page:

7/2/2013

The month is a zero-based integer, which is why I had to increment the month value in the example to get the actual numeric month value. To get the month name, you’ll most likely want to use an array:

var months = ['January','February','March','April','May','June','July','August',
'September','October','November','December'];
var month = dt.getMonth();
var monthString = months[month];

Printing Out the UTC Date and Time

Problem

You want to print out the current UTC (universal time) date and time, rather than the local time.

Solution

Use the UTC JavaScript methods in order to access the current date and time as universal time:

var dateElement = document.getElementById("date");
var today = new Date();
var utcDate = today.toUTCString();
dateElement.innerHTML = "<p>local datetime: " + today + "<br /> UTC datetime: " +
utcDate + "</p>";

Discussion

The Date toUTCString method returns the date/time string formatted in universal convention. This not only returns the UTC equivalent of the local datetime, it also returns it the UTC format, which varies just slightly from the datetime for the local time. The printout from the solution would be:

local datetime: Tue Jul 02 2013 11:58:06 GMT-0500 (Central Daylight Time)
UTC datetime: Tue, 02 Jul 2013 16:58:06 GMT

There are a couple of differences between the two date printouts. First of all, the time zone designation differs, which we would expect. I’m currently in Central Daylight Time (CDT), which is five hours behind universal time (UTC/GMT). In addition, the day of week in the UTC string is followed by a comma, which doesn’t occur with the local time printout.

Rather than the entire date string, you can access the UTC equivalent of the month, day, year, and time using the relevant Date methods. Instead of getMonth, use getUTCMonth, and so on. Using these getUTC methods with the local date, you could build a printout string identical to that given with the local time, or to match any other formatting.

See Also

The get methods are detailed in Table 2-1 and the set methods are detailed in Table 2-2.

Creating a Specific Date

Problem

You want to create a Date object given a month, day, and year.

Solution

Construct a Date object, passing in the month, day, and year as parameters:

var month = 10; // Month 10, in zero based system, is November
var day = 18;
var year = 1984;
var dt = new Date(year,month,day); // time is set to zero by default
console.log(dt.toString()); // verify date

Discussion

The month, day, and year are integer values passed into the Date constructor. Because the time values were not given, they’re set to zero by default.

In the solution, a November date is wanted, which is typically written out as 11. However, months with the Date object are zero-based, which means that November would be designated, numerically, as 10.

The toString method is called on the date once created, to verify the accuracy of the setting.

Creating a Timeout

Problem

You want to trigger a timeout based on an event.

Solution

Use the window.setTimeout method to create a one-time-only timer:

function someFunction {
  setTimeout("console.log('timeout!')",3000);
}

Discussion

Though setTimeout is a window object method, it’s defined globally so you don’t need to specify window.setTimeout, only setTimeout

The setTimeout method takes a minimum of two parameters: the expression to process, and the time (in milliseconds) when the expression is evaluated. In the solution, the expression is code, contained in a text string, that’s processed three seconds after the setTimeout function is run.

The first parameter can also be the name of a function:

setTimeout(functionName, 2000);

If you use something like JSLint, you’ll get a warning about the use of a string rather than a function name as the first paramter:

 

Implied eval is evil. Pass a function instead of a string.

 
  -- JSLint

When passing a string, the JavaScript engine does have to do extra work, evaluating the string and then processing the code. If you control the string, there is no inherent evil in the use of a string, and creating a function that wraps the call to console.log is overkill. However, if you have a complex bit of code to process, you’re better off using a function. You definitely don’t want to pass a string that the user can manipulate.

You can also create an expression that’s a combination of function and parameters by providing optional parameters after the time:

setTimeout(functionName, 2000, param1, param2, ..., param(n));

You can cancel a timeout, using the clearTimeout method:

var timer1 = setTimeout(functionName, 2000);
...
window.clearTimeout(timer1);

There’s no absolute guarantee that the timer event fires when it is supposed to fire. Timers run on the same execution thread as all other User Interface (UI) events, such as mouse-clicks. All events are queued and blocked, including the timer event, until its turn. So, if you have several events in the queue ahead of the timer, the actual time could differ. Probably not enough to be noticeable to your application users, but a delay can happen.

See Also

John Resig offers an excellent discussion on how timers work, and especially the issues associated with event queues and single threads of execution, at http://ejohn.org/blog/how-javascript-timers-work/.

Creating Recurring Timers

Problem

You need to run the same function several times at regular intervals.

Solution

Use setInterval to create a recurring timer:

var x = 0;
setInterval(moveElement,1000);

function moveElement() {
   x+=10;
  var left = x + "px";
  document.getElementById("redbox").style.left=left;
}

Discussion

Dynamic animations in a web page, SVG, or Canvas, are dependent on the setTimeout and setInterval methods. In particular, any flashing, moving, or following type of animation is dependent on a timer calling a method at specified intervals.

Nowadays, JavaScript isn’t the only way to animate web page content. CSS3 and SVG declarative animations can also provide sophisticated animated effects. However, since this is a book on JavaScript, we’ll pay them nevermind.

The setInterval method requires two parameters: the code or function to process, and the delay between timer events. The first parameter can be a function name:

setInterval(functionName,3000);

The first parameter can also be a function call with parameters in a text string:

setInterval ("alert('hello')", 3000);

The second parameter is the time, in milliseconds, of the timer delay. Unlike setTimeout, discussed in “Creating a Timeout”, the setInterval timer will continue to cycle until the JavaScript application (the web page) is unloaded, or until the clearInterval method is called:

var intervalid = setInterval(functionName, 3000);
...
clearInterval(intervalid);

If the first parameter is a function name, you can pass parameters, optionally, following the timer delay:

setInterval(functionName, 2000, param1, param2, ..., paramn);

Being able to pass parameters to the function is handy if you’re creating an animation and generating the parameters dynamically. You can also use a function closure with the timer.

Keeping an Incremental Counter

Problem

You want to maintain an incremental counter in code.

Solution

Define a number variable, either locally or globally, or as part of an object’s properties, and increment the variable’s value with each iteration of code:

var globalCounter = 0;
function nextTest() {
   globalCounter++;
   ...
}

Discussion

The simplest way to increase or decrease a number is using the increment (++) and decrement (--) operators, respectively. They’re equivalent to:

numValue = numValue + 1; // equivalent to numValue++
numValue = numValue - 1; // equivalent to numValue--

Both operators can be used prefix or postfix, which means the operators can be placed before or after the operand. How they’re positioned is significant. If the operator is placed before the operand, the operand’s value is adjusted first, before the operand is used:

var numValue = 1;
var numValue2 = ++numValue; // numValue and numValue2 are both 2

If the operator is postfix (placed after the operand), the operand is used first, and then its value is adjusted:

var numValue = 1;
var numValue2 = numValue++; // numValue is 2 and numValue2 is 1

The point at which the counter is incremented depends on its use. If it’s needed in a loop, the value is incremented in the loop:

var counter = 0;
while (counter <= 10) {
   ...
   counter++;
}

If the counter is needed more globally, it can be declared as a global variable, but use with caution. A global variable is one that’s declared outside of a function. It can easily conflict with any other global variables that might exist in the application or other libraries you use:

var counter = 0;
function someFunction() {
   counter++;
}

Another approach is to add the counter as property to an object, persisting as long as the object, and accessible by all object methods.

Creating a Random Number Generator

Problem

You need to generate a random number, between 0 and 255.

Solution

Use a combination of JavaScript Math methods: random to generate a random value between 0 and 1, which is then multiplied by 255, and floor to truncate the number.

var randomNumber = Math.floor(Math.random() * 255);

Discussion

The random method generates a random number between 0 and 1. To increase the range, multiply the result by the upper end of the range of values you want. If you need a random number with a higher lower end, such as a number between 5 and 10, multiply the value from random by a number equal to the upper range, minus the lower range, minus 1, and then add the lower range to the result:

var randomNumber = Math.floor(Math.random() * 6) + 5;

The floor method rounds down the floating-point value to the nearest integer.

Randomly Generating Colors

Problem

You need to randomly generate a web color.

Solution

Use the Math object to randomly generate each RGB (Red-Green-Blue) value:

function randomVal(val) {
  return Math.floor(Math.random() * val);
}

function randomColor() {
   return "rgb(" + randomVal(255) + "," + randomVal(255) + "," +
randomVal(255) + ")";
}

Discussion

Web color can be expressed in hexadecimal notation, color name, or as an RGB value. With the RGB value, each color is represented as a number between 0 and 255. The example demonstrates one technique to generate a color: using one function to randomly generate the number, and a second to return an RGB formatted string that calls the random number generating function.

See Also

See “Keeping an Incremental Counter” about converting between decimal and hexadecimal notation, and “Creating a Random Number Generator” for how to randomly generate numbers.

Converting Between Degrees and Radians

Problem

You have an angle in degrees. To use the value in the Math object’s trigonometric functions, you need to convert the degrees to radians.

Solution

To convert degrees to radians, multiply the value by (Math.PI / 180):

var radians = degrees * (Math.PI / 180);

To convert radians to degrees, multiply the value by (180 / Math.PI):

var degrees = radians * (180 / Math.PI);

Discussion

All Math trigonometric methods (sin, cos, tin, asin, acos, atan, and atan2), take values in radians, and return radians as a result. Yet it’s not unusual for people to provide values in degrees rather than radians, as degrees are the more familiar unit of measure. The functionality provided in the solution provides the conversion between the two units.

Find the Radius and Center of a Circle to Fit Within a Page Element

Problem

Given the width and height of a page element, you need to find the radius of the largest circle that fits within that page element, and its center point.

Solution

Find the smaller of the width and height; divide this by 2 to find the radius:

var circleRadius = Math.min(elementWidth, elementHeight) / 2;

Given the page element’s width and height, find the center by dividing both by 2:

var x = elementWidth / 2;
var y = elementHeight / 2;

Discussion

Working with graphics requires us to do things such as finding the center of an element, or finding the radius of the largest circle that will fit into a rectangle (or largest rectangle that can fit in a circle).

Example 2-1 demonstrates both of the solution calculations, modifying an SVG circle contained within an XHTML document so that the circle fits within the div element that surrounds it.

Example 2-1. Fitting a SVG circle into a div element
<!DOCTYPE html>
<html>
<head>
<title>Using Math method to fit a circle</title>
<style type="text/css">
#elem
{
   width: 400px;
   height: 200px;
   border: 1px solid #000;
}
</style>
<script type="text/javascript">

function compStyle(elemId,property) {
   var elem = document.getElementById(elemId);
   var style =
   (window.getComputedStyle) ?
   window.getComputedStyle(elem,null).getPropertyValue(property) :
   null;
   return style;
}
window.onload=function() {
  var height = parseInt(compStyle("elem","height"),10);
  var width = parseInt(compStyle("elem","width"),10);

  var x = width / 2;
  var y = height / 2;

  var circleRadius = Math.min(width,height) / 2;

  var circ = document.getElementById("circ");
  circ.setAttribute("r",circleRadius);
  circ.setAttribute("cx",x);
  circ.setAttribute("cy",y);
}

</script>

</head>
<body>
<div id="elem">
   <svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">
      <circle id="circ" width="10" height="10" r="10" fill="red" />
   </svg>

</div>
</body>

There are techniques in SVG that can accomplish the same purpose using the SVG element’s viewPort setting, but even with these techniques, at some point in time you’ll need to polish your basic geometry skills if you want to work with graphics. However, as the example demonstrates, most of the math you’ll need is relatively basic.

See Also

Finding a circle’s radius and the center point of an element is important when working with both SVG and Canvas, covered in Chapter 5.