Skip to content

ZonedDateTime within a timeline overlap changes the instant it represents when passed through the polyglot boundary #4918

Open
@radeusgd

Description

@radeusgd

Describe GraalVM and your environment :

  • GraalVM version or commit id if built from source: 21.3.0
  • CE or EE: CE
  • JDK version: JDK11
  • OS and OS Version: Ubuntu 22.04
  • Architecture: amd64
  • The output of java -Xinternalversion:
OpenJDK 64-Bit Server VM (11.0.13+7-jvmci-21.3-b05) for linux-amd64 JRE (11.0.13+7-jvmci-21.3-b05), built on Oct 16 2021 12:17:09 by "buildslave" with gcc 7.3.0

Have you verified this issue still happens when using the latest snapshot?

No.

Describe the issue

The issue is that in the InteropLibrary the datetime consists only of a Time, Date and a TimeZone. This is however not always enough and can be a source of ambiguity - to have an unambiguous representation in all cases, the offset is also necessary.

The issue shows during the autumn Daylight Saving Time switch - when the two timelines overlap and times like 2:30am can mean two moments in time. At such moment, the timezone is not enough to unambiguously pinpoint the time instant - the offset is needed too.

Currently, the InteropLibrary only allows to expose the Date, Time and TimeZone, so there's no way for a representation of a date-time in a Truffle language to also expose the zone. Thus if a ZonedDateTime representing such an ambiguous location in time is passed to such language and then converted back to Java, it necessarily loses information.

See the HostToTypeNode::asJavaObject method, HostToTypeNode.java:464:

else if (targetType == ZonedDateTime.class) {
    if (interop.isDate(value) && interop.isTime(value) && interop.isTimeZone(value)) {
        LocalDate date;
        LocalTime time;
        ZoneId timeZone;
        try {
            date = interop.asDate(value);
            time = interop.asTime(value);
            timeZone = interop.asTimeZone(value);
        } catch (UnsupportedMessageException e) {
            throw shouldNotReachHere(e);
        }
        obj = createZonedDateTime(date, time, timeZone);
    }
    
...

@TruffleBoundary
private static ZonedDateTime createZonedDateTime(LocalDate date, LocalTime time, ZoneId timeZone) {
    return ZonedDateTime.of(date, time, timeZone);
}

Note that when using ZonedDateTime.of(date, time, timeZone) we lose the offset information. To unambiguously migrate such instant in time, the ZonedDateTime.ofLocal(datetime, timezone, offset) should be used.

Thus, I would like to suggest if it is possible to add ZoneOffset support to the polyglot mechanism, so that datetimes can register to also expose the offset and allow it to be used when reconstructing the ZonedDateTime.

I don't have an exact repro, as I couldn't quickly find a way to handle a Java date on the side of JS, we are encountering this issue in Enso, for example see the following test suite.

To make the issue a bit more clear, I can show the following +- steps of action:

var polyglotMethod; // assume a polyglot method that takes a ZonedDateTime, converts it into a polyglot value of some guest language and then converts it back into ZonedDateTime

var tz = ZoneId.of("Europe/Warsaw");

// 2:30 am before DST switch: 2022-10-30T02:30:00+02:00[Europe/Warsaw]
var dt1 = ZonedDateTime.of(2022, 10, 30, 2, 30, 0, 0, tz);

// 2:30 am after DST switch (note the offset changed to +01:00): 2022-10-30T02:30+01:00[Europe/Warsaw]
var dt2 = dt1.plusHours(1);

// Note how these will differ by 3600.
System.out.println(dt1.toEpochSeconds());
System.out.println(dt2.toEpochSeconds());

var dt1Prime = polyglotMethod.execute(dt1);
var dt2Prime = polyglotMethod.execute(dt2);

// And afterwards, both datetimes will point at the instant in time associated with `dt1`. The distinction of `dt2` has been lost.
System.out.println(dt1Prime.toEpochSeconds());
System.out.println(dt2Prime.toEpochSeconds());

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions