I need some help understanding how dates and time zones work in Swift / SwiftUI.
I’m currently using the DatePicker component and selecting the range to be now to infinity. The DatePicker returns a date in UTC format and this date is saved to my database. When a user in another timezone views this date will it automatically be converted to the correct zone?
My date is essentially a countdown so this countdown should be the same for every user regardless of their timezone. I don’t know if I need to do more conversions or if iOS is doing it for me.
Here is the sample code I’m playing around with:
import SwiftUI
struct ContentView: View {
@State private var timeNow = Date.now.addingTimeInterval(3600)
var body: some View {
VStack {
Text("Countdown ends in:")
Text(timeNow, style: .timer)
.font(.largeTitle)
.monospaced()
DatePicker("Opens", selection: $timeNow, in: Date.now...)
.labelsHidden()
}
.padding()
.onAppear {
UIDatePicker.appearance().minuteInterval = 15
}
}
}
#Preview {
ContentView()
}
>Solution :
Date is not associated with any timezone. It just represents an instant in time, i.e. n seconds since some predefined epoch. You see it formatted as a datetime in UTC when you print it out, but a Date is just a number of seconds.
Assuming the database doesn’t do anything weird with the Date value (i.e. if the column’s type also represents an instant), then all users will see the same count down when they fetch the same row from the database. Since this is a count down, there is no need to convert Dates in any way. All that needs to be done is to find the difference in seconds between now and the Date, and format that as a duration. Time zones are irrelevant here.
On the other hand, users in different timezones will obviously see different times selected in the date picker for the same timeNow value. DatePicker needs to display the year, month, day, hour, minute, and so on. To get these numbers, it needs to interpret the Date in some timezone. This is by default the user’s timezone, but you can override this by changing the environment.
.environment(\.timeZone, someTimeZone)