Swift and Foundation offer a few different types and APIs for working with dates and calendars.
Date: A specific point in time, independent of any calendar or time zone.
Calendar: A definition of the relationships between calendar units and absolute points in time, providing features for calculation and comparison of dates.
DateComponents: A date or time specified in terms of units (such as year, month, day, hour, and minute) to be evaluated in a calendar system and time zone.
Duration: A representation of high precision elapsed time. Unlike the types above, Duration measures a length of time rather than a point in time.
These enable working with points in time and converting them across calendars and time zones. However, there are a few additional types that would be useful to complete the picture around date and time handling.
Local dates and times
It is common to work with dates and times that are independent of a time zone. Examples include:
- Human-meaningful dates: birthdays, anniversaries, and holidays refer to the same calendar date everywhere. A person born on 1990-03-15 has their birthday on March 15 regardless of where they travel.
- Recurring local schedules: store opening hours, school timetables, medication reminders, and train departure boards are expressed as "09:00 local time" at each location. Pinning them to an absolute
Date requires choosing a time zone, which is wrong: the schedule is intentionally time-zone-agnostic until interpreted at a specific place.
- Contractual and legal dates: expiration dates, deadlines, document dates, and historical events are recorded as calendar dates without any associated instant.
- Wire formats and storage: ISO-8601 permits date and time-of-day representations without an offset (
2007-12-03, 10:15:30, 2007-12-03T10:15:30). Databases similarly distinguish DATE, TIME, and TIMESTAMP WITHOUT TIME ZONE from TIMESTAMP WITH TIME ZONE. Today, Swift code parsing or producing these formats must round-trip through Date + TimeZone or DateComponents, neither of which models the "no time zone" semantic precisely.
Today, modeling these concepts in Swift forces developers to either:
- Use
Date plus an out-of-band convention (e.g., "always interpret as UTC midnight"), which silently breaks across time-zone boundaries and DST transitions.
- Use
DateComponents, which is loosely typed. Every field is optional, validity is not enforced at the type level, and arithmetic requires a Calendar.
Neither approach gives a value type that statically guarantees "this is a calendar date" or "this is a wall-clock time".
We should introduce types to fill this gap:
LocalDate: A date without a time zone in the ISO-8601 calendar system, such as 2007-12-03.
LocalDateTime: A date-time without a time zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.
LocalTime: A time without a time zone in the ISO-8601 calendar system, such as 10:15:30.
Prior art
This trio is well-established across other ecosystems, which makes the proposed names and semantics familiar:
- Java's
java.time (JSR-310): LocalDate, LocalDateTime, LocalTime.
- Kotlin's
kotlinx-datetime: LocalDate, LocalDateTime, LocalTime.
- Python's standard library:
datetime.date, datetime.datetime (naive), datetime.time.
Swift and Foundation offer a few different types and APIs for working with dates and calendars.
Date: A specific point in time, independent of any calendar or time zone.Calendar: A definition of the relationships between calendar units and absolute points in time, providing features for calculation and comparison of dates.DateComponents: A date or time specified in terms of units (such as year, month, day, hour, and minute) to be evaluated in a calendar system and time zone.Duration: A representation of high precision elapsed time. Unlike the types above,Durationmeasures a length of time rather than a point in time.These enable working with points in time and converting them across calendars and time zones. However, there are a few additional types that would be useful to complete the picture around date and time handling.
Local dates and times
It is common to work with dates and times that are independent of a time zone. Examples include:
Daterequires choosing a time zone, which is wrong: the schedule is intentionally time-zone-agnostic until interpreted at a specific place.2007-12-03,10:15:30,2007-12-03T10:15:30). Databases similarly distinguishDATE,TIME, andTIMESTAMP WITHOUT TIME ZONEfromTIMESTAMP WITH TIME ZONE. Today, Swift code parsing or producing these formats must round-trip throughDate+TimeZoneorDateComponents, neither of which models the "no time zone" semantic precisely.Today, modeling these concepts in Swift forces developers to either:
Dateplus an out-of-band convention (e.g., "always interpret as UTC midnight"), which silently breaks across time-zone boundaries and DST transitions.DateComponents, which is loosely typed. Every field is optional, validity is not enforced at the type level, and arithmetic requires aCalendar.Neither approach gives a value type that statically guarantees "this is a calendar date" or "this is a wall-clock time".
We should introduce types to fill this gap:
LocalDate: A date without a time zone in the ISO-8601 calendar system, such as2007-12-03.LocalDateTime: A date-time without a time zone in the ISO-8601 calendar system, such as2007-12-03T10:15:30.LocalTime: A time without a time zone in the ISO-8601 calendar system, such as10:15:30.Prior art
This trio is well-established across other ecosystems, which makes the proposed names and semantics familiar:
java.time(JSR-310):LocalDate,LocalDateTime,LocalTime.kotlinx-datetime:LocalDate,LocalDateTime,LocalTime.datetime.date,datetime.datetime(naive),datetime.time.