How does Time wrapping work in EK9?

← Date, Time, and Duration · Ref: Q556

Time wraps at the 24-hour boundary. Adding time past midnight wraps to the next day's time. Time is a circular clock, not a linear timeline.

BASIC WRAPPING

  22:00 + PT3H = 01:00 (wraps past midnight)
  01:00 - PT3H = 22:00 (wraps backwards past midnight)

Time always stays within 00:00:00 to 23:59:59.

WHY WRAPPING

Time represents a position on the clock face, not an absolute point in time. A clock does not stop at midnight; it wraps to 00:00. This models the real world correctly: if it is 22:00 and you wait 3 hours, the clock shows 01:00.

WRAPPING WITH INCREMENT/DECREMENT

  lateNight <- 23:59:59
  lateNight++ wraps to 00:00:00
  early <- 00:00:00
  early-- wraps to 23:59:59

WRAPPING AND SUBTRACTION

Subtracting a later time from an earlier time produces a negative Duration:

  gap <- 01:00 - 22:00
  gap is PT-21H (not PT3H)

This is the linear difference, not the 'clock distance'.

DATETIME DOES NOT WRAP

DateTime (which includes a date) does NOT wrap. Adding PT3H to a DateTime at 22:00 moves to 01:00 on the NEXT DAY. The date changes.

WHEN TO USE TIME VS DATETIME

Time: schedules, recurring daily events, clock positions.
DateTime: events with specific dates, timestamps, logging.

See Q31 for Time basics. See Q540 for date arithmetic. See Q539 for time subtraction. See Q550 for calendar edge cases.

Example

defines module qa.time.wrapping

  defines program
    TimeWrappingDemo()
      stdout <- Stdout()

      // Basic wrapping past midnight
      evening <- 22:00
      pastMidnight <- evening + PT3H
      stdout.println(`22:00 + PT3H = ${pastMidnight}`)

      // Wrapping backwards past midnight
      earlyMorning <- 01:00
      lastNight <- earlyMorning - PT3H
      stdout.println(`01:00 - PT3H = ${lastNight}`)

      // Wrapping with larger durations
      noon <- 12:00
      plusDay <- noon + PT24H
      stdout.println(`12:00 + PT24H = ${plusDay}`)

      plusDayHalf <- noon + PT36H
      stdout.println(`12:00 + PT36H = ${plusDayHalf}`)

      // Increment wrapping via duration
      almostMidnight <- 23:59:59
      almostMidnight += PT1S
      stdout.println(`23:59:59 + 1s = ${almostMidnight}`)

      // Decrement wrapping via duration
      justPastMidnight <- 00:00:00
      justPastMidnight -= PT1S
      stdout.println(`00:00:00 - 1s = ${justPastMidnight}`)

      // Subtraction gives linear difference (not clock distance)
      negGap <- 01:00 - 22:00
      stdout.println(`01:00 - 22:00 = ${negGap}`)

      posGap <- 22:00 - 01:00
      stdout.println(`22:00 - 01:00 = ${posGap}`)

      // DateTime does NOT wrap - date advances instead
      eveningDT <- 2024-06-15T22:00:00Z
      nextDayDT <- eveningDT + PT3H
      stdout.println(`DateTime 22:00 + 3h = ${nextDayDT}`)
      // The date changes from June 15 to June 16
      stdout.println(`Day changed: ${nextDayDT.day()}`)

      // startOfDay and endOfDay
      dayStart <- Time().startOfDay()
      dayEnd <- Time().endOfDay()
      stdout.println(`Start of day: ${dayStart}`)
      stdout.println(`End of day: ${dayEnd}`)

Common mistakes

E50001 — EK9 has no static field access like Java's Time.MIN or Time.MAX. Type names without () are not resolved as expressions. Use Time().startOfDay() and Time().endOfDay() factory methods. See ek9 -h E50001 for details.

Incorrect:

dayStart <- Time.MIN
      dayEnd <- Time.MAX

Correct:

dayStart <- Time().startOfDay()
      dayEnd <- Time().endOfDay()
Other ways to ask this
  • What happens when Time goes past midnight?
  • Does Time wrap around at 24 hours?
  • How does Time arithmetic handle overflow?

Coming from another language?

Java: LocalTime wraps at midnight (plusHours past midnight wraps). Python: time does not support arithmetic (must use datetime). JavaScript: no Time type, Date wraps dates. Go: no separate Time type, time.Time includes date. Rust: chrono NaiveTime wraps at midnight. EK9: Time wraps at 24h boundary, DateTime does not wrap (date advances).

Keywords: clock, wrapping, circular, arithmetic, 24 hour, midnight, overflow, duration, wrap, time, timezone