The time zone is accounted for (implicitly) in the example. It may help the proposal if it were spelled out, but it is actually incorporated into the current calendar.
let calendar = Calendar.current // this has a time zone
var when = calendar.dateComponents([.day, .month, .year], from: .now)
when.day = when.day.map { $0 + 1 }
when.hour = 8
// ...
For example:
let c = Calendar.current
print(c.timeZone) // America/Los_Angeles (for me)
And this line:
calendar.date(from: when)
uses the calendar's time zone by default, or the one in the components if set.
In general, you are correct that calculating the right Date
is fairly complicated and comes with lots of nuance. In Foundation's calendar APIs, we split that responsibility out into the Calendar
type, leaving Date
to be just a timestamp. There's never one right answer to choose. Sometimes alarms are really meant to be at a specific time of day and sometimes they are meant to adjust +/- an hour if a DST transition happens to occur.
Using your example, a meeting set for 2pm Cupertino time or 11am London time is calculated by finding the right Date
first - the Date
does not change after the fact if a DST boundary is crossed. Calendar
calculates it using the data from time zone and the input to the date(from:)
API. It has options to help in DST transitions, like this one:
/// Determines which result to use when a time is repeated on a day in a calendar (for example, during a daylight saving transition when the times between 2:00am and 3:00am may happen twice).
public enum RepeatedTimePolicy : Sendable {
/// If there are two or more matching times (all the components are the same, including isLeapMonth) before the end of the next instance of the next higher component to the highest specified component, then the algorithm will return the first occurrence.
case first
/// If there are two or more matching times (all the components are the same, including isLeapMonth) before the end of the next instance of the next higher component to the highest specified component, then the algorithm will return the last occurrence.
case last
}
In the end, any kind of "AlarmClock" that attempted to accommodate for all of this using Calendar would probably just end up replicating Calendar's API, using it to calculate a Date, then scheduling it using UTC.