Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Date.to(UTC)String() outputs match web reality and spec language #4067

Merged
merged 1 commit into from
Nov 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: newline after this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general the above function is a bit ugly but I understand the need to implement ~ this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't super clear from the read that the reason for converting the input number to uint16 is so that it is compatible with the char16 _u('0'). Can you add a comment explaining? What will behavior look like for years > 4 digits and > MAX_UINT16 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I fixed it by moving the static_cast to where the int32 value is assigned to char16, for readability and avoided > MAX_UINT16 issue.


//
// 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 @@ -140,4 +140,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" });