diff --git a/boot/boot.js b/boot/boot.js index 97bf73837..f6341dab0 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -305,7 +305,12 @@ $tw.utils.stringifyDate = function(value) { // Parse a date from a UTC YYYYMMDDHHMMSSmmm format string $tw.utils.parseDate = function(value) { if(typeof value === "string") { - var year = parseInt(value.substr(0,4),10), + var negative = 1; + if(value.charAt(0) === "-") { + negative = -1; + value = value.substr(1); + } + var year = parseInt(value.substr(0,4),10) * negative, d = new Date(Date.UTC(year, parseInt(value.substr(4,2),10)-1, parseInt(value.substr(6,2),10), diff --git a/core/modules/utils/utils.js b/core/modules/utils/utils.js index a606c2a2a..b3c56fb8c 100644 --- a/core/modules/utils/utils.js +++ b/core/modules/utils/utils.js @@ -302,7 +302,7 @@ exports.formatDateString = function(date,template) { return $tw.utils.pad($tw.utils.getHours12(date)); }], [/^wYYYY/, function() { - return $tw.utils.getYearForWeekNo(date); + return $tw.utils.pad($tw.utils.getYearForWeekNo(date),4); }], [/^hh12/, function() { return $tw.utils.getHours12(date); @@ -311,7 +311,14 @@ exports.formatDateString = function(date,template) { return date.getDate() + $tw.utils.getDaySuffix(date); }], [/^YYYY/, function() { - return date.getFullYear(); + return $tw.utils.pad(date.getFullYear(),4); + }], + [/^aYYYY/, function() { + return $tw.utils.pad(Math.abs(date.getFullYear()),4); + }], + [/^\{era:([^,\|}]*)\|([^}\|]*)\|([^}]*)\}/, function(match) { + var year = date.getFullYear(); + return year === 0 ? match[2] : (year < 0 ? match[1] : match[3]); }], [/^0hh/, function() { return $tw.utils.pad(date.getHours()); @@ -400,7 +407,7 @@ exports.formatDateString = function(date,template) { $tw.utils.each(matches, function(m) { var match = m[0].exec(t); if(match) { - matchString = m[1].call(); + matchString = m[1].call(null,match); t = t.substr(match[0].length); return false; } diff --git a/editions/test/tiddlers/tests/test-utils.js b/editions/test/tiddlers/tests/test-utils.js index ec60a6691..d57b0e0dc 100644 --- a/editions/test/tiddlers/tests/test-utils.js +++ b/editions/test/tiddlers/tests/test-utils.js @@ -25,6 +25,16 @@ describe("Utility tests", function() { expect(psa(" [[Tidd\u00a0ler8]] two ")).toEqual(["Tidd\u00a0ler8","two"]); }); + it("should handle parsing a date", function() { + var pd = function(v) { + return $tw.utils.parseDate(v).toString(); + }; + expect(pd("20150428204930183")).toEqual("Tue Apr 28 2015 21:49:30 GMT+0100 (British Summer Time)"); + expect(pd("-20150428204930183")).toEqual("Sun Apr 28 -2015 20:48:15 GMT-0001 (British Summer Time)"); + expect(pd("00730428204930183")).toEqual("Fri Apr 28 0073 20:48:15 GMT-0001 (British Summer Time)"); + expect(pd("-00730428204930183")).toEqual("Thu Apr 28 -0073 20:48:15 GMT-0001 (British Summer Time)"); + }); + it("should handle base64 encoding emojis", function() { var booksEmoji = "📚"; expect(booksEmoji).toBe(booksEmoji); @@ -62,6 +72,8 @@ describe("Utility tests", function() { var fds = $tw.utils.formatDateString, // nov is month: 10! d = new Date(2014,10,9,17,41,28,542); + expect(fds(d,"{era:bce||ce}")).toBe("ce"); + expect(fds(d,"YYYY")).toBe("2014"); expect(fds(d,"DDD DD MMM YYYY")).toBe("Sunday 9 November 2014"); expect(fds(d,"ddd hh mm ssss")).toBe("Sun 17 41 2828"); expect(fds(d,"MM0DD")).toBe("1109"); @@ -92,6 +104,19 @@ describe("Utility tests", function() { d = new Date(2014,11,29,23,59,59); expect(fds(d,"WW")).toBe("1"); expect(fds(d,"wYYYY")).toBe("2015"); + + // Negative years + d = new Date(-2014,10,9,17,41,28,542); + expect(fds(d,"YYYY")).toBe("-2014"); + expect(fds(d,"aYYYY")).toBe("2014"); + expect(fds(d,"{era:bce||ce}")).toBe("bce"); + + // Zero years + d = new Date(0,10,9,17,41,28,542); + d.setUTCFullYear(0); // See https://stackoverflow.com/a/5870822 + expect(fds(d,"YYYY")).toBe("0000"); + expect(fds(d,"aYYYY")).toBe("0000"); + expect(fds(d,"{era:bce|z|ce}")).toBe("z"); }); it("should parse text references", function() { diff --git a/editions/tw5.com/tiddlers/concepts/Date Fields.tid b/editions/tw5.com/tiddlers/concepts/Date Fields.tid deleted file mode 100644 index b1dcbe82d..000000000 --- a/editions/tw5.com/tiddlers/concepts/Date Fields.tid +++ /dev/null @@ -1,28 +0,0 @@ -created: 20150117190213631 -modified: 20150124214537000 -tags: Concepts -title: Date Fields -type: text/vnd.tiddlywiki - -Certain [[fields|TiddlerFields]] of a tiddler are used to store dates and times. - -The two standard date fields are <<.field created>> and <<.field modified>>. - -Values of date fields are 17-character strings: - -* 4 digits for the year -* 2 digits for the month -* 2 digits for the day -* 2 digits for the hour -* 2 digits for the minute -* 2 digits for the second -* 3 digits for the millisecond - -To avoid problems arising from differences of time zone, TiddlyWiki always uses [[UTC|https://en.wikipedia.org/wiki/Coordinated_Universal_Time]]. - -As an example, the <<.field created>> field of this tiddler has the value <<.value """<$view field="created"/>""">>. - -Dates can be [[converted to other formats|DateFormat]] for display: - -<$macrocall $name="wikitext-example-without-html" -src="""<$view field="created" format="date" template="DDD DDth MMM YYYY"/>"""> diff --git a/editions/tw5.com/tiddlers/features/DateFormat.tid b/editions/tw5.com/tiddlers/features/DateFormat.tid deleted file mode 100644 index 4d138e576..000000000 --- a/editions/tw5.com/tiddlers/features/DateFormat.tid +++ /dev/null @@ -1,48 +0,0 @@ -created: 20140418142957325 -modified: 20180730201626985 -tags: Features -title: DateFormat -type: text/vnd.tiddlywiki - -When used to display date values (with the `format` attribute set to ''date''), the ViewWidget accepts a `template` attribute that allows the format of the date values to be specified. The format string is processed with the following substitutions: - -|!Token |!Substituted Value | -|`DDD` |Day of week in full (eg, "Monday") | -|`ddd` |Short day of week (eg, "Mon") | -|`DD` |Day of month | -|`0DD` |Adds a leading zero | -|`DDth` |Adds a suffix | -|`WW` |ISO-8601 week number of year | -|`0WW` |Adds a leading zero | -|`MMM` |Month in full (eg, "July") | -|`mmm` |Short month (eg, "Jul") | -|`MM` |Month number | -|`0MM` |Adds leading zero | -|`YYYY` |Full year | -|`YY` |Two digit year | -|`wYYYY` |Full year with respect to week number | -|`wYY` |Two digit year with respect to week number | -|`hh` |Hours | -|`0hh` |Adds a leading zero | -|`hh12` |Hours in 12 hour clock | -|`0hh12` |Hours in 12 hour clock with leading zero | -|`mm` |Minutes | -|`0mm` |Minutes with leading zero | -|`ss` |Seconds | -|`0ss` |Seconds with leading zero | -|`XXX` |Milliseconds | -|`0XXX` |Milliseconds with leading zero | -|`am` or `pm` |Lower case AM/PM indicator | -|`AM` or `PM` |Upper case AM/PM indicator | -|`TZD` |Timezone offset | -|`\x` |Used to escape a character that would otherwise have special meaning | -|`[UTC]`|Time-shift the represented date to UTC. Must be at very start of format string| - -Note that other text is passed through unchanged, allowing commas, colons or other separators to be used. - -! Examples - -|!Template |!Output | -|`DDth MMM YYYY` |16th February 2011 | -|`DDth MMM \M\M\M YYYY` |16th February MMM 2011 | -|`DDth mmm YYYY 0hh:0mm:0ss` |16th Feb 2011 11:38:42 |