How do I compare dates in EK9?

← Date, Time, and Duration · Ref: Q542

All temporal types (Date, Time, DateTime, Duration, Millisecond) support the comparison operators == <> < > <= >= and <=>. The fuzzy operator <~> is available on Date, Time, DateTime and Millisecond, but not on Duration.

COMPARISON OPERATORS

  - == equal
  - <> not equal
  - < less than (earlier)
  - > greater than (later)
  - <= less than or equal
  - >= greater than or equal
  - <=> spaceship (returns -1, 0, or 1)
  - <~> fuzzy comparison (not on Duration)

DATE COMPARISON

Dates compare chronologically:

  newYear <- 2024-01-01
  christmas <- 2024-12-25
  isEarlier <- newYear < christmas   // true
  isSame <- newYear == christmas   // false

Comparing two literals directly is rejected (E08082, the result is predetermined), so compare variables.

TIME COMPARISON

Times compare within the day:

  morning <- 09:00
  evening <- 17:00
  isEarlier <- morning < evening   // true

DATETIME COMPARISON — UTC NORMALIZED

DateTimes in different timezones compare by their UTC-equivalent instant:

  utcTen <- 2024-06-15T10:00:00Z
  nySix <- 2024-06-15T06:00:00-04:00
  isSame <- utcTen == nySix   // true, both represent the same moment

This means you can safely compare timestamps from different timezones.

SPACESHIP OPERATOR

The <=> operator returns an Integer: negative (before), zero (equal), positive (after). Useful for custom sorting logic.

FUZZY COMPARISON

The <~> operator returns an Integer, but what it means depends on the type. Date and Millisecond delegate to <=>, so they give -1, 0 or 1 (newYear <~> christmas is -1 and christmas <~> newYear is 1, whatever the gap). Time compares to the minute and ignores seconds, again giving -1, 0 or 1. DateTime returns the absolute number of seconds between the two instants. Duration has no <~> (using it is E07620). Use <=> for ordering and <~> only when you want one of these approximations.

SORTING

Since all comparison operators are defined, temporal values work naturally in sorted collections and stream sort operations.

See Q31 for Date and Time basics. See Q548 for cross-timezone comparison details.

Example

defines module qa.compare.dates

  defines program
    CompareDatesDemo()
      stdout <- Stdout()

      // Date comparison
      newYear <- 2024-01-01
      christmas <- 2024-12-25
      summer <- 2024-06-15
      sameSummer <- 2024-06-15

      require newYear < christmas
      require christmas > newYear
      require summer == sameSummer
      require newYear <> christmas
      require newYear <= summer
      require christmas >= summer
      stdout.println(`Jan < Dec: ${newYear < christmas}`)
      stdout.println(`Jun == Jun: ${summer == sameSummer}`)

      // Time comparison
      morning <- 09:00
      evening <- 17:00
      require morning < evening
      stdout.println(`09:00 < 17:00: ${morning < evening}`)

      // DateTime comparison — UTC normalized
      utcNoon <- 2024-06-15T12:00:00Z
      nyMorning <- 2024-06-15T08:00:00-04:00
      // Both represent the same instant (12:00 UTC = 08:00 EDT)
      require utcNoon == nyMorning
      stdout.println(`UTC noon == NY 8am: ${utcNoon == nyMorning}`)

      // Different instants in different zones
      laterNY <- 2024-06-15T14:00:00-04:00
      require laterNY > utcNoon
      stdout.println(`NY 2pm > UTC noon: ${laterNY > utcNoon}`)

      // Spaceship operator
      ordering <- newYear <=> christmas
      stdout.println(`Jan <=> Dec: ${ordering}`)
      require ordering < 0

      // Fuzzy comparison
      fuzzy <- newYear <~> christmas
      stdout.println(`Fuzzy distance: ${fuzzy}`)

      // Duration comparison
      shortDur <- PT30M
      longDur <- PT2H
      require shortDur < longDur
      stdout.println(`30min < 2h: ${shortDur < longDur}`)

      // Millisecond comparison
      shortMs <- 100ms
      longMs <- 500ms
      require shortMs < longMs
      require longMs > shortMs
      stdout.println(`100ms < 500ms: ${shortMs < longMs}`)

Common mistakes

E50060 — Date has no isBefore() method. EK9 uses comparison operators (<, >, <=, >=, ==, <>) directly on temporal types. See ek9 -h E50060 for details.

Incorrect:

require newYear.isBefore(christmas)

Correct:

require newYear < christmas
Other ways to ask this
  • How do I check if one date is before another?
  • How does date sorting work in EK9?
  • What comparison operators work on dates?

Coming from another language?

Java: compareTo(), isBefore(), isAfter(), isEqual() methods. Python: direct comparison operators work on datetime objects. JavaScript: compare via getTime() milliseconds (operators on Date objects are unreliable). Go: t.Before(), t.After(), t.Equal() methods. Rust: PartialOrd trait. EK9: operators ==, <>, <, >, <=, >=, <=> on all temporal types (<~> on every one except Duration), UTC-normalized DateTime comparison.

Keywords: sort, equal, duration, compare, after, chronological, before, spaceship, datetime, fuzzy, timezone, date, operators, time