vitest icon indicating copy to clipboard operation
vitest copied to clipboard

Add `Temporal` support to functions that accept `Date`

Open beeequeue opened this issue 7 months ago • 2 comments

Clear and concise description of the problem

I'm testing out using Temporal instead of Date, and one of the pain points I found is vi.setSystemTime only accepting number | Date.

Suggested solution

Add Temporal as an option to functions that accept Date. The one I encountered was vi.setSystemTime

Alternative

As a workaround, you can convert a PlainDate[Time] to a ZonedDateTime or Instant and get the epoch time from that:

vi.setSystemTime(
  Temporal.PlainDateTime.from("2022-02-02 12:00").toZonedDateTime("utc")
    .epochMilliseconds,
)

Additional context

Some Temporal support was added in #8007 but that could be achieved without having to use the Temporal global, which I think this feature would require.

For example, (I believe) to support PlainDate in vi.setSystemTime one would have to convert it to a ZonedDatetime to get .epochMilliseconds, which might require using Temporal.Now.timeZoneId() unless you would default to "UTC".

                        // or "UTC"?
plainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds

To support this one would probably have to use temporal-polyfill in some way until V8 implements Temporal (https://github.com/nodejs/node/issues/57127#issuecomment-2762978399, https://github.com/nodejs/node/pull/57128).

Validations

beeequeue avatar Jun 05 '25 17:06 beeequeue

I am, of course, open to implementing this if given enough context. 😊

beeequeue avatar Jun 09 '25 16:06 beeequeue

Also linking https://github.com/nodejs/node/issues/57891, which seems to be discussing the general idea of extending number | Date API to number | Date | Temporal.xxx on Node. It looks like we could only extend to number | Date | Temporal.Instant, so don't have to deal with Temporal.PlainDateTime which is inherently ambiguous.

hi-ogawa avatar Jun 09 '25 23:06 hi-ogawa

Hi - I'm one of the Temporal proposal's champions on TC39. I agree with @hi-ogawa that using Temporal.Instant is good (and Temporal.PlainDateTime is bad) in this context, for exactly the ambiguity reasons cited.

I'd consider accepting Temporal.ZonedDateTime too because that's also not ambiguous.

Note that Temporal has nanoseconds precision (although not in polyfills that depend on Date under the covers). If the goal is just to emulate what Date provides then milliseconds is fine. But you'll want to be careful about precision mismatch, e.g. when comparing a Temporal.Instant to a Date, because even if instant.epochMilleseconds === date.getTime(), that doesn't mean that instant represents exactly the same time as date.

justingrant avatar Aug 11 '25 04:08 justingrant

Since only exact time (epoch) is relevant (date, time, and time zone are irrelevant) in this context, accepting only Temporal.Instant would be appropriate from the perspective of semantics. Note that it is very easy and straightforward to convert from Temporal.ZonedDateTime to Temporal.Instant (just call toInstant method without any arguments).

fabon-f avatar Aug 12 '25 14:08 fabon-f

Yep. Given that Temporal.ZonedDateTime is never ambiguous and (for purposes of Date-compatibility) has the identical epochMilliseconds / epochNanoseconds API, is there any reason to not accept both types?

justingrant avatar Aug 12 '25 17:08 justingrant

As a note, chai supports Temporal equality: https://github.com/chaijs/deep-eql/blob/2dae026aac30517d9649a51aa6e807ba9aa88787/index.js#L252

So functions like expect(plainDate).to.eq(anotherPlainDate) should already work

sheremet-va avatar Sep 04 '25 01:09 sheremet-va