Skip to content

Commit

Permalink
[1.8>master] [MERGE #4067 @xiaoyinl] Make Date.to(UTC)String() output…
Browse files Browse the repository at this point in the history
…s match web reality and spec language

Merge pull request #4067 from xiaoyinl:parse_own_toString

Ref #4178

[Sec 20.3.3.2](https://tc39.github.io/ecma262/#sec-date.parse) requires `Date.parse` should be able to parse the values returned by `Date.toString()`, `Date.toUTCString()` and `Date.toISOString()` in each engine's own implementation. In ChakraCore, if the year is <100, `toString()` and `toUTCString()` don't pad the year to 4 digits, and thus `Date.parse` can't parse them.

This PR makes two changes:
1. If the absolute value of the year is less than 1000, pad it to 4 digits
2. For a BC year, output negative year, rather than positive year + "B.C."
  • Loading branch information
dilijev committed Nov 22, 2017
2 parents b3e57b9 + f09c147 commit 30082da
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 53 deletions.
9 changes: 5 additions & 4 deletions lib/Runtime/Library/DateImplementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,15 @@ namespace Js {
bs->AppendChars(_u(' '));

// Add the year.
if (pymd->year > 0)
if ((pymd->year) > 0)
{
bs->AppendChars(pymd->year, 10, ConvertLongToString);
bs->AppendChars(pymd->year, 10, ConvertUInt32ToString_ZeroPad_4);
}
else
{
bs->AppendChars(1 - pymd->year, 10, ConvertLongToString);
bs->AppendChars(_u(" B.C."));
int positiveYear = -(pymd->year); // pymd->year is negative
bs->AppendChars(_u('-'));
bs->AppendChars(positiveYear, 10, ConvertUInt32ToString_ZeroPad_4);
}

// Add the time.
Expand Down
45 changes: 44 additions & 1 deletion lib/Runtime/Library/DateImplementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,40 @@ namespace Js {
return GetDateDefaultString<StringBuilder>(&ymd, &tzd, DateTimeFlag::None, scriptContext, newStringBuilder);
}

const auto ConvertUInt32ToString_ZeroPad_4 = [](const uint32 value, char16 *const buffer, const CharCount charCapacity)
{
Assert(charCapacity >= 4);
if (value < 10)
{
buffer[0] = _u('0');
buffer[1] = _u('0');
buffer[2] = _u('0');
buffer[3] = static_cast<char16>(value + _u('0'));
buffer[4] = 0;
}
else if (value < 100)
{
buffer[0] = _u('0');
buffer[1] = _u('0');
buffer[2] = static_cast<char16>((value / 10) + _u('0'));
buffer[3] = static_cast<char16>((value % 10) + _u('0'));
buffer[4] = 0;
}
else if (value < 1000)
{
buffer[0] = _u('0');
buffer[1] = static_cast<char16>((value / 100) + _u('0'));
buffer[2] = static_cast<char16>(((value / 10) % 10) + _u('0'));
buffer[3] = static_cast<char16>((value % 10) + _u('0'));
buffer[4] = 0;
}
else
{
const errno_t err = _ultow_s(value, buffer, charCapacity, 10);
Assert(err == 0);
}
};

//
// Get default date string, shared with hybrid debugging.
// StringBuilder: A Js::StringBuilder/CompoundString like class, used to build strings.
Expand Down Expand Up @@ -418,7 +452,16 @@ namespace Js {
bs->AppendChars(_u(' '));

// year is directly after day, month, daydigit for IE11+
bs->AppendChars(pymd->year, 10, ConvertLongToString);
if ((pymd->year) > 0)
{
bs->AppendChars(pymd->year, 10, ConvertUInt32ToString_ZeroPad_4);
}
else
{
int positiveYear = -(pymd->year); // pymd->year is negative
bs->AppendChars(_u('-'));
bs->AppendChars(positiveYear, 10, ConvertUInt32ToString_ZeroPad_4);
}

if(!(noDateTime & DateTimeFlag::NoTime))
{
Expand Down
5 changes: 3 additions & 2 deletions test/Date/DateParse2.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
myPrint("A --");
testDate(new Date(-2012, 1, 2, 1, 2, 3));
testParseDate(new Date(-2012, 1, 2, 1, 2, 3).toString());
testParseDate(new Date(-2012, 1, 2, 1, 2, 3).toUTCString());
// Disabled due to https://github.com/Microsoft/ChakraCore/issues/4300
//testParseDate(new Date(-2012, 1, 2, 1, 2, 3).toUTCString());
testParseDate(new Date(-2012, 1, 2, 1, 2, 3).toISOString());

myPrint("B --");
Expand All @@ -26,7 +27,7 @@ testParseDate(new Date(99999, 1, 2, 1, 2, 3).toISOString());
myPrint("D --");
testDate(new Date(-99999, 1, 2, 1, 2, 3));
testParseDate(new Date(-99999, 1, 2, 1, 2, 3).toString());
testParseDate(new Date(-99999, 1, 2, 1, 2, 3).toUTCString());
//testParseDate(new Date(-99999, 1, 2, 1, 2, 3).toUTCString());
testParseDate(new Date(-99999, 1, 2, 1, 2, 3).toISOString());

myPrint("E --");
Expand Down
72 changes: 26 additions & 46 deletions test/Date/DateParse2.v5.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ A --
Date string: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
raw: -125657017077000
toString: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toUTCString: Tue, 02 Feb -2012 09:02:03 GMT
toGMTString: Tue, 02 Feb -2012 09:02:03 GMT
toISOString: -002012-02-02T09:02:03.000Z
2 -125657017077000 480
-2012/1/2
Expand All @@ -13,18 +13,8 @@ Date string: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
Date string: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
raw: -125657017077000
toString: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toISOString: -002012-02-02T09:02:03.000Z
2 -125657017077000 480
-2012/1/2
1:2:3.0

Date string: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
raw: -125657017077000
toString: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toUTCString: Tue, 02 Feb -2012 09:02:03 GMT
toGMTString: Tue, 02 Feb -2012 09:02:03 GMT
toISOString: -002012-02-02T09:02:03.000Z
2 -125657017077000 480
-2012/1/2
Expand All @@ -33,8 +23,8 @@ Date string: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
Date string: -002012-02-02T09:02:03.000Z
raw: -125657017077000
toString: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toUTCString: Tue, 02 Feb -2012 09:02:03 GMT
toGMTString: Tue, 02 Feb -2012 09:02:03 GMT
toISOString: -002012-02-02T09:02:03.000Z
2 -125657017077000 480
-2012/1/2
Expand Down Expand Up @@ -126,8 +116,8 @@ D --
Date string: Fri Feb 02 -99999 01:02:03 GMT-0800 (Pacific Standard Time)
raw: -3217827999477000
toString: Fri Feb 02 -99999 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toGMTString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toUTCString: Fri, 02 Feb -99999 09:02:03 GMT
toGMTString: Fri, 02 Feb -99999 09:02:03 GMT
toISOString: -099999-02-02T09:02:03.000Z
2 -3217827999477000 480
-99999/1/5
Expand All @@ -136,18 +126,8 @@ Date string: Fri Feb 02 -99999 01:02:03 GMT-0800 (Pacific Standard Time)
Date string: Fri Feb 02 -99999 01:02:03 GMT-0800 (Pacific Standard Time)
raw: -3217827999477000
toString: Fri Feb 02 -99999 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toGMTString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toISOString: -099999-02-02T09:02:03.000Z
2 -3217827999477000 480
-99999/1/5
1:2:3.0

Date string: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
raw: -3217827999477000
toString: Fri Feb 02 -99999 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toGMTString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toUTCString: Fri, 02 Feb -99999 09:02:03 GMT
toGMTString: Fri, 02 Feb -99999 09:02:03 GMT
toISOString: -099999-02-02T09:02:03.000Z
2 -3217827999477000 480
-99999/1/5
Expand All @@ -156,45 +136,45 @@ Date string: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
Date string: -099999-02-02T09:02:03.000Z
raw: -3217827999477000
toString: Fri Feb 02 -99999 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toGMTString: Fri, 02 Feb 100000 B.C. 09:02:03 GMT
toUTCString: Fri, 02 Feb -99999 09:02:03 GMT
toGMTString: Fri, 02 Feb -99999 09:02:03 GMT
toISOString: -099999-02-02T09:02:03.000Z
2 -3217827999477000 480
-99999/1/5
1:2:3.0

E --
Date string: Tue Feb 02 -12 01:02:03 GMT-0800 (Pacific Standard Time)
Date string: Tue Feb 02 -0012 01:02:03 GMT-0800 (Pacific Standard Time)
raw: -62543113077000
toString: Tue Feb 02 -12 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 13 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 13 B.C. 09:02:03 GMT
toString: Tue Feb 02 -0012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb -0012 09:02:03 GMT
toGMTString: Tue, 02 Feb -0012 09:02:03 GMT
toISOString: -000012-02-02T09:02:03.000Z
2 -62543113077000 480
-12/1/2
1:2:3.0

Date string: Tue Feb 02 -12 01:02:03 GMT-0800 (Pacific Standard Time)
Date string: Tue Feb 02 -0012 01:02:03 GMT-0800 (Pacific Standard Time)
raw: -62543113077000
toString: Tue Feb 02 -12 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 13 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 13 B.C. 09:02:03 GMT
toString: Tue Feb 02 -0012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb -0012 09:02:03 GMT
toGMTString: Tue, 02 Feb -0012 09:02:03 GMT
toISOString: -000012-02-02T09:02:03.000Z
2 -62543113077000 480
-12/1/2
1:2:3.0

Date string: Tue, 02 Feb 13 B.C. 09:02:03 GMT
Date string: Tue, 02 Feb -0012 09:02:03 GMT
raw: NaN
toString: Invalid Date
toUTCString: Invalid Date
toGMTString: Invalid Date

Date string: -000012-02-02T09:02:03.000Z
raw: -62543113077000
toString: Tue Feb 02 -12 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 13 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 13 B.C. 09:02:03 GMT
toString: Tue Feb 02 -0012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb -0012 09:02:03 GMT
toGMTString: Tue, 02 Feb -0012 09:02:03 GMT
toISOString: -000012-02-02T09:02:03.000Z
2 -62543113077000 480
-12/1/2
Expand Down Expand Up @@ -295,8 +275,8 @@ Date string: Tue Feb 02 2012 01:02:03 GMT+0430 (prisec@)
Date string: Tue Feb 2 01:02:03 PST 2013 B.C.
raw: -125657017077000
toString: Tue Feb 02 -2012 01:02:03 GMT-0800 (Pacific Standard Time)
toUTCString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toGMTString: Tue, 02 Feb 2013 B.C. 09:02:03 GMT
toUTCString: Tue, 02 Feb -2012 09:02:03 GMT
toGMTString: Tue, 02 Feb -2012 09:02:03 GMT
toISOString: -002012-02-02T09:02:03.000Z
2 -125657017077000 480
-2012/1/2
Expand Down
8 changes: 8 additions & 0 deletions test/Date/rlexe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,12 @@
<files>TwoDigitYears.js</files>
</default>
</test>
<test>
<default>
<files>toStringAndToUTCStringYearPadding.js</files>
<!-- test is timezone-sensitive; remove exclude_jenkins after fix (Microsoft/ChakraCore#319) -->
<tags>exclude_jenkins</tags>
<compile-flags>-args summary -endargs</compile-flags>
</default>
</test>
</regress-exe>
47 changes: 47 additions & 0 deletions test/Date/toStringAndToUTCStringYearPadding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

// For dates whose years are less than 1000, Date.toString() and Date.toUTCString() should pad the years
// to 4 digits.
// See https://github.com/Microsoft/ChakraCore/pull/4067

/// <reference path="../UnitTestFramework/UnitTestFramework.js" />
if (this.WScript && this.WScript.LoadScriptFile) { // Check for running in ch
this.WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
}

function testDate(DateObj, toStringExpected, toUTCStringExpected) {
assert.areEqual(toStringExpected, DateObj.toString(), "Date.toString() returns invalid value.");
assert.areEqual(toUTCStringExpected, DateObj.toUTCString(), "Date.toUTCString() returns invalid value.");
}

let tests = [{
name: "test if Date.toString() and Date.toUTCString() pad positive years to four digits",
body: function () {
testDate(new Date("0001-10-13T05:16:33Z"), "Fri Oct 12 0001 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Sat, 13 Oct 0001 05:16:33 GMT");
testDate(new Date("0011-10-13T05:16:33Z"), "Wed Oct 12 0011 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Thu, 13 Oct 0011 05:16:33 GMT");
testDate(new Date("0111-10-13T05:16:33Z"), "Mon Oct 12 0111 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Tue, 13 Oct 0111 05:16:33 GMT");
testDate(new Date("1111-10-13T05:16:33Z"), "Thu Oct 12 1111 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Fri, 13 Oct 1111 05:16:33 GMT");
}
},
{
name: "test if Date.toString() and Date.toUTCString() pad negative years to four digits",
body: function () {
testDate(new Date("-000001-10-13T05:16:33Z"), "Tue Oct 12 -0001 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Wed, 13 Oct -0001 05:16:33 GMT");
testDate(new Date("-000011-10-13T05:16:33Z"), "Thu Oct 12 -0011 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Fri, 13 Oct -0011 05:16:33 GMT");
testDate(new Date("-000111-10-13T05:16:33Z"), "Sat Oct 12 -0111 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Sun, 13 Oct -0111 05:16:33 GMT");
testDate(new Date("-001111-10-13T05:16:33Z"), "Wed Oct 12 -1111 22:16:33 GMT-0700 (Pacific Daylight Time)",
"Thu, 13 Oct -1111 05:16:33 GMT");
}
}];

testRunner.run(tests, { verbose: WScript.Arguments[0] != "summary" });

0 comments on commit 30082da

Please sign in to comment.