What is the difference between withSameInstant() and withZone() in EK9?

← Date, Time, and Duration · Ref: Q546

These two methods serve fundamentally different purposes. Confusing them is one of the most common timezone bugs.

withSameInstant(zoneId): SAME MOMENT, DIFFERENT CLOCK
Converts the display to show the same physical instant in a different timezone. The moment in time stays the same, but the clock reading changes:

  10:00 UTC .withSameInstant('America/New_York') = 06:00 EDT
  Same moment: both represent the same point on the timeline.
  Use case: 'What time is it in New York RIGHT NOW?'

withZone(zoneId): SAME CLOCK, DIFFERENT MOMENT
Keeps the clock reading (hour, minute, second) but changes the timezone label. This creates a DIFFERENT moment in time:

  10:00 UTC .withZone('America/New_York') = 10:00 EDT
  Different moment: 10:00 UTC and 10:00 EDT are 4 hours apart.
  Use case: 'The meeting is at 10:00 in the New York office' (when you have the local time as UTC by mistake).

THE CRITICAL DIFFERENCE

withSameInstant: preserves the INSTANT, changes the DISPLAY
withZone: preserves the DISPLAY, changes the INSTANT

Most timezone work uses withSameInstant. Use withZone only when you know the clock reading is correct but the timezone label is wrong (e.g., importing data where times were recorded in local time but stored as UTC).

See Q541 for timezone basics. See Q545 for timezone conversion patterns. See Q547 for UTC storage practices. See Q553 for common timezone mistakes.

Example

defines module qa.withsameinstant.vs.withzone

  defines constant
    newYorkZone <- "America/New_York"

  defines program
    WithSameInstantVsWithZoneDemo()
      stdout <- Stdout()

      utcTime <- 2024-06-15T10:00:00Z
      stdout.println(`Original UTC: ${utcTime}`)

      // withSameInstant: same moment, different clock
      nyInstant <- utcTime.withSameInstant(newYorkZone)
      stdout.println(`withSameInstant NY: ${nyInstant}`)
      stdout.println(`  Hour: ${nyInstant.hour()}`)
      // The hour changes (10:00 UTC -> 06:00 EDT)
      // But they represent the SAME moment
      require utcTime == nyInstant

      // withZone: same clock, different moment
      nyZone <- utcTime.withZone(newYorkZone)
      stdout.println(`withZone NY: ${nyZone}`)
      stdout.println(`  Hour: ${nyZone.hour()}`)
      // The hour stays 10 but the timezone changes
      // They represent DIFFERENT moments (4 hours apart)
      require utcTime <> nyZone

      // Visual comparison
      stdout.println("---")
      stdout.println(`UTC:             ${utcTime}`)
      stdout.println(`Same instant NY: ${nyInstant}`)
      stdout.println(`Same clock NY:   ${nyZone}`)

      // The difference between the two results
      instantDiff <- nyZone - nyInstant
      stdout.println(`Difference: ${instantDiff}`)

      // Real-world example: Tokyo office meeting at 15:00 local
      tokyoMeeting <- 2024-06-15T15:00:00+09:00
      // What time should NY team join? (withSameInstant)
      nyJoinTime <- tokyoMeeting.withSameInstant(newYorkZone)
      stdout.println(`Tokyo 15:00 = NY ${nyJoinTime.hour()}:00`)

Common mistakes

E50060 — DateTime has no withZoneSameInstant() method (that is the Java name). EK9 uses the clearer name withSameInstant(). See ek9 -h E50060 for details.

Incorrect:

nyInstant <- utcTime.withZoneSameInstant(newYorkZone)

Correct:

nyInstant <- utcTime.withSameInstant(newYorkZone)

E50001 — Renaming the variable means later references to 'nyInstant' become unresolved, triggering E50001. See ek9 -h E50001 for details.

Incorrect:

nyInstantXYZ <- utcTime.withSameInstant(newYorkZone)

Correct:

nyInstant <- utcTime.withSameInstant(newYorkZone)
Other ways to ask this
  • When should I use withSameInstant vs withZone?
  • How do withSameInstant and withZone differ?
  • Why does EK9 have two timezone methods?

Coming from another language?

Java: withZoneSameInstant() vs withZoneSameLocal() (confusing names, easy to mix up). Python: astimezone() for same-instant, replace(tzinfo=) for same-clock (dangerous). JavaScript: no built-in distinction. Go: In() for same-instant only. Rust: chrono with_timezone() for same-instant. EK9: withSameInstant() and withZone() with clear descriptive names.

Keywords: timezone, withZone, duration, convert, display, time, moment, instant, withSameInstant, clock