I've read the Date struct docs but not sure I understand. It says that it's a specific time independent of a timezone.
However when I take a Date() instance, and format it with the DateFormatter.timeZone as UTC the resultant date I get is the same exact date as print(Date()).
Does this mean that a Date() instance is always UTC even though the docs say there is no timezone association?
A Date
value is a timestamp, and timestamps count the number of seconds from January 1, 1970 (edit: brain fart) January 1, 2001 in the UTC timezone.
This, fundamentally, is the only thing a Date
is: a number of seconds.
If you want to interpret that value relative to a calendaring system (like the Gregorian or Islamic or Buddhist etc calendars), you'll need a Calendar
value for extracting "components" (component = numeric calendrical value. For example, the current "month" component on the Gregorian calendar is 11
, which we interpret as "November").
If you want to "render" a Date
into some text to show the user, then you use a DateFormatter
, which gets configured with a Calendar
and TimeZone
(defaulting to the machine's current values for those types) and a style for rendering the date and time portions of the timestamp.
I'd suggest avoiding printing a Date
directly, since that ends up relying on its description
value and it can lead to some false assumptions about the value. Basically, I would recommend always using a DateFormatter
(and similarly-based formatting APIs) for getting a "human readable" version of a Date
.
To add, I think a lot of the confusion stems from the implementation of Date.description
(as used by print
, for example) and how it “maintains the illusion”.
It won’t print the raw Double value (num seconds since the reference date), it’ll instead format to your local timezone. Convenient, but can confuse beginners.
UTC is not just an "ordinary" timezone: Usually, timezones are defined by their offset to UTC, which is basically world time.
When you create an instance with Date()
, this will always be the current time in UTC, no matter where you are, and when you instantiate it with a year, month, day etc and a timezone, all that is converted to UTC.
Another way to think about it is that Date
is the "time" version of latitude and longitude.
Latitude and longitude can get you to the exact right spot on the globe, but they won't tell you what the name of the street there is; you need a geographic map to do that.
A Date
can get you to the exact right spot in time, but it won't tell you what the name of year/month/day/hour/minute/second it is then; you need a temporal map to do that: that's Calendar
.
I am pretty sure Date
’s epoch is the instant UTC reached A.D. 2001.
(I also suspect the number of seconds is measured in UT1, not UTC, although the documentation does not specify and it has been a while since I have worked on anything where the difference mattered.)
it’ll instead format to your local timezone.
It stopped doing that a while back (r. 7094236). Starting with Apple’s 2010 OS releases, this code:
import Foundation
print(TimeZone.current)
print(Date())
prints this [1]:
America/Los_Angeles (current)
2021-11-02 09:33:24 +0000
While there’s still a lot of confusion about Date
, we have at least fix this specific issue (unless you happen to be in GMT).
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
[1] And I just tested this with a command-line tool target built using Xcode 13.1 on macOS 11.6 with System Preferences > Date & Time > Time Zone set to Cupertino.
ugh silly mistake. You're absolutely right. Thanks for the correction.