Using the time scale

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.

Getting Ready

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

How to do it...

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:

How to do it...

Time scale

How it works...

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

Tip

The JavaScript Date object starts its month from 0 and day from 1. Therefore, new Date(2013, 0, 1) gives you January 1, 2013 while new Date(2013, 0, 0) actually gives you December 31, 2012.

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.

There's more...

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 number

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset