diff --git a/README.md b/README.md index c23c14b..a49f892 100644 --- a/README.md +++ b/README.md @@ -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]. diff --git a/src/locale.js b/src/locale.js index a423b9a..515cd00 100644 --- a/src/locale.js +++ b/src/locale.js @@ -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, @@ -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, @@ -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, @@ -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) { @@ -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); } @@ -611,3 +632,11 @@ function formatUTCZone() { function formatLiteralPercent() { return "%"; } + +function formatUnixTimestamp(d) { + return d.getTime(); +} + +function formatUnixTimestampSeconds(d) { + return Math.floor(d.getTime() / 1000); +} diff --git a/test/utcFormat-test.js b/test/utcFormat-test.js index 20c9d0b..89a6963 100644 --- a/test/utcFormat-test.js +++ b/test/utcFormat-test.js @@ -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"); diff --git a/test/utcParse-test.js b/test/utcParse-test.js index 0924562..f7da14d 100644 --- a/test/utcParse-test.js +++ b/test/utcParse-test.js @@ -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(); +});