Skip to content

Commit

Permalink
Added %Q and %s directives for Unix timestamps
Browse files Browse the repository at this point in the history
  • Loading branch information
krukon authored and mbostock committed Oct 9, 2017
1 parent 66ee751 commit dd25a6d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ Returns a new formatter for the given string *specifier*. The specifier string m
* `%M` - minute as a decimal number [00,59].
* `%L` - milliseconds as a decimal number [000, 999].
* `%p` - either AM or PM.*
* `%Q` - UNIX timestamp - milliseconds from Epoch
* `%s` - UNIX timestamp in seconds - seconds from Epoch
* `%S` - second as a decimal number [00,61].
* `%u` - Monday-based (ISO) weekday as a decimal number [1,7].
* `%U` - Sunday-based week of the year as a decimal number [00,53].
Expand Down
29 changes: 29 additions & 0 deletions src/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export default function formatLocale(locale) {
"m": formatMonthNumber,
"M": formatMinutes,
"p": formatPeriod,
"Q": formatUnixTimestamp,
"s": formatUnixTimestampSeconds,
"S": formatSeconds,
"u": formatWeekdayNumberMonday,
"U": formatWeekNumberSunday,
Expand Down Expand Up @@ -100,6 +102,8 @@ export default function formatLocale(locale) {
"m": formatUTCMonthNumber,
"M": formatUTCMinutes,
"p": formatUTCPeriod,
"Q": formatUnixTimestamp,
"s": formatUnixTimestampSeconds,
"S": formatUTCSeconds,
"u": formatUTCWeekdayNumberMonday,
"U": formatUTCWeekNumberSunday,
Expand Down Expand Up @@ -130,6 +134,8 @@ export default function formatLocale(locale) {
"m": parseMonthNumber,
"M": parseMinutes,
"p": parsePeriod,
"Q": parseUnixTimestamp,
"s": parseUnixTimestampSeconds,
"S": parseSeconds,
"u": parseWeekdayNumberMonday,
"U": parseWeekNumberSunday,
Expand Down Expand Up @@ -216,6 +222,11 @@ export default function formatLocale(locale) {
d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;
}

// If Unix timestamp is specified, return date constructed from milliseconds from Epoch
if ("Q" in d) {
return new Date(d.Q);
}

// If a time zone is specified, all fields are interpreted as UTC and then
// offset according to the specified time zone.
if ("Z" in d) {
Expand Down Expand Up @@ -463,6 +474,16 @@ function parseLiteralPercent(d, string, i) {
return n ? i + n[0].length : -1;
}

function parseUnixTimestamp(d, string, i) {
var n = numberRe.exec(string.slice(i));
return n ? (d.Q = +n[0], i + n[0].length) : -1;
}

function parseUnixTimestampSeconds(d, string, i) {
var n = numberRe.exec(string.slice(i));
return n ? (d.Q = (+n[0]) * 1000, i + n[0].length) : -1;
}

function formatDayOfMonth(d, p) {
return pad(d.getDate(), p, 2);
}
Expand Down Expand Up @@ -611,3 +632,11 @@ function formatUTCZone() {
function formatLiteralPercent() {
return "%";
}

function formatUnixTimestamp(d) {
return d.getTime();
}

function formatUnixTimestampSeconds(d) {
return Math.floor(d.getTime() / 1000);
}
16 changes: 16 additions & 0 deletions test/utcFormat-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,22 @@ tape("utcFormat(\"%p\")(date) formats AM or PM", function(test) {
test.end();
});

tape("utcFormat(\"%Q\")(date) formats UNIX timestamps", function(test) {
var f = timeFormat.utcFormat("%Q");
test.equal(f(date.utc(1970, 0, 1, 0, 0, 0)), "0");
test.equal(f(date.utc(1990, 0, 1, 0, 0, 0)), "631152000000");
test.equal(f(date.utc(1990, 0, 1, 12, 34, 56)), "631197296000");
test.end();
});

tape("utcFormat(\"%s\")(date) formats UNIX timetamps in seconds", function(test) {
var f = timeFormat.utcFormat("%s");
test.equal(f(date.utc(1970, 0, 1, 0, 0, 0)), "0");
test.equal(f(date.utc(1990, 0, 1, 0, 0, 0)), "631152000");
test.equal(f(date.utc(1990, 0, 1, 12, 34, 56)), "631197296");
test.end();
});

tape("utcFormat(\"%S\")(date) formats zero-padded seconds", function(test) {
var f = timeFormat.utcFormat("%S");
test.equal(f(date.utc(1990, 0, 1, 0, 0, 0)), "00");
Expand Down
14 changes: 14 additions & 0 deletions test/utcParse-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,17 @@ tape("utcParse(\"%V %Y\")(date) week number (ISO) and year", function(test) {
test.deepEqual(p("X 1995 Z"), null);
test.end();
});

tape("utcParse(\"\")(date) parses Unix timestamps", function(test) {
var p = timeFormat.utcParse("%Q");
test.deepEqual(p("0"), date.utc(1970, 0, 1));
test.deepEqual(p("631152000000"), date.utc(1990, 0, 1));
test.end();
});

tape("utcParse(\"\")(date) parses Unix timestamps in seconds", function(test) {
var p = timeFormat.utcParse("%s");
test.deepEqual(p("0"), date.utc(1970, 0, 1));
test.deepEqual(p("631152000"), date.utc(1990, 0, 1));
test.end();
});

0 comments on commit dd25a6d

Please sign in to comment.