How do I handle timezones in EK9?

← Date, Time, and Duration · Ref: Q541

DateTime is EK9's timezone-aware type. It always carries a timezone. Use withSameInstant() to convert between timezones for display, and withZone() to reinterpret the clock reading in a different zone.

TIMEZONE IN LITERALS

UTC: 2024-06-15T10:30:00Z (the Z suffix means UTC)
Offset: 2024-06-15T10:30:00-05:00 (five hours behind UTC)
Offset: 2024-06-15T10:30:00+05:30 (India Standard Time)

TIMEZONE ACCESSORS

zone() returns the timezone string: 'Z', '-05:00', '+05:30'
offSetFromUTC() returns the offset as a Duration: PT0S for UTC, PT-5H for -05:00

CONVERTING TIMEZONES

withSameInstant(zoneId) converts the DISPLAY to another timezone while preserving the actual moment in time. The clock reading changes but the instant stays the same:

  utcMeeting <- 2024-06-15T10:30:00Z
  nyTime <- utcMeeting.withSameInstant("America/New_York")
  //nyTime is 2024-06-15T06:30:00-04:00 (same instant, different clock)

withZone(zoneId) changes the timezone label WITHOUT converting the time. The clock reading stays but the instant changes:

  labeled <- utcMeeting.withZone("America/New_York")
  //labeled is 2024-06-15T10:30:00-04:00 (same clock, different instant)

See Q546 for a detailed comparison of withSameInstant vs withZone.

IANA TIMEZONE NAMES

EK9 supports standard IANA timezone names:

  ["America/New_York", "Europe/London", "Asia/Tokyo", "Australia/Sydney"]

Also supports UTC offsets: 'UTC', 'UTC+5', 'UTC-8'

See Q545 for timezone conversion patterns. See Q547 for UTC storage best practices. See Q548 for comparing across timezones. See Q553 for common timezone mistakes.

Example

#!ek9
defines module qa.handle.timezones

  defines program
    HandleTimezonesDemo()
      stdout <- Stdout()

      // UTC literal
      utcMeeting <- 2024-06-15T10:30:00Z
      stdout.println(`UTC: ${utcMeeting}`)
      stdout.println(`Zone: ${utcMeeting.zone()}`)
      stdout.println(`Offset: ${utcMeeting.offSetFromUTC()}`)

      // Offset literals
      estEvent <- 2024-06-15T10:30:00-05:00
      indiaEvent <- 2024-06-15T10:30:00+05:30
      stdout.println(`EST: ${estEvent}, zone: ${estEvent.zone()}`)
      stdout.println(`IST: ${indiaEvent}, zone: ${indiaEvent.zone()}`)

      // withSameInstant: same moment, different clock
      nyTime <- utcMeeting.withSameInstant("America/New_York")
      tokyoTime <- utcMeeting.withSameInstant("Asia/Tokyo")
      londonTime <- utcMeeting.withSameInstant("Europe/London")
      stdout.println(`NY: ${nyTime}`)
      stdout.println(`Tokyo: ${tokyoTime}`)
      stdout.println(`London: ${londonTime}`)

      // withZone: same clock, different timezone label
      relabeled <- utcMeeting.withZone("America/New_York")
      stdout.println(`Relabeled: ${relabeled}`)

      // The key difference:
      // withSameInstant changes the clock to show the same moment
      // withZone keeps the clock and changes the timezone
      // So nyTime and relabeled show different times!
      stdout.println(`Same instant NY hour: ${nyTime.hour()}`)
      stdout.println(`Relabeled NY hour: ${relabeled.hour()}`)

      // Offset accessor returns Duration
      estOffset <- estEvent.offSetFromUTC()
      stdout.println(`EST offset: ${estOffset}`)

Common mistakes

E50060 — DateTime has no toTimezone() method. Use withSameInstant() to convert a DateTime to another timezone while preserving the same instant. See ek9 -h E50060 for details.

Incorrect:

nyTime <- utcMeeting.toTimezone("America/New_York")

Correct:

nyTime <- utcMeeting.withSameInstant("America/New_York")
Other ways to ask this
  • How does EK9 handle timezone-aware dates?
  • How do I create a DateTime with a specific timezone?
  • What timezone formats does EK9 support?

Coming from another language?

Java: ZonedDateTime with ZoneId, withZoneSameInstant() and withZoneSameLocal() (confusing names). Python: datetime with pytz/zoneinfo, astimezone() for conversion. JavaScript: no built-in timezone support, Intl.DateTimeFormat or moment-timezone. Go: time.In(location) for conversion. Rust: chrono with_timezone(). EK9: DateTime built-in with zone(), withSameInstant() and withZone(), IANA names supported.

Keywords: convert, datetime, duration, iana, offset, time, timezone, utc, withSameInstant, withZone, zone