How do I construct a DateTime from individual components in EK9?

← Date, Time, and Duration · Ref: Q555

Date, Time, and DateTime all support component-based construction.

DATE CONSTRUCTORS

  Date(year, month, dayOfMonth) from three integers
  Date(daysFromEpoch) from epoch day count
  Date(stringValue) from ISO 8601 string
  Date() unset date

TIME CONSTRUCTORS

  Time(hour, minute) two components
  Time(hour, minute, second) three components
  Time(secondOfDay) from seconds since midnight
  Time(stringValue) from ISO 8601 string
  Time() unset time

DATETIME CONSTRUCTORS

  DateTime(year, month, dayOfMonth) date only (midnight UTC)
  DateTime(year, month, dayOfMonth, hour) with hour
  DateTime(year, month, dayOfMonth, hour, minute) with minute
  DateTime(year, month, dayOfMonth, hour, minute, second) full
  DateTime(dateValue) from a Date (promotes)
  DateTime(stringValue) from ISO 8601 string
  DateTime() unset datetime

LITERAL SYNTAX

For known values, literals are more readable:

  date <- 2024-06-15
  time <- 10:30:00
  dt <- 2024-06-15T10:30:00Z

COMPONENT CONSTRUCTION FOR DYNAMIC VALUES

When values come from variables or calculations:

  year <- 2024
  month <- 6
  dayVal <- 15
  computed <- Date(year, month, dayVal)

INVALID COMPONENTS PRODUCE UNSET

  invalid <- Date(2024, 13, 01) produces an unset Date (month 13 does not exist).
  invalid <- Time(25, 00) produces an unset Time.

See Q538 for string parsing. See Q552 for Date-to-DateTime promotion. See Q554 for extracting components.

Example

defines module qa.construct.from.components

  defines program
    ConstructFromComponentsDemo()
      stdout <- Stdout()

      // Date constructors
      fromComponents <- Date(2024, 06, 15)
      fromEpochDays <- Date(19889)
      fromString <- Date("2024-06-15")
      fromLiteral <- 2024-06-15
      stdout.println(`Components: ${fromComponents}`)
      stdout.println(`Epoch days: ${fromEpochDays}`)
      stdout.println(`String: ${fromString}`)
      stdout.println(`Literal: ${fromLiteral}`)

      // Time constructors
      twoArgs <- Time(10, 30)
      threeArgs <- Time(10, 30, 45)
      fromSecond <- Time(37845)
      timeLiteral <- 10:30:45
      stdout.println(`Two args: ${twoArgs}`)
      stdout.println(`Three args: ${threeArgs}`)
      stdout.println(`From seconds: ${fromSecond}`)
      stdout.println(`Literal: ${timeLiteral}`)
      require threeArgs == timeLiteral

      // DateTime from Date (3 args OK)
      dateOnly <- DateTime(2024, 06, 15)
      stdout.println(`Date only: ${dateOnly}`)

      // DateTime from Date promotion then add time via duration
      dtBase <- DateTime(2024, 06, 15)
      withMinute <- dtBase + PT10H30M
      stdout.println(`With minute: ${withMinute}`)

      withSecond <- dtBase + PT10H30M45S
      stdout.println(`With second: ${withSecond}`)

      // From Date (promotes)
      datePart <- 2024-06-15
      fromDate <- DateTime(datePart)
      stdout.println(`From Date: ${fromDate}`)

      // Dynamic component construction
      year <- 2024
      month <- 12
      dayVal <- 25
      christmas <- Date(year, month, dayVal)
      stdout.println(`Dynamic: ${christmas}`)

      // Invalid components produce unset
      badMonth <- Date(2024, 13, 01)
      badHour <- Time(25, 00)
      require ~badMonth?
      require ~badHour?
      stdout.println(`Bad month isSet: ${badMonth?}`)
      stdout.println(`Bad hour isSet: ${badHour?}`)

Common mistakes

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

Incorrect:

fromComponentsXYZ <- Date(2024, 06, 15)

Correct:

fromComponents <- Date(2024, 06, 15)
Other ways to ask this
  • What constructor forms does DateTime have?
  • How do I create a Date from year, month, and day?
  • How do I build a DateTime programmatically?

Coming from another language?

Java: LocalDate.of(2024, 6, 15), LocalTime.of(10, 30), ZonedDateTime.of(..., ZoneId.of('UTC')). Python: date(2024, 6, 15), time(10, 30), datetime(2024, 6, 15, 10, 30). JavaScript: new Date(2024, 5, 15) (month is 0-indexed!). Go: time.Date(2024, 6, 15, 10, 30, 0, 0, time.UTC). EK9: Date(2024, 06, 15), Time(10, 30), DateTime(2024, 06, 15, 10, 30) plus literal syntax.

Keywords: construct, year, constructor, second, duration, time, date, literal, minute, hour, build, create, constant, timezone, day, month, component