Time is one of those tricky programming things that seems like it should be easy, but usually turns out not to be. We will use D3's built in time parsing and interval functions. We will also take a look at the powerful Moment.js library, for when you just need more time power.
The first task when dealing with dates is usually getting a Date object out of a string. Most of the time, your data will have dates or times in an (mostly) arbitrary format, and you need to force that mess into an actual date.
D3 has d3.timeParse which provides a way to do this parsing. It was a little confusing for me the first time I tried it. You use this function to create a string parser, and then use the parser to actually convert the string.
In our nesting example, we saw data that had dates as strings:
var expense = {"name":"jim","amount":34,"date":"11/12/2015"};
To convert this date string to a Date object, we would need a parser that looks like:
var parser = d3.timeParse("%m/%d/%Y");
The input string to d3.timeParse
indicates what the date string should look like. You have a lot of options for the special, percent-sign-prefixed variables. You can see in the string I'm using month, day, and four-digit year. The slashes in the format string are not special variables - but just what we expect to find separating the fields in the date string.
Next we use the parser to parse our string.
expense.date = parser(expense.date);
console.log(expense);
=> {name: "jim", amount: 34, date: Thu Nov 12 2015 00:00:00 GMT-0500 (EST)}
Note that the returned value of the d3.timeParse
function is itself a function, so we can just pass our date string to this function directly.
Also note that the timezone is dependent on your local browser, so you might see a different value if you live in a different timezone.
Cool! Now our date is actually a Date object.
Here are a few more time parsers to show the capabilities of D3's parsing. Note again that we are creating a d3.timeParse
function and then passing in a string to parse, this time all on one line.
Just the date:
var date = d3.timeParse("%A, %B %-d, %Y")("Wednesday, November 12, 2014");
console.log(date);
=> Wed Nov 12 2014 00:00:00 GMT-0500 (EST)
The little dash in front of the d
is to remove the 0-padding)
date = d3.timeParse("%m/%y")("12/14");
console.log(date);
=> Mon Dec 01 2014 00:00:00 GMT-0500 (EST)
You can see it defaults to the first day of the month.
Just the time:
var time = d3.timeParse("%I:%M%p")("12:34pm");
console.log(time);
=> Mon Jan 01 1900 12:34:00 GMT-0500 (EST)
Gives you a somewhat strange default date.
Date and time:
time = d3.timeParse("%m/%d/%Y %H:%M:%S %p")("1/2/2014 8:22:05 AM");
console.log(time);
=> Thu Jan 02 2014 08:22:05 GMT-0500 (EST)
This could also be done using some built in short-hands:
time = d3.timeParse("%x %X")("1/2/2014 8:22:05 AM");
console.log(time);
=> Thu Jan 02 2014 08:22:05 GMT-0500 (EST)
You can see that d3.timeParse
gives you a lot of flexibility about what your time string will look like.
In many cases, you might want to modify a date object. Perhaps you only want to display the hour from a date, or maybe you want to figure out what a week from now would be.
The d3.time set of functions provides a starting point for these kinds of manipulations.
Intervals allow for modifying dates around specific time slices like minutes, hours, days, months, or years. We are given a number of functions to work with each interval, depending on what we might want to do.
So, to get the nearest hour from a date, we can use d3.timeHour.round
var hourParser = d3.timeParse("%I:%M%p");
var time = hourParser("10:34pm");
var hour = d3.timeHour.round(time);
console.log(hour);
=> Mon Jan 01 1900 23:00:00 GMT-0500
It returns a date object that just contains the nearest hour (11:00pm). We can display this by using a d3.timeFormat to format the date object into a string.
var hourFormater = d3.timeFormat("%I:%M%p")
console.log(hourFormater(hour));
=> 11:00PM
Moment.js is another JavaScript library that could be better suited to your needs, if you happen to be doing a lot of time manipulations. Its syntax and capabilities seem a bit more intuitive for certain time manipulations.
Check it out if you need more time control power!