Working with dates is a very common task in our software. This section describes how we can perform date calculations in our CoffeeScript applications and provides some useful utility methods that you can use in your own applications.
Performing date calculations
Performing date calculations is not as intuitive as one would like in JavaScript. For example, subtracting two dates returns the number of milliseconds between the two dates. JavaScript does not provide methods to add hours, days, months, and so on for a date. In the next section, we will create methods to address each of these complications.
How to do it...
Let's define methods to calculate the difference between two dates and add a timespan to a date as follows:
MILLISECONDS_PER_SECOND = 1000
MILLISECONDS_PER_MINUTE = MILLISECONDS_PER_SECOND * 60
MILLISECONDS_PER_HOUR = MILLISECONDS_PER_MINUTE * 60
MILLISECONDS_PER_DAY = MILLISECONDS_PER_HOUR * 24
MILLISECONDS_PER_WEEK = MILLISECONDS_PER_DAY * 7
MILLISECONDS_PER_YEAR = MILLISECONDS_PER_WEEK * 52
dateDifference = (startDate, endDate, units = 'days') ->
elapsed = endDate - startDate
switch units
when 'days'
return elapsed / MILLISECONDS_PER_DAY
when 'weeks'
return elapsed / MILLISECONDS_PER_WEEK
when 'months'
return elapsed / MILLISECONDS_PER_YEAR * 12
when 'years'
return elapsed / MILLISECONDS_PER_YEAR
when 'hours'
return elapsed / MILLISECONDS_PER_HOUR
when 'minutes'
return elapsed / MILLISECONDS_PER_MINUTE
when 'seconds'
return elapsed / MILLISECONDS_PER_SECOND
return elapsed
dateAdd = (date, amount, units = 'days') ->
workingDate = new Date(date.valueOf())
switch units
when 'days'
workingDate.setDate date.getDate() + amount
when 'weeks'
workingDate.setDate date.getDate() + amount * 7
when 'months'
workingDate.setMonth date.getMonth() + amount
when 'years'
workingDate.setFullYear date.getFullYear() + amount
when 'hours'
workingDate.setHours date.getHours() + amount
when 'minutes'
workingDate.setMinutes date.getMinutes() + amount
when 'seconds'
workingDate.setSeconds date.getSeconds() + amount
return workingDate
module.exports =
dateAdd: dateAdd
dateDifference: dateDifference
How it works...
First, define some useful constants to help convert milliseconds to days or years.
Next, we define a method to calculate the difference between two dates. The dateDifference() method takes a startDate and endDate parameter as well as an optional units parameter (which defaults to days) that represents the units to be returned.
The dateDifference() method essentially subtracts the two dates and converts the resultant milliseconds to the desired units.
We then define the dateAdd() method. This method accepts date, amount, and an optional units parameter representing the units of the amount being added (which defaults to days).
To add time to a date, you must use a little trick to set the proper date unit to its value and the amount to be added. For example, to add 5 days to the current date, you would use the following code:
currentDate = new Date()
currentDate.setDays currentDate.getDays() + 5
console.log currentDate
You can subtract amounts from the given date by using negative values. For example, 7 days ago would be as follows:
currentDate = new Date()
console.log dateAdd currentDate, -7
An example of using these date math functions is shown as follows:
dm = require './date_math'
zeroPad = (value, length = 2) ->
return "00000000000000#{value}".split('')[-length..].join('')
formatDate = (date) ->
year = date.getFullYear()
month = date.getMonth() + 1
day = date.getDate()
hour = date.getHours()
minute = date.getMinutes()
return "#{year}-#{zeroPad month}-#{zeroPad day} #{zeroPad hour}:#{zeroPad minute}"
currentDate = new Date()
newCentury = new Date(2000, 0)
console.log 'Current date: ', formatDate currentDate
console.log 'Days since Jan. 1, 2000: ',
dm.dateDifference newCentury, currentDate
console.log 'Years since Jan. 1, 2000: ',
dm.dateDifference newCentury, currentDate, 'years'
console.log '3 days from now: ',
formatDate dm.dateAdd currentDate, 3
console.log '3 days ago: ',
formatDate dm.dateAdd currentDate, -3
console.log '3 months from now: ',
formatDate dm.dateAdd currentDate, 3, 'months'
console.log '3 years from now: ',
formatDate dm.dateAdd currentDate, 3, 'years'
console.log '3 hours from now: ',
formatDate dm.dateAdd currentDate, 3, 'hours'
Its output will be:
Current date: 2013-10-21 18:54
Days since Jan. 1, 2000: 5042.746363993056
Years since Jan. 1, 2000: 13.806287101965928
3 days from now: 2013-10-24 18:54
3 days ago: 2013-10-18 18:54
3 months from now: 2014-01-21 18:54
3 years from now: 2016-10-21 18:54
3 hours from now: 2013-10-21 21:54
Measuring elapsed time
Using what we covered about working with dates and times, we can easily take it one step further and create a performance measurement tool that can clock the start and end times to execute a function and display execution statistics once complete.
How to do it...
In this section, we define helper methods to format and display results, and a timer() method that performs the timing function:
This little performance utility module begins by requiring our date_utils library as we will be using the dateDifference() method to calculate how long a method takes to execute.
Then, we have some formatting helper methods. The formatNumber() method will format a number for display and includes optional parameters for the number of decimal places and zero padding. For example, formatNumber(5.4, 3, 2) will produce 05.400.
The formatTime() method will take a value in milliseconds and display it as hours, minutes, and seconds. For example, formatTime(5680) will be displayed as 00:00:05.680.
Tip
You may have noticed we need to define our helper methods before they are used. This is a requirement of JavaScript due to its dynamic nature.
After our formatting helper methods, we have a method that displays the performance measurement results, but let's look at the timer() method first.
The timer() method is really the heart of our module. It is responsible for executing the function being measured and gathering timing statistics with each run. The method takes a function (func) as a parameter and a numberOfTimesToExecute optional parameter representing the number of times to execute the function, which defaults to 1.
The timer() method then declares a timerResults array to store our execution times.
We then loop between 1 and numberOfTimesToExecute. With each iteration, we perform the following tasks:
Store the current date and time in a variable called start
Execute the function that is being measured
Store the current date and time after the execution of a variable called end
Push the results into our timerResults array
Once the function execution has been measured, the timer() method calls displayResults() to pass the timerResults array. The displayResults() method displays the number of executions, the total time, minimum time, maximum time, and the average time.
It is worth noting that the act of measuring performance negatively impacts the performance, however minimally. When working to improve performance in your code, it is better to compare results between tests with the understanding that each test executes with roughly the same overhead.
Let's try running our timer as follows:
tu = require './timer_utils'
test = () ->
for i in [1..1000000]
d = new Date()
tu.timer test, 5
Our little timer demo declares a test method that simply iterates from one to a million, and with each iteration, the current date/time is stored in the d variable.
Tip
Why a million? Turns out d = new Date() happens very quickly. If we do it a million times, it takes about 0.5 seconds.
We then pass our test() method to timer() and have it execute five times.