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
  (no Date(Integer): a bare number cannot state its unit - for epoch work use the literal
  1970-01-01 with Date - Date -> Duration, see Q543)
  - 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)
      fromString <- Date("2024-06-15")
      fromLiteral <- 2024-06-15
      stdout.println(`Components: ${fromComponents}`)
      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 — Constructing a type that does not exist (the misspelt Dates) leaves the call unresolved, triggering E50001. See ek9 -h E50001 for details.

Incorrect:

Dates(2024, 06, 15)

Correct:

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: minute, literal, date, time, duration, second, constructor, year, construct, component, month, day, timezone, constant, create, build, hour