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

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: withSameInstant, duration, offset, zone, iana, withZone, utc, time, convert, timezone, datetime