Often, we perform analysis on a data set that is time- and date-sensitive, therefore, D3 provides a built-in time scale to help perform this type of mapping. In this recipe, we will learn how to use D3 time scale.
Open your local copy of the following file in your web browser:
https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter4/time-scale.html
First, let's take a look at the following code example:
<div id="time" class="clear"> <span>Linear Time Progression<br></span> <span>Mapping [01/01/2013, 12/31/2013] to [0, 900]<br></span> </div> <script type="text/javascript"> var start = new Date(2013, 0, 1), // <-A end = new Date(2013, 11, 31), range = [0, 1200], time = d3.time.scale().domain([start, end]) // <-B .rangeRound(range), // <-C max = 12, data = []; for (var i = 0; i < max; ++i){ // <-D var date = new Date(start.getTime()); date.setMonth(start.getMonth() + i); data.push(date); } function render(data, scale, selector) { // <-E d3.select(selector).selectAll("div.fixed-cell") .data(data) .enter() .append("div").classed("fixed-cell", true); d3.select(selector).selectAll("div.fixed-cell") .data(data) .exit().remove(); d3.select(selector).selectAll("div.fixed-cell") .data(data) .style("margin-left", function(d){ // <-F return scale(d) + "px"; }) .html(function (d) { // <-G var format = d3.time.format("%x"); // <-H return format(d) + "<br>" + scale(d) + "px"; }); } render(data, time, "#time"); </script>
This recipe generates the following visual output:
In this recipe, we have a Date
range defined on line A
between January 1, 2013 and December 31, 2013.
var start = new Date(2013, 0, 1), // <-A end = new Date(2013, 11, 31), range = [0, 900], time = d3.time.scale().domain([start, end]) // <-B .rangeRound(range), // <-C
This range was then used to create a D3 time scale on line B
using the d3.time.scale
function. Similar to quantitative scales, time scale also supports separate domain
and range
definition, which is used to map date- and time-based data points to visual range. In this example, we set the range of the scale to [0, 900]
. This effectively defines a mapping from any date-and-time value in time range between January 1, 2013 and December 31, 2013 to a number between 0 and 900.
With the time scale defined, we can now map any given Date
object by calling the scale function, for example, time(new Date(2013, 4, 1))
will return 395
and time(new Date(2013, 11, 15))
will return 1147
, and so on.
On line D
, we create our data array consisting 12 months from January to December in 2013:
for (var i = 0; i < max; ++i){ // <-D var date = new Date(start.getTime()); date.setMonth(start.getMonth() + i); data.push(date); }
Then, on line E
, we created 12 cells representing each month in a year using the render
function.
To spread the cells horizontally, line F
performs a mapping from the month to the margin-left
CSS style using the time scale we defined:
.style("margin-left", function(d){ // <-F return scale(d) + "px"; })
Line G
generates the label to demonstrating what the scale-based mapping produces in this example:
.html(function (d) { // <-G var format = d3.time.format("%x"); // <-H return format(d) + "<br>" + scale(d) + "px"; });
To generate human-readable strings from a JavaScript Date
object, we used a D3 time formatter on line H
. D3 ships with a powerful and flexible time-formatting library, which is extremely useful when dealing with the Date
object.
Here are some of the most useful d3.time.format
patterns:
%a
: This is the abbreviated weekday name%A
: This is the full weekday name%b
: This is the abbreviated month name%B
: This is the full month name%d
: This is the zero-padded day of the month as a decimal number [01,31]%e
: This is the space-padded day of the month as a decimal number [ 1,31]%H
: This is the hour (24-hour clock) as a decimal number [00,23]%I
: This is the hour (12-hour clock) as a decimal number [01,12]%j
: This is the day of the year as a decimal number [001,366]%m
: This is the month as a decimal number [01,12]%M
: This is the minute as a decimal number [00,59]%L
: This is the milliseconds as a decimal number [000, 999]%p
: This is the either AM or PM%S
: This is the second as a decimal number [00,61]%x
: This is the date, as "%m/%d/%Y
"%X
: This is the time, as "%H:%M:%S
"%y
: This is the year without century as a decimal number [00,99]%Y
: This is the year with century as a decimal numberhttps://github.com/mbostock/d3/wiki/Time-Formatting#wiki-format