From c792141a7c999a984c6a3eb530e39dedf35cc648 Mon Sep 17 00:00:00 2001 From: Brian Mitchell Date: Sun, 1 Oct 2017 22:52:00 -0500 Subject: [PATCH 1/2] Implement ISO weekday number (%u) --- README.md | 1 + src/locale.js | 34 +++++++++++++++++++++++++++------- test/format-test.js | 8 ++++++++ test/parse-test.js | 24 ++++++++++++++++++++++-- test/utcFormat-test.js | 8 ++++++++ 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index f2ea1f3..25b58da 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ Returns a new formatter for the given string *specifier*. The specifier string m * `%L` - milliseconds as a decimal number [000, 999]. * `%p` - either AM or PM.* * `%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]. * `%w` - Sunday-based weekday as a decimal number [0,6]. * `%W` - Monday-based week of the year as a decimal number [00,53]. diff --git a/src/locale.js b/src/locale.js index a03d6a2..9957e8a 100644 --- a/src/locale.js +++ b/src/locale.js @@ -59,8 +59,9 @@ export default function formatLocale(locale) { "M": formatMinutes, "p": formatPeriod, "S": formatSeconds, + "u": formatWeekdayNumberMonday, "U": formatWeekNumberSunday, - "w": formatWeekdayNumber, + "w": formatWeekdayNumberSunday, "W": formatWeekNumberMonday, "x": null, "X": null, @@ -86,8 +87,9 @@ export default function formatLocale(locale) { "M": formatUTCMinutes, "p": formatUTCPeriod, "S": formatUTCSeconds, + "u": formatUTCWeekdayNumberMonday, "U": formatUTCWeekNumberSunday, - "w": formatUTCWeekdayNumber, + "w": formatUTCWeekdayNumberSunday, "W": formatUTCWeekNumberMonday, "x": null, "X": null, @@ -113,8 +115,9 @@ export default function formatLocale(locale) { "M": parseMinutes, "p": parsePeriod, "S": parseSeconds, + "u": parseWeekdayNumberMonday, "U": parseWeekNumberSunday, - "w": parseWeekdayNumber, + "w": parseWeekdayNumberSunday, "W": parseWeekNumberMonday, "x": parseLocaleDate, "X": parseLocaleTime, @@ -171,7 +174,8 @@ export default function formatLocale(locale) { // Convert day-of-week and week-of-year to day-of-year. if ("W" in d || "U" in d) { - if (!("w" in d)) d.w = "W" in d ? 1 : 0; + if (!("u" in d)) d.u = "W" in d ? 1 : 7; + if (!("w" in d)) d.w = d.u === 7 ? 0 : d.u; var day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); d.m = 0; d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7; @@ -339,11 +343,17 @@ function formatLookup(names) { return map; } -function parseWeekdayNumber(d, string, i) { +function parseWeekdayNumberSunday(d, string, i) { var n = numberRe.exec(string.slice(i, i + 1)); return n ? (d.w = +n[0], i + n[0].length) : -1; } +function parseWeekdayNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + var r = n ? (d.u = +n[0], i + n[0].length) : -1; + return r; +} + function parseWeekNumberSunday(d, string, i) { var n = numberRe.exec(string.slice(i)); return n ? (d.U = +n[0], i + n[0].length) : -1; @@ -441,11 +451,16 @@ function formatSeconds(d, p) { return pad(d.getSeconds(), p, 2); } +function formatWeekdayNumberMonday(d) { + var dow = d.getDay(); + return dow === 0 ? 7 : dow; +} + function formatWeekNumberSunday(d, p) { return pad(timeSunday.count(timeYear(d), d), p, 2); } -function formatWeekdayNumber(d) { +function formatWeekdayNumberSunday(d) { return d.getDay(); } @@ -500,11 +515,16 @@ function formatUTCSeconds(d, p) { return pad(d.getUTCSeconds(), p, 2); } +function formatUTCWeekdayNumberMonday(d) { + var dow = d.getUTCDay(); + return dow === 0 ? 7 : dow; +} + function formatUTCWeekNumberSunday(d, p) { return pad(utcSunday.count(utcYear(d), d), p, 2); } -function formatUTCWeekdayNumber(d) { +function formatUTCWeekdayNumberSunday(d) { return d.getUTCDay(); } diff --git a/test/format-test.js b/test/format-test.js index cbf7460..0513a5b 100644 --- a/test/format-test.js +++ b/test/format-test.js @@ -191,6 +191,14 @@ tape("timeFormat(\"%L\")(date) formats zero-padded milliseconds", function(test) test.end(); }); +tape("timeFormat(\"%u\")(date) formats week day numbers", function(test) { + var f = timeFormat.timeFormat("%u"); + test.equal(f(date.local(1990, 0, 1, 0)), "1"); + test.equal(f(date.local(1990, 0, 7, 0)), "7"); + test.equal(f(date.local(2010, 2, 13, 23)), "6"); + test.end(); +}); + tape("timeFormat(\"%U\")(date) formats zero-padded week numbers", function(test) { var f = timeFormat.timeFormat("%U"); test.equal(f(date.local(1990, 0, 1, 0)), "00"); diff --git a/test/parse-test.js b/test/parse-test.js index a7ee428..c4aefd7 100644 --- a/test/parse-test.js +++ b/test/parse-test.js @@ -57,7 +57,7 @@ tape("timeParse(\"%A %U %Y\")(date) parses weekday, week number (Sunday) and yea test.end(); }); -tape("timeParse(\"%w %U %Y\")(date) parses numeric weekday, week number (Sunday) and year", function(test) { +tape("timeParse(\"%w %U %Y\")(date) parses numeric weekday (Sunday), week number (Sunday) and year", function(test) { var p = timeFormat.timeParse("%w %U %Y"); test.deepEqual(p("1 00 1990"), date.local(1990, 0, 1)); test.deepEqual(p("0 05 1991"), date.local(1991, 1, 3)); @@ -66,6 +66,17 @@ tape("timeParse(\"%w %U %Y\")(date) parses numeric weekday, week number (Sunday) test.end(); }); +tape("timeParse(\"%u %U %Y\")(date) parses numeric weekday (Monday), week number (Monday) and year", function(test) { + var p = timeFormat.timeParse("%u %W %Y"); + test.deepEqual(p("1 00 1990"), date.local(1989, 11, 25)); + test.deepEqual(p("1 01 1990"), date.local(1990, 0, 1)); + test.deepEqual(p("1 05 1991"), date.local(1991, 1, 4)); + test.deepEqual(p("7 00 1995"), date.local(1995, 0, 1)); + test.deepEqual(p("1 01 1995"), date.local(1995, 0, 2)); + test.equal(p("X 03 2010"), null); + test.end(); +}); + tape("timeParse(\"%W %Y\")(date) parses week number (Monday) and year", function(test) { var p = timeFormat.timeParse("%W %Y"); test.deepEqual(p("01 1990"), date.local(1990, 0, 1)); @@ -92,7 +103,7 @@ tape("timeParse(\"%A %W %Y\")(date) parses weekday, week number (Monday) and yea test.end(); }); -tape("timeParse(\"%w %W %Y\")(date) parses numeric weekday, week number (Monday) and year", function(test) { +tape("timeParse(\"%w %W %Y\")(date) parses numeric weekday (Sunday), week number (Monday) and year", function(test) { var p = timeFormat.timeParse("%w %W %Y"); test.deepEqual(p("1 01 1990"), date.local(1990, 0, 1)); test.deepEqual(p("0 04 1991"), date.local(1991, 1, 3)); @@ -101,6 +112,15 @@ tape("timeParse(\"%w %W %Y\")(date) parses numeric weekday, week number (Monday) test.end(); }); +tape("timeParse(\"%u %W %Y\")(date) parses numeric weekday (Monday), week number (Monday) and year", function(test) { + var p = timeFormat.timeParse("%u %W %Y"); + test.deepEqual(p("1 01 1990"), date.local(1990, 0, 1)); + test.deepEqual(p("7 04 1991"), date.local(1991, 1, 3)); + test.deepEqual(p("7 00 1995"), date.local(1995, 0, 1)); + test.equal(p("X 03 2010"), null); + test.end(); +}); + tape("timeParse(\"%m/%d/%y\")(date) parses month, date and two-digit year", function(test) { var p = timeFormat.timeParse("%m/%d/%y"); test.deepEqual(p("02/03/69"), date.local(1969, 1, 3)); diff --git a/test/utcFormat-test.js b/test/utcFormat-test.js index 5a01cf1..fd95a0c 100644 --- a/test/utcFormat-test.js +++ b/test/utcFormat-test.js @@ -179,6 +179,14 @@ tape("utcFormat(\"%L\")(date) formats zero-padded milliseconds", function(test) test.end(); }); +tape("utcFormat(\"%u\")(date) formats week day numbers", function(test) { + var f = timeFormat.utcFormat("%u"); + test.equal(f(date.utc(1990, 0, 1, 0)), "1"); + test.equal(f(date.utc(1990, 0, 7, 0)), "7"); + test.equal(f(date.utc(2010, 2, 13, 23)), "6"); + test.end(); +}); + tape("utcFormat(\"%U\")(date) formats zero-padded week numbers", function(test) { var f = timeFormat.utcFormat("%U"); test.equal(f(date.utc(1990, 0, 1, 0)), "00"); From 8efc1948b2e86b1c7be0054ff32895aff00eb95a Mon Sep 17 00:00:00 2001 From: Brian Mitchell Date: Mon, 2 Oct 2017 20:57:14 -0500 Subject: [PATCH 2/2] More concise numerical day of week parsing --- src/locale.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/locale.js b/src/locale.js index 9957e8a..4e6dce5 100644 --- a/src/locale.js +++ b/src/locale.js @@ -174,8 +174,7 @@ export default function formatLocale(locale) { // Convert day-of-week and week-of-year to day-of-year. if ("W" in d || "U" in d) { - if (!("u" in d)) d.u = "W" in d ? 1 : 7; - if (!("w" in d)) d.w = d.u === 7 ? 0 : d.u; + if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0; var day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); d.m = 0; d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;