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