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

Missing tests forbidding Date.parse output with fractional part #3437

Open
gibson042 opened this issue Mar 17, 2022 · 4 comments
Open

Missing tests forbidding Date.parse output with fractional part #3437

gibson042 opened this issue Mar 17, 2022 · 4 comments

Comments

@gibson042
Copy link
Contributor

gibson042 commented Mar 17, 2022

The algorithm at https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.parse requires returning a time value—"either a finite integral Number representing an instant in time to millisecond precision or NaN representing no specific instant". This should be covered by tests, to avoid violations as seen in JavaScriptCore:

$ eshost -se '
  [
    "1970-01-01T00:00:00.000500001Z",
    "1969-12-31T23:59:59.999515625Z",
    "1969-12-31T23:59:59.999015625Z",
  ]
  .map(str => {
    const tv = Date.parse(str);
    return `${str} => ${(new Date(str)).toISOString()} (${Object.is(tv, -0) ? "-0" : tv} ms from epoch)`;
  })
  .join("\n")
'
#### ChakraCore, engine262, GraalJS, Hermes, SpiderMonkey, V8
1970-01-01T00:00:00.000500001Z => 1970-01-01T00:00:00.000Z (0 ms from epoch)
1969-12-31T23:59:59.999515625Z => 1969-12-31T23:59:59.999Z (-1 ms from epoch)
1969-12-31T23:59:59.999015625Z => 1969-12-31T23:59:59.999Z (-1 ms from epoch)

#### JavaScriptCore
1970-01-01T00:00:00.000500001Z => 1970-01-01T00:00:00.000Z (0.500001 ms from epoch)
1969-12-31T23:59:59.999515625Z => 1970-01-01T00:00:00.000Z (-0.484375 ms from epoch)
1969-12-31T23:59:59.999015625Z => 1970-01-01T00:00:00.000Z (-0.984375 ms from epoch)

#### Moddable XS
1970-01-01T00:00:00.000500001Z => 1970-01-01T00:00:00.001Z (1 ms from epoch)
1969-12-31T23:59:59.999515625Z => 1970-01-01T00:00:00.000Z (0 ms from epoch)
1969-12-31T23:59:59.999015625Z => 1969-12-31T23:59:59.999Z (-1 ms from epoch)

Every engine except JavaScriptCore seems to get this right, and a bug has now been reported there: https://bugs.webkit.org/show_bug.cgi?id=238050

@Constellation
Copy link
Member

I think 0 ms for all three inputs is reasonable since TimeClip is trunc https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-timeclip

new Date(0.500001).valueOf();  // 0
new Date(-0.484375).valueOf();  // 0
new Date(-0.984375).valueOf();  // 0

@gibson042
Copy link
Contributor Author

To copy from https://bugs.webkit.org/show_bug.cgi?id=238050#c5 , Date.parse doesn't depend upon TimeClip, and couldn't even use that operation until first parsing a number from input. The above expressions bypass Date.parse, and are instead subject only to the usual treatment of non-integer input in JavaScript where integers are needed. Truncating numbers towards zero is expected, while rounding datetimes towards the start of 1970 is surprising, especially when it results in rollover of coarser unit components due to arithmetic carry (e.g., when input like "1969-…" gets mapped to 1970).

But regardless, https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.parse is underspecified and it is not the proper place of test262 to correct that. Enforcement here should be limited to verifying the absence of fractional data.

@Constellation
Copy link
Member

It looks inconsistent to me. TimeClip is designed to be used only to produce time value. It means that, ECMAScript behaves differently only when passing sub-millisecond epoch double value to Date constructor.
If floor behavior is expected for sub-millisecond time values, then I think we should also do so in TimeClip to align to that expectation.

@gibson042
Copy link
Contributor Author

gibson042 commented Mar 23, 2022

I responded at https://bugs.webkit.org/show_bug.cgi?id=238050#c7 , but the summary is that the only cases where input to TimeClip can have a nonempty fractional component correspond with source text providing a single number to a date function (Date(nonDateNumberable) and dateInstance.setTime(numberable)), where usual JavaScript conventions for deriving integers from inputs using truncation inside ToNumber are expected. So while I do think the truncation towards zero of e.g. Date(-0.9) is expected and analogous to e.g. "foo".slice(-0.9)==="foo", I don't think it is relevant to the expected behavior of Date.parse(overlyPreciseString), in which the more logical origin to which truncation should be directed is not 1970 but rather the start of time itself (i.e., towards negative infinity).

But with that, I am done with this thread. As I said above, enforcement within test262 should be limited to verifying the absence of fractional data output from Date.parse and should not be opinionated about how overly-precise input is rounded to integer (because that behavior is not specified in ECMA-262).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants