Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3v4: d3.timeParse fails with UNIX epoch seconds (%s)

My dataset includes UNIX timestamps, such as "1509392160". I can't seem to parse those using d3.timeParse("%s"), which returns null.

Checking the reverse process with d3.timeFormat fails me as well. The official example and all other format strings work:

var formatTime = d3.timeFormat("%B %d, %Y");
formatTime(new Date); // -> "June 30, 2015"

However, formatting to UNIX (milli)seconds just returns "s" or "Q" for "%s" and "%Q":

var formatTime = d3.timeFormat("%s");
formatTime(new Date); // -> "s"

Using D3 v4.11.0 btw. What am I missing?

like image 953
gl03 Avatar asked Oct 31 '17 19:10

gl03


2 Answers

I ran this code with only the d3-time-format module and had no problems:

var parse = d3.timeParse("%s");
var time = parse(1509392160);

console.log(time);

var format = d3.timeFormat("%s");
time = format(Date.now());

console.log(time);
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>

However, as you have found out, this does not work with d3 v4.11 (nor does it work with any other version of d3 v4). It appears that d3-time-format only recently added functionality to support parsing UNIX timestamps, and was released on October 9, 2017.

The "%s" and "%Q" selectors were added in the most recent release along with "%f", "%u", and "%V", these other ones also appear to not work in v4.11:

console.log(d3.timeParse("%u")(1));  // day of week
console.log(d3.timeParse("%V")(25)); // week of year
console.log(d3.timeParse("%f")(100));// microseconds

console.log("For Comparison, %Y:");
console.log(d3.timeParse("%Y")(2017)); // Year
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

Meanwhile, it appears that d3 v4.11 was released on October 3rd, 2017. It would appear that the most recent d3 core library is therefore outdated in this respect. I would imagine that an updated version will be available shortly.

Though you should be able to use both the core library for everything else and the module for time formatting/parsing to get the desired functionality (until an update appears anyways):

var parse = d3.timeParse("%Q");
var time = parse(1509392160);

d3.select("body").append("p")
  .html(time);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>
like image 165
Andrew Reid Avatar answered Oct 11 '22 02:10

Andrew Reid


As a complement to Andrew's answer, this is the problem:

D3 default (core) bundle has these specifiers in its source code:

var parses = {
    "a": parseShortWeekday,
    "A": parseWeekday,
    "b": parseShortMonth,
    "B": parseMonth,
    "c": parseLocaleDateTime,
    "d": parseDayOfMonth,
    "e": parseDayOfMonth,
    "H": parseHour24,
    "I": parseHour24,
    "j": parseDayOfYear,
    "L": parseMilliseconds,
    "m": parseMonthNumber,
    "M": parseMinutes,
    "p": parsePeriod,
    "S": parseSeconds,
    "U": parseWeekNumberSunday,
    "w": parseWeekdayNumber,
    "W": parseWeekNumberMonday,
    "x": parseLocaleDate,
    "X": parseLocaleTime,
    "y": parseYear,
    "Y": parseFullYear,
    "Z": parseZone,
    "%": parseLiteralPercent
};

As you can see, if you compare this with the complete list here, it's missing all these:

  • "f"
  • "Q"
  • "s"
  • "V"
  • "u"

So, the alternative for now is referencing the time standalone microlibrary:

<script src="https://d3js.org/d3-time-format.v2.min.js"></script>

EDIT: indeed, the default bundle doesn't have yet those new directives. This is a GitHub issue just closed by Bostock: https://github.com/d3/d3-time-format/issues/38

So, meanwhile, just stick with the standalone microlibrary.

like image 41
Gerardo Furtado Avatar answered Oct 11 '22 04:10

Gerardo Furtado