Someday, we who attend Tampa Bay’s Geek Breakfast will reconvene at Jimbo’s Pit Bar-B-Q, and I will have my customary stack o’ hotcakes or biscuits and gravy washed down with a half-dozen cups of coffee. Until that happens, Geek Breakfast continues online, and it’s happening tomorrow from 8:00 to 9:30 a.m. See you there!
In the previous article in this series on working with dates and times in Swift 5, we looked at three key structs for date and time programming in Swift:
Date
represents a single point in time, using a format that can easily be translated into just about any calendar and time-reckoning system: a number of seconds relative to the start of the Third Millennium (January 1, 2001, 00:00:00 UTC).DateComponents
specifies time units like year, month, day, hour, minute, and more to represent either a point in time or a duration of time.Calendar
provides a context forDate
s, and convertsDate
s toDateComponents
andDateComponents
toDate
s.
These structs all deal with the internal representation of dates and times in Swift 5.
In this article, we’ll look at the DateFormatter
class, which allows us to deal with the external representation of dates and times in Swift 5 as strings to be presented to the user. We use this class to convert Date
s into formatted String
s that match the user’s language and locale, and properly-formatted String
s into Date
s.
Tap the image to see it at full size.
We’ve already used the Date
struct’s description
property and description(with:)
method to print its value in a human-readable form, but they’re meant for debugging purposes only, and not for presenting date and time information to the user. When presenting dates to the user in string form, use strings that have been created by DateFormatter
.
Let’s convert a Date
into a String
, part 1: Just the date
Start a new playground and enter the following code, which gives us a Date
that we can format — June 2, 2014, the day when the Swift programming language was first released:
// The user's calendar incorporates the user's locale and // time zone settings, which means it's the one you'll use // most often. // 1 let userCalendar = Calendar.current // The Swift programming language was first released on // June 2, 2014. // 2 let swiftDebutDateComponents = DateComponents( year: 2014, month: 6, day: 2 ) // 3 let swiftDebutDate = userCalendar.date(from: swiftDebutDateComponents)!
This code is similar to code we entered in the previous article:
- Get the user’s current
Calendar
. - Create a
DateComponents
struct,swiftDebutDateComponents
, providing theyear:
,month:
, andday:
parameters that correspond to the date June 2, 2014. - Use the user’s
Calendar
to createswiftDebutDate
usingswiftDebutDateComponents
.
Let’s try turning this date into a string with a DateFormatter
.
Add the following to the playground, then run it:
let myFormatter = DateFormatter() print("Swift’s debut date, via the DateFormatter: \(myFormatter.string(from: swiftDebutDate))")
The output should look like this:
Swift’s debut date, via the DateFormatter:
You may be surprised that the result is an empty String
. That’s because you need to specify a dateStyle
, which specifies which pre-defined format should be used for the date. We’ll start with the short
style.
Add the following to the playground, then run it:
myFormatter.dateStyle = .short print("Swift’s debut date, “short” style: \(myFormatter.string(from: swiftDebutDate)).")
The output should look like this:
Swift’s debut date, “short” style: 6/2/14.
Let’s try the other styles: medium
, long
, full
, and none
.
Add the following to the playground, then run it:
myFormatter.dateStyle = .medium print("Swift’s debut date, “medium” style: \(myFormatter.string(from: swiftDebutDate))") myFormatter.dateStyle = .long print("Swift’s debut date, “long” style: \(myFormatter.string(from: swiftDebutDate))") myFormatter.dateStyle = .full print("Swift’s debut date, “full” style: \(myFormatter.string(from: swiftDebutDate))") myFormatter.dateStyle = .none print("Swift’s debut date, “none” style: \(myFormatter.string(from: swiftDebutDate))")
The output should look like this:
Swift’s debut date, “medium” style: Jun 2, 2014.
Swift’s debut date, “long” style: June 2, 2014.
Swift’s debut date, “full” style: Monday, June 2, 2014.
Swift’s debut date, “none” style: .
If turns out that the default dateStyle
is none.
Why would there be a dateStyle
called .none
? I’ll explain in the next section.
Let’s convert a Date
into a String
, part 2: A date and a time
Let’s create a date and approximate known time: When SwiftUI was announced at WWDC 2019. It’s introduced 2 hours and 8 minutes into a keynote that started at 10:00 a.m. Pacific Daylight Time, so we’ll say it debuted at 12:08 p.m. PDT on June 3, 2019.
Add the following to the playground, then run it:
// SwiftUI was introduced at WWDC 2019 on // June 3, 2019 at 12:08 p.m. Pacific Daylight Time. let swiftUIDebutDateComponents = DateComponents( timeZone: TimeZone(abbreviation: "PDT"), year: 2019, month: 6, day: 3, hour: 12, minute: 8 ) let swiftUIDebutDate = userCalendar.date(from: swiftUIDebutDateComponents)! print("The newly-created date: \(swiftUIDebutDate.description(with: Locale(identifier: "en-US"))).")
On my computer, the output looked like this:
The newly-created date: Monday, June 3, 2019 at 3:08:00 PM Eastern Daylight Time.
The date and time you’ll see will be determined your system calendar settings.
Now that we have a date and time, let’s format it using the dateStyle
property to style the date part, and timeStyle
property to style the time part.
Add the following to the playground, then run it:
myFormatter.dateStyle = .short myFormatter.timeStyle = .short print("Swift’s debut date and time, “short” style: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateStyle = .medium myFormatter.timeStyle = .medium print("Swift’s debut date and time, “medium” style: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateStyle = .long myFormatter.timeStyle = .long print("Swift’s debut date and time, “long” style: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateStyle = .full myFormatter.timeStyle = .full print("Swift’s debut date and time, “full” style: \(myFormatter.string(from: swiftUIDebutDate)).")
On my computer, the output looked like this:
Swift’s debut date and time, “short” style: 6/3/19, 3:08 PM.
Swift’s debut date and time, “medium” style: Jun 3, 2019 at 3:08:00 PM.
Swift’s debut date and time, “long” style: June 3, 2019 at 3:08:00 PM EDT.
Swift’s debut date and time, “full” style: Monday, June 3, 2019 at 3:08:00 PM Eastern Daylight Time.
You can mix and match dateStyle
and timeStyle
settings. Add the following to the playground, then run it:
myFormatter.dateStyle = .full myFormatter.timeStyle = .short print("Swift’s debut date and time, with “full” style date and “short” style time: \(myFormatter.string(from: swiftUIDebutDate)).")
On my computer, the output looked like this:
Swift’s debut date and time, with “full” style date and “short” style time: Monday, June 3, 2019 at 3:08 PM.
Now that we’re working with a date and time, I can tell you what the .none
style is for: for suppressing the display of the date or time in a formatted date string.
Add the following to the playground, then run it:
// Show only the time myFormatter.dateStyle = .none myFormatter.timeStyle = .medium print("Swift’s debut time: \(myFormatter.string(from: swiftUIDebutDate)).") // Show only the date myFormatter.dateStyle = .full myFormatter.timeStyle = .none print("Swift’s debut date: \(myFormatter.string(from: swiftUIDebutDate)).")
Remember that the Date
struct represents a single point in time, which has both a date and a time. The .none
style for DateFormatter
‘s dateStyle
and timeStyle
properties allows us to create a String
representation of a Date
that shows only its date or time part.
This table summarizes the different dateStyle
and timeStyle
settings for the US English language setting:
Setting | dateStyle | timeStyle |
.none |
[ empty string ] | [ empty string ] |
.short |
6/3/19 | 3:08 PM |
.medium |
Jun 3, 2019 | 3:08:00 PM |
.long |
June 3, 2019 | 3:08:00 PM EDT |
.full |
Monday, June 3, 2019 | 3:08:00 PM Eastern Daylight Time |
Let’s convert a Date
into a String
, part 3: Displaying dates and times in other languages
DateFormatter
defaults to the user’s preferred language, as specified in their settings. In my case, that’s US English. By setting the locale
property of the DateFormatter
, I can specify the language for my formatted date strings. Add the following to the playground, then run it:
// We want to see as much of these languages as possible, // so let’s set both dateStyle and timeStyle to .full. myFormatter.dateStyle = .full myFormatter.timeStyle = .full myFormatter.locale = Locale(identifier: "fr") print("International French: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.locale = Locale(identifier: "fr-CA") print("Canadian French: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.locale = Locale(identifier: "hr") print("Croatian: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.locale = Locale(identifier: "ko_KR") print("Korean: \(myFormatter.string(from: swiftUIDebutDate)).")
On my computer, the output looked like this:
International French: lundi 3 juin 2019 à 15:08:00 heure d’été de l’Est.
Canadian French: lundi 3 juin 2019 à 15:08:00 heure avancée de l’Est.
Croatian: ponedjeljak, 3. lipnja 2019. u 15:08:00 (istočno ljetno vrijeme).
Korean: 2019년 6월 3일 월요일 오후 3시 8분 0초 미 동부 하계 표준시.
Let’s convert a Date
into a String
, part 4: Custom date/time formats
In addition to the built-in formats for dates, you can tell DateFormatter
to use a custom format.
Before we begin working with custom date/time formats, I should point out that if you need to display a Date
as a String
to the user, it’s best if you use Swift’s built-in dateStyle
and timeStyle
values. They display dates and times properly, according to the user’s settings, which include country and language. You’d be surprised how date formats differ from culture to culture, and it’s better to let Swift do the formatting work.
However, there are times when you need to format dates and times in a specific way that doesn’t match the styles provided by DateFormatter
’s dateStyle
and timeStyle
properties, such as when dealing with certain APIs. That’s where DateFormatter
’s dateFormat
property comes in handy.
To be certain that the DateFormatter
will use your custom date format, set its locale
property to POSIX, then define the custom date format string in dateFormat
.
Add the following to the playground, then run it:
// Setting the locale to POSIX ensures that the user's locale // won't be used to format the Date. myFormatter.locale = Locale(identifier: "en_US_POSIX") // DateFormatter's format string uses the date format specifiers // spelled out in Unicode Technical Standard #35 (located at // http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns) myFormatter.dateFormat = "y-MM-dd" print("Swift’s debut date and time, y-MM-dd format: \(myFormatter.string(from: swiftUIDebutDate)).")
You can use the date format specifiers listed in Appendix F of the Unicode Technical Standard #35 to define the formatting String
for the dateFormat
property. Here are some examples (Add the following to the playground, then run it):
// DateFormatter's format string uses the date format specifiers // spelled out in Unicode Technical Standard #35 (located at // http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns) myFormatter.dateFormat = "y-MM-dd" print("Swift’s debut date and time, y-MM-dd format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "'Year: 'y' Month: 'M' Day: 'd" print("Swift’s debut date and time, in labeled y M d format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "MM/dd/yy" print("Swift’s debut date and time, MM/dd/yy format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "MMM dd, yyyy" print("Swift’s debut date and time, MMM dd, yyyy format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "E MMM dd, yyyy" print("Swift’s debut date and time, E MMM dd, yyyy format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "EEEE, MMMM dd, yyyy' at 'h:mm a" print("Swift’s debut date and time, EEEE, MMMM dd, yyyy' at 'h:mm a. format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "EEEE, MMMM dd, yyyy' at 'h:mm a zzzz" print("Swift’s debut date and time, EEEE, MMMM dd, yyyy' at 'h:mm a zzzz. format: \(myFormatter.string(from: swiftUIDebutDate)).")
Let’s convert a String
into a Date
DateFormatter
works the other way — just as it can convert Date
s to String
s, it can also convert String
s to Date
s. By setting its dateFormat
to the format of the String
it should expect, you can use its date(from:)
method to convert a String
into a Date
.
Once again, use the date format specifiers listed in Appendix F of the Unicode Technical Standard #35 to define the formatting String
for the dateFormat
property.
Add the following to the playground, then run it:
// Let’s define the format for date strings we want to parse: myFormatter.dateFormat = "yyyy/MM/dd hh:mm Z" // Here's a date in the specified format. // DateFormatter’s date(from:) method will be able to parse it. let newDate1 = myFormatter.date(from: "2019/06/03 12:08 -0700") print("newDate1’s value is: \(newDate1?.description ?? "nil").") // And here's the same date, but in a different format: let newDate2 = myFormatter.date(from: "Jun 6, 2019, 12:08 PM PDT") print("newDate2’s value is: \(newDate2?.description ?? "nil").")
On my computer, the output looked like this:
newDate1’s value is: 2019-06-03 07:08:00 +0000.
newDate2’s value is: nil.
Let’s change the dateFormat
string and try it again. Add the following to the playground, then run it:
// Let's change the date format strings and try // date(from:) with the same two strings: myFormatter.dateFormat = "MMM d, yyyy, hh:mm a zz" let newDate3 = myFormatter.date(from: "2019/06/03 12:08 -0700") print("newDate3’s value is: \(newDate3?.description ?? "nil").") let newDate4 = myFormatter.date(from: "Jun 6, 2019, 12:08 PM PDT") print("newDate4’s value is: \(newDate4?.description ?? "nil").")
On my computer, the output looked like this:
newDate3’s value is: nil.
newDate4’s value is: 2019-06-06 19:08:00 +0000.
If you’re trying to parse a weird date format, use a weird date format string. Add the following to the playground, then run it:
// Don’t forget that you can get weird if you expect to // parse dates in weird formats! // (D is the format string for “day of year”, which can be 1...366) myFormatter.dateFormat = "y 😍 D" let weirdEmojiDate = myFormatter.date(from: "2020 😍 333") print("weirdEmojiDate’s value is: \(weirdEmojiDate?.description ?? "nil").")
On my computer, the output looked like this:
weirdEmojiDate’s value is: 2020-11-28 05:00:00 +0000.
Wrapping it all up
Here’s the complete code for the playground containing all the code we just worked with:
import UIKit // Let’s convert a Date into a String, part 1: Just the date // ========================================================= // The user's calendar incorporates the user's locale and // time zone settings, which means it's the one you'll use // most often. // 1 let userCalendar = Calendar.current // The Swift programming language was first released on // June 2, 2014. // 2 let swiftDebutDateComponents = DateComponents( year: 2014, month: 6, day: 2 ) // 3 let swiftDebutDate = userCalendar.date(from: swiftDebutDateComponents)! let myFormatter = DateFormatter() print("Swift’s debut date, via the DateFormatter: \(myFormatter.string(from: swiftDebutDate))") // Hey, what gives? myFormatter.dateStyle = .short print("Swift’s debut date, “short” style: \(myFormatter.string(from: swiftDebutDate)).") myFormatter.dateStyle = .medium print("Swift’s debut date, “medium” style: \(myFormatter.string(from: swiftDebutDate)).") myFormatter.dateStyle = .long print("Swift’s debut date, “long” style: \(myFormatter.string(from: swiftDebutDate)).") myFormatter.dateStyle = .full print("Swift’s debut date, “full” style: \(myFormatter.string(from: swiftDebutDate)).") myFormatter.dateStyle = .none print("Swift’s debut date, “none” style: \(myFormatter.string(from: swiftDebutDate)).") // Let’s convert a Date into a String, part 2: A date and a time // ============================================================= // SwiftUI was introduced at WWDC 2019 on // June 3, 2019 at 12:08 p.m. Pacific Daylight Time. let swiftUIDebutDateComponents = DateComponents( timeZone: TimeZone(identifier: "America/Los_Angeles"), year: 2019, month: 6, day: 3, hour: 12, minute: 8 ) let swiftUIDebutDate = userCalendar.date(from: swiftUIDebutDateComponents)! print("The newly-created date: \(swiftUIDebutDate.description(with: Locale(identifier: "en-US"))).") myFormatter.dateStyle = .short myFormatter.timeStyle = .short print("Swift’s debut date and time, “short” style: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateStyle = .medium myFormatter.timeStyle = .medium print("Swift’s debut date and time, “medium” style: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateStyle = .long myFormatter.timeStyle = .long print("Swift’s debut date and time, “long” style: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateStyle = .full myFormatter.timeStyle = .full print("Swift’s debut date and time, “full” style: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateStyle = .full myFormatter.timeStyle = .short print("Swift’s debut date and time, with “full” style date and “short” style time: \(myFormatter.string(from: swiftUIDebutDate)).") // Show only the time myFormatter.dateStyle = .none myFormatter.timeStyle = .medium print("Swift’s debut time: \(myFormatter.string(from: swiftUIDebutDate)).") // Show only the date myFormatter.dateStyle = .full myFormatter.timeStyle = .none print("Swift’s debut date: \(myFormatter.string(from: swiftUIDebutDate)).") // Let’s convert a Date into a String, part 3: Displaying dates and times in other languages // ========================================================================================= // We want to see as much of these languages as possible, // so let’s set both dateStyle and timeStyle to .full. myFormatter.dateStyle = .full myFormatter.timeStyle = .full myFormatter.locale = Locale(identifier: "fr") print("International French: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.locale = Locale(identifier: "fr-CA") print("Canadian French: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.locale = Locale(identifier: "hr") print("Croatian: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.locale = Locale(identifier: "ko_KR") print("Korean: \(myFormatter.string(from: swiftUIDebutDate)).") // Let’s convert a Date into a String, part 4: Custom date/time formats // ==================================================================== // Setting the locale to POSIX ensures that the user's locale // won't be used to format the Date. myFormatter.locale = Locale(identifier: "en_US_POSIX") // DateFormatter's format string uses the date format specifiers // spelled out in Unicode Technical Standard #35 (located at // http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns) print("Custom date and time formats:") myFormatter.dateFormat = "y-MM-dd" print("Swift’s debut date and time, y-MM-dd format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "'Year: 'y' Month: 'M' Day: 'd" print("Year: y Month: M Day: d format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "MM/dd/yy" print("MM/dd/yy format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "MMM dd, yyyy" print("MMM dd, yyyy format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "E MMM dd, yyyy" print("E MMM dd, yyyy format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "EEEE, MMMM dd, yyyy' at 'h:mm a" print("EEEE, MMMM dd, yyyy' at 'h:mm a. format: \(myFormatter.string(from: swiftUIDebutDate)).") myFormatter.dateFormat = "EEEE, MMMM dd, yyyy' at 'h:mm a zzzz" print("EEEE, MMMM dd, yyyy' at 'h:mm a zzzz. format: \(myFormatter.string(from: swiftUIDebutDate)).") // Let’s convert a String into a Date // ================================== // Let’s define the format for date strings we want to parse: myFormatter.dateFormat = "yyyy/MM/dd hh:mm Z" // Here's a date in the specified format. // DateFormatter’s date(from:) method will be able to parse it. let newDate1 = myFormatter.date(from: "2019/06/03 12:08 -0700") print("newDate1’s value is: \(newDate1?.description ?? "nil").") // And here's the same date, but in a different format: let newDate2 = myFormatter.date(from: "Jun 6, 2019, 12:08 PM PDT") print("newDate2’s value is: \(newDate2?.description ?? "nil").") // Let's change the date format strings and try // date(from:) with the same two strings: myFormatter.dateFormat = "MMM d, yyyy, hh:mm a zz" let newDate3 = myFormatter.date(from: "2019/06/03 12:08 -0700") print("newDate3’s value is: \(newDate3?.description ?? "nil").") let newDate4 = myFormatter.date(from: "Jun 6, 2019, 12:08 PM PDT") print("newDate4’s value is: \(newDate4?.description ?? "nil").") // Don’t forget that you can get weird if you expect to // parse dates in weird formats! // (D is the format string for “day of year”, which can be 1...366) myFormatter.dateFormat = "y 😍 D" let weirdEmojiDate = myFormatter.date(from: "2020 😍 333") print("weirdEmojiDate’s value is: \(weirdEmojiDate?.description ?? "nil").")
You can download the playground here (3KB, zipped Xcode playground file).
In the next installment on dates and times in Swift 5, we’ll look at date calculations.
The How to work with dates and times in Swift 5 series
If you’re just getting started with programming dates and times in Swift 5, you probably looked at Apple’s documentation and got confused. Let me reassure you that it isn’t your fault. For starters, Apple’s documentation hasn’t been very good lately, and I’m not the only developer who’s noticed this decline in quality.
There’s also the fact that working with dates and times in Swift 5 seems unnecessarily complicated. If you’ve come to Swift from other programming languages, such as JavaScript, which uses a single object type called Date
, the idea of having this set of classes just to handle dates and times looks like overkill:

I promise you that there’s a method to this madness. The set of structs for working with dates and times in Swift 5 make for a super-flexible system that will let you keep store, calculate, and display dates and times no matter what time zone, calendar system, or language you use.
For example, with Swift, I can easily schedule an appointment for the third Wednesday of July at 3:30 p.m. Pacific and then display that date as it would appear in the Coptic Calendar system in Melbourne, Australia. If you had to do that in JavaScript, the only easy answer is “go away” (there are, of course, some less polite variations of that answer).
This series, Dates and times in Swift 5, will help you make sense of the set of classes that Swift provides for dealing with timekeeping and time calculations. It will do so with a lot of examples and experimentation. I strongly recommend that you fire up Xcode, open a Swift playground, and follow along.
In this article, I’ll show you the following:
- The
Date
struct, which stores date and times in Swift 5. - The
Calendar
struct, which represents one of 16 different calendar systems, and provides a meaningful context forDate
s. - The
DateComponents
struct, which a collection of date and time components, such as years, months, days, hours, minutes, and so on. - How to create a
Date
object representing the current date and time. - How to create a
Date
object representing a given date and time. - How to create a
Date
object based on criteria such as “the first Friday of June 2020.” - How to extract the parts of a date, such as the year, month, day, time, and so on from a
Date
object.
The Date struct

The Date
struct is used to represent dates and times in Swift 5, and it’s designed to do so in the most flexible way possible: as a number of seconds relative to the start of the Third Millennium, January 1, 2001, 00:00:00 UTC.
This approach allows Date
to be independent of any time zone or any calendar system; you store it as an amount of time before or after the start of the Third Millennium and use other objects (which you’ll see soon) to convert into the appropriate calendar, time zone, and format.
To create a Date
object containing the current date and time, simply create an instance of Date
using the default, no-argument initializer.
Open a playground in Xcode and add the following:
// To create a Date representing the current date and time, // simply initialize a new Date. let now = Date() // Contains the date and time that this object // was instantiated.
To see the value stored inside the newly created Date
object, use Date
’s timeIntervalSinceReferenceDate
property, which contains the number of seconds since the reference date.
Add the following to the playground, then run it:
// How many seconds have passed between the Date we just created // and the reference date of January 1, 2001, 00:00:00 UTC? print("It’s been \(now.timeIntervalSinceReferenceDate) seconds since the start of the Third Millennium.")
When I ran that line of code (just before 9:00 a.m. EDT on Tuesday, May 26, 2020), I got this output: It’s been 612190714.691352 seconds since the start of the Third Millennium.
To see the Date
’s value in a more meaningful form, use Date
’s description
property to see it in “YYYY-MM-DD HH:MM:SS +HHMM” format, or the description(with:)
method with a Locale
instance to display its value using a specified locale.
Add the following to the playground, then run it:
// Use Date’s description property for debugging print(now.description) // YYYY-MM-DD HH:MM:SS +HHMM print(now.description(with: Locale(identifier: "en-US"))) // US English print(now.description(with: Locale(identifier: "en-GB"))) // UK English* print(now.description(with: Locale(identifier: "es"))) // Spanish print(now.description(with: Locale(identifier: "zh-Hans"))) // Simplified Chinese // * Yes, I know that “gb” means “Great Britain” and that it’s not the same thing // as the UK. I didn’t come up with these locale names!
To create a Date
object containing a date and time that isn’t the current date and time, and without other helper objects, you have to use one of the following initializers:
Date initializer | What it does |
Date(timeIntervalSinceNow:) |
Creates a Parameters:
|
Date(timeIntervalSinceReferenceDate:) |
Creates a Parameters:
|
Date(timeIntervalSince1970:) |
Creates a Parameters:
|
Date(timeInterval:since:) |
Creates a Parameters:
|
Here are some examples showing these initializers in action — add the following to the playground, then run it:
// Date’s other initializers expect arguments of type TimeInterval, // which is a typealias for Double. // To create a Date a specified number of seconds before or after // the current date and time, use the "timeIntervalSinceNow" initializer. let fiveMinutesAgo = Date(timeIntervalSinceNow: -5 * 60) let fiveMinutesFromNow = Date(timeIntervalSinceNow: 5 * 60) // Martin Cooper made the first cellular phone call on April 3, 1973. // We don't know the exact time the call was made, but it happened // sometime during business hours in New York City, in the U.S. Eastern // Time Zone (UTC-5). // // Let’s suppose that he made the call at 12:00 p.m.. That would mean that // he made the call 875,602,800 seconds BEFORE the reference date and time. let firstCellularCallDate = Date(timeIntervalSinceReferenceDate: -875_602_800) // The "Stevenote" where the iPhone was introduced started on January 9, 2007, // 10 a.m. Pacific time (UTC-7), 190,058,400 seconds AFTER the reference date and time. let iPhoneStevenoteDate = Date(timeIntervalSinceReferenceDate: 190_058_400) // Unix time (a.k.a. POSIX time or Epoch Time) is the way time is represented // by Unix, Unix-like, and other operating systems. It defines time as a // number of seconds after the Unix Epoch, January 1, 1970, 00:00:00 UTC. // To create a Date relative to the Unix Epoch, use the // "timeIntervalSince1970" initializer. let oneYear = TimeInterval(60 * 60 * 24 * 365) let newYears1971 = Date(timeIntervalSince1970: oneYear) let newYears1969 = Date(timeIntervalSince1970: -oneYear) // To create a Date relative to another Date, use the // "timeInterval:Since:" initializer. // // The "Stevenote" where the iPad was introduced started on January 27, 2010, // 10 a.m. Pacific time (UTC-7), 96,249,600 seconds after the start of the // iPhone Stevenote three years earlier. let secondsBetweeniPhoneAndiPadStevenote = TimeInterval(96_249_600) let iPadStevenoteDate = Date(timeInterval: secondsBetweeniPhoneAndiPadStevenote, since: iPhoneStevenoteDate)
Of course, we don’t think of dates and times in terms of seconds relative to the start of the Third Millennium, or the start of the Unix Epoch, or any other arbitrary date and time. That’s why dates and times in Swift 5 make use of a couple of other structs to help us make sense of Date
s: Calendar
and DateComponents
. Calendar
s give dates context, and DateComponents
let us assemble dates or break dates apart.
The Calendar struct

Think of the Calendar
struct as a way to view Date
s in a way that makes more sense to us: not as a number of seconds before or after January 1, 2001 00:00:00 UTC, but in terms of a date in a calendar system.
The Calendar
struct supports 16 different calendar systems, including the Gregorian calendar (a.k.a. the Western or Christian calendar), which is likely the one you use the most.
The DateComponents struct

The DateComponents
struct allows us to assemble a point in time or a length of time out of components such as year, month, day, hour, minute, and more. We’ll use DateComponents
to construct a Date
object using a year, month, day and time, and also deconstruct a Date
object into a year, month, day and time.
Consider Swift’s reference date: January 1, 2001 at 00:00:00 UTC. Here are what its components are in various calendar systems:
Calendar | Date components for January 1, 2001 00:00:00 UTC |
Gregorian |
|
Hebrew |
|
Buddhist |
|
Let’s use Calendar
and DateComponents
to make it easier to create Dates
.
Creating known Date
s with Calendar
and DateComponents
Let’s create a Date
based on the first moment in phone history: March 10, 1876, when Alexander Graham Bell made the first phone call. I don’t know what time he made the call on that day, so for this example, I’m going to assume that it happened at 1:00 p.m..
Add the following to the playground, then run it:
// 1 // To translate between Dates and DateComponents, you need a Calendar. // The user's Calendar is probably the one you’ll use most often, // as it incorporates the user's locale and time zone settings. let userCalendar = Calendar.current // March 10, 1876: The day Alexander Graham Bell // made the first phone call // --------------------------------------------- // 2 // DateComponents' full initializer method is very thorough, but very long. let firstLandLineCallDateComponents = DateComponents( calendar: nil, timeZone: TimeZone(secondsFromGMT: -18000), era: nil, year: 1876, month: 3, day: 10, hour: 13, minute: 00, second: 00, nanosecond: nil, weekday: nil, weekdayOrdinal: nil, quarter: nil, weekOfMonth: nil, weekOfYear: nil, yearForWeekOfYear: nil) // 3 let firstLandLineCallDate = userCalendar.date(from: firstLandLineCallDateComponents)! // 4 print("The first land line phone call happened on \(firstLandLineCallDate.description(with: Locale(identifier: "en-US"))).") print("That’s \(firstLandLineCallDate.timeIntervalSinceReferenceDate) seconds since the start of the Third Millennium.")
In the code, we:
- Get the user’s current
Calendar
. - Create a
DateComponents
struct,firstLandLineCallDateComponents
, providing values for the timeZone:,year:
,month:
, andday:
,hour:
,minute:
, andsecond:
parameters, andnil
for all the others. Bell made the call in his laboratory in Boston, whose time zone is UTC-5. We construct the time zone using theTimeZone(secondsFromGMT:)
constructor, which specifies how many seconds the given time zone is ahead or behind UTC (GMT — Greenwich Meridian Time — is the old name for UTC). - Use the user’s
Calendar
to createfirstLandLineCallDate
usingfirstLandLineCallDateComponents
. - Print the date of the call using the American English format as well as in terms of seconds since the start of the Third Millennium. Since the call happened over a century before the Third Millennium, this number is negative.
On my computer, the output is:
The first land line phone call happened on Friday, March 10, 1876 at 12:03:58 PM GMT-04:56:02.
That’s -3938655600.0 seconds since the start of the Third Millennium.
Let’s create another date: December 9, 1968 at 3:45 p.m. Pacific, when Douglas Englebart changes the world of computing with his demonstration of the GUI, mouse, chording keyboard, hypertext links, and collaborative document editing — a session that would come to be called “The Mother of All Demos.”
Add the following to the playground, then run it:
// December 9, 1968, 3:45 p.m. Pacific Time: // Douglas Englebart gives “The Mother of All Demos” // ------------------------------------------------- // This time, we’ll use only the DateComponents initializer parameters we need. // 1 let motherOfAllDemosDateComponents = DateComponents( timeZone: TimeZone(identifier: "America/Los_Angeles"), year: 1968, month: 12, day: 9, hour: 15, minute: 45 ) // 2 let motherOfAllDemosDate = userCalendar.date(from: motherOfAllDemosDateComponents)! // 3 print("The Mother of All Demos happened on \(motherOfAllDemosDate.description(with: Locale(identifier: "en-US"))).") print("That’s \(motherOfAllDemosDate.timeIntervalSince1970) seconds since the start of the Unix Epoch.")
In the code, we:
- Create a
DateComponents
struct,motherOfAllDemosDateComponents
, providing values for only the parameters that matter t us:timeZone:
,year:
,month:
, andday:
,hour:
, andminute:
. This time, we construct the time zone using theTimeZone(identifier:)
constructor, which specifies the time zone by the appropriate TZ database name. - Use the user’s
Calendar
(userCalendar
, which we’ve already declared) to createmotherOfAllDemosDate
usingmotherOfAllDemosDateComponents
. - Print the date of the call using the American English format as well as in terms of seconds since the start of the Unix Epoch. Since the call happened a little over a year before the Unix Epoch, this number is negative.
On my computer, the output is:
The Mother of All Demos happened on Monday, December 9, 1968 at 6:45:00 PM GMT-05:00.
That’s -33437700.0 seconds since the start of the Unix Epoch.
Let’s try creating another momentous date in phone history: the day when Martin Cooper made the first cellular phone call, April 3, 1973.
Add the following to the playground, then run it:
// April 3, 1973: Martin Cooper makes the first // cellular phone call // -------------------------------------------- // 1 var firstCellCallDateComponents = DateComponents() // 2 firstCellCallDateComponents.year = 1973 firstCellCallDateComponents.month = 4 firstCellCallDateComponents.day = 3 firstCellCallDateComponents.timeZone = TimeZone(abbreviation: "EST") // 3 let firstCellCallDate = userCalendar.date(from: firstCellCallDateComponents)! print("Martin Cooper made the first cellular call on \(firstCellCallDate.description(with: Locale(identifier: "en-US"))).") print("That’s \(firstCellCallDate.timeIntervalSince(motherOfAllDemosDate)) seconds since the Mother of All Demos.")
In the code, we:
- Create an empty
DateComponents
struct,firstCellCallDateComponents
. Note that we’re usingvar
instead oflet
to declare it; that’s because we’re going to set its properties after it’s been declared, and you can’t do that to a struct declared withlet
. - Set the year, month, and day properties of
firstCellCallDateComponents
to correspond to the date April 3, 1973 in Eastern Standard Time. This time, we construct the time zone using theTimeZone(abbreviation:)
constructor, which specifies the time zone by the appropriate time zone abbreviation. - Use the user’s
Calendar
to createfirstCellCallDate
usingfirstCellCallDateComponents
.
On my computer, the output is:
Martin Cooper made the first cellular call on Tuesday, April 3, 1973 at 12:00:00 AM Eastern Standard Time.
That’s 136098900.0 seconds since the Mother of All Demos.
Note that in the absence of a specified time, the assumed time is 00:00:00.
Discovering Date
s with Calendar
and DateComponents
So far, we’ve created Date
s based on known dates and times — March 10, 1876, December 9, 1968, and April 3, 1973. How about Date
s where we don’t have a specific date, but have enough criteria to specify a date? The great thing about working with dates and times in Swift 5 is that the Calendar
class is that it does its best to work with the DateComponents
that you give it, and DateComponents
gives you all sorts of ways to specify a date.
Having come from Canada, the country with the world’s highest per capita donut shop concentration and the people who eat the most donuts per capita, I can assure you that National Donut Day has been a real thing since 1938, and it takes place on the first Friday in June. We can find out what date it falls on in 2020 — or any other year — through the judicious use of DateComponents
properties.
Add the following to the playground, then run it:
// The first Friday in June, 2020: // National Donut Day // ------------------------------- let donutDay2020Components = DateComponents( year: 2020, // We want a date in 2020, month: 6, // in June. weekday: 6, // We want a Friday; weekdayOrdinal: 1 // the first one. ) let donutDay2020 = userCalendar.date(from: donutDay2020Components)! print("Donut Day 2020 happens on \(donutDay2020Date.description(with: Locale(identifier: "en-US"))).")
You should be familiar with the year
and month
DayComponents
properties by now, and we’re using a couple that may be new to you:
weekday
: Specifies a day of the week. With the Gregorian calendar, valid values are 1 through 7, where 1 is Sunday, 2 is Monday, 3 is Tuesday, and so on. Since we’re looking for a Friday, we’ve set this value to 6.weekdayOrdinal
: Specifies the order of the given weekday in the next larger specified calendar unit. Since we setweekday
to 6 and set this value to 1, and since the next largest specified calendar unit wasmonth
, we’ll get the date of the first Friday of the month.
On my computer, the output is:
Donut Day 2020 happens on Friday, June 5, 2020 at 12:00:00 AM Eastern Daylight Time.
Note that in the absence of a specified time zone, the assumed time zone is the system time zone, which in my case is Eastern Daylight Time (UTC-4).
In the spirit of the fake book cover shown above, let’s see what happens when we use Donut Day 2020’s components, except for the month.
Add the following to the playground, then run it:
// Mystery Friday 2020 // ------------------------------- let mysteryFridayDateComponents = DateComponents( year: 2020, // We want a date in 2020: weekday: 6, // A Friday; weekdayOrdinal: 1 // the first one. ) let mysteryFridayDate = userCalendar.date(from: mysteryFridayDateComponents)! print("Mystery Friday happens on \(mysteryFridayDate.description(with: Locale(identifier: "en-US"))).")
On my computer, the output is:
Mystery Friday happens on Friday, January 3, 2020 at 12:00:00 AM Eastern Standard Time.
That makes sense: By specifying year 2020, weekday 6 and weekday ordinal 1, we just asked for the first Friday of the year.
Suppose you’re meeting up with a friend in Tokyo some relaxing Suntory times at 9:00 p.m. on the Thursday of the 27th week of 2020. What is that date?
The answer comes from this code:
// 9:00 p.m. Tokyo time on the Thursday of the 27th week of 2020 // ------------------------------------------------------------- var relaxingSuntoryTimesDateComponents = DateComponents( timeZone: TimeZone(identifier: "Asia/Tokyo")!, year: 2020, hour: 21, weekday: 5, weekOfYear: 27 ) let relaxingSuntoryTimesDate = userCalendar.date(from: relaxingSuntoryTimesDateComponents)! print("Thursday on the 27th week of 2020 at 9:00 p.m. Tokyo time is \(relaxingSuntoryTimesDate.description(with: Locale(identifier: "en-US"))).")
On my computer, the output is:
Thursday on the 27th week of 2020 at 9:00 p.m. Tokyo time is Thursday, July 2, 2020 at 8:00:00 AM Eastern Daylight Time.
Here’s a simple question: What’s the 234th day of 2020?
Add the following to the playground, then run it:
// 234th day of 2020 // ----------------- let day234DateComponents = DateComponents( year: 2020, // We want a date in 2020: day: 234 // the 234th day. ) let day234Date = userCalendar.date(from: day234DateComponents)! print("The 234th day of 2020 is \(day234Date.description(with: Locale(identifier: "en-US"))).")
On my computer, the output is:
The 234th day of 2020 is Friday, August 21, 2020 at 12:00:00 AM Eastern Daylight Time.
The “Ten Thousand Hour Rule”, which states that it takes 10,000 hours of directed practice to become an expert at something, was popularized by Malcolm Gladwell in his novel Blink. There’s been a lot of debate about the truth of the rule, and we’re going to side-step it to ask a related question: If I set out to get 10,000 hours of non-stop practice starting on midnight of January 1, 2020, when would I be done?
Add the following to the playground, then run it:
// 10000th hour of 2020 // ----------------- let hour10kDateComponents = DateComponents( year: 2020, // We want a date in 2020: hour: 10000 // the 10000th hour. ) let hour10kDate = userCalendar.date(from: hour10kDateComponents)! print("Your 10,000 hours would complete on \(hour10kDate.description(with: Locale(identifier: "en-US"))).")
On my computer, the output is:
Your 10,000 hours would complete on Saturday, February 20, 2021 at 4:00:00 PM Eastern Standard Time.
In other words, 10,000 hours is longer than a year.
Let’s look at the case of overflow. What happens if you try to create a Date
using components that would define the nonsense date September 50th, 2020?
Add the following to the playground, then run it:
// September 50, 2020 // ------------------ var sept50DateComponents = DateComponents( year: 2020, month: 9, day: 50) let sept50Date = userCalendar.date(from: sept50DateComponents)! print("September 50, 2020 is actually \(sept50Date.description(with: Locale(identifier: "en-US"))).")
On my computer, the output is:
September 50, 2020 is actually Tuesday, October 20, 2020 at 12:00:00 AM Eastern Daylight Time.
Swift treats these date components as “the start of September, plus 50 days” — September’s 30 days, plus an additional 20 days into October.
Let’s extract DateComponents
from a Date
, part 1
Now that we’ve created some Date
s using DateComponents
, let’s do the reverse and extract DateComponents
from given Date
s. We’ll continue with our playground and use a Date
we’ve already created
Let’s extract the year, month, and day from firstLandPhoneCallDate
, which corresponds to the date of Alexander Graham Bell’s historic phone call, March 10, 1876:
// We want to extract the year, month, and day from firstLandLineCallDate let alexanderGrahamBellDateComponents = userCalendar.dateComponents([.year, .month, .day], from: firstLandLineCallDate) print("The first land line phone call happened \(-firstLandLineCallDate.timeIntervalSinceNow) seconds ago.") print("Year: \(alexanderGrahamBellDateComponents.year!)") print("Month: \(alexanderGrahamBellDateComponents.month!)") print("Day: \(alexanderGrahamBellDateComponents.day!)")
When I ran it on my computer, the output was:
The first land line phone call happened 4550860374.044979 seconds ago.
Year: 1876
Month: 3
Day: 10
Let’s extract DateComponents
from a Date
, part 2
This time, let’s extract the DateComponents
from another Date
we’d previously defined: The date and time of the “Stevenote” where the original iPhone was first announced:
It happened 190,058,400 seconds after the reference date. For most of us, this is a meaningless figure, so we’ll extract the following DateComponents
from this Date
:
- Year
- Month
- Day
- Hour
- Minute
- What day of the week it fell on
- What week of the year it fell on
Here’s the code:
// The original iPad Stevenote (10 a.m. Pacific time, // January 27, 2010) // ---------------------------------------------------- // We want to extract ALL the DateComponents for this date // in local time for the event (which took place in San Francisco). let iPadStevenoteDateComponents = pacificCalendar.dateComponents([.calendar, .day, .era, .hour, .minute, .month, .nanosecond, .quarter, .second, .timeZone, .weekday, .weekdayOrdinal, .weekOfMonth, .weekOfYear, .year, .yearForWeekOfYear], from: iPadStevenoteDate) print("The original iPad Stevenote happened \(-iPadStevenoteDate.timeIntervalSinceNow) seconds ago.") print("Calendar: \(iPadStevenoteDateComponents.calendar!.identifier)") print("Day: \(iPadStevenoteDateComponents.day!)") print("Era: \(iPadStevenoteDateComponents.era!)") print("Hour: \(iPadStevenoteDateComponents.hour!)") print("Minute: \(iPadStevenoteDateComponents.minute!)") print("Month: \(iPadStevenoteDateComponents.month!)") print("Nanosecond: \(iPadStevenoteDateComponents.nanosecond!)") print("Quarter: \(iPadStevenoteDateComponents.quarter!)") print("Second: \(iPadStevenoteDateComponents.second!)") print("Time zone: \(iPadStevenoteDateComponents.timeZone!)") print("Weekday: \(iPadStevenoteDateComponents.weekday!)") print("Weekday ordinal: \(iPadStevenoteDateComponents.weekdayOrdinal!)") print("Week of month: \(iPadStevenoteDateComponents.weekOfMonth!)") print("Week of year: \(iPadStevenoteDateComponents.weekOfYear!)") print("Year: \(iPadStevenoteDateComponents.year!)") print("Year for week of year: \(iPadStevenoteDateComponents.yearForWeekOfYear!)")
Let’s extract DateComponents
from a Date
, part 3
Let’s try it again with another key iOS date — the Stevenote where the original iPad was announced:
This time, if you were to ask Swift when this Stevenote took place, it would reply “286,308,000 seconds after the reference date”. Let’s get all the DateComponents
for this date:
// The original iPad Stevenote (10 a.m. Pacific time, // January 27, 2010) // ---------------------------------------------------- // We want to extract ALL the DateComponents for this date // in local time for the event (which took place in San Francisco). let iPadStevenoteDateComponents = pacificCalendar.dateComponents([.calendar, .day, .era, .hour, .minute, .month, .nanosecond, .quarter, .second, .timeZone, .weekday, .weekdayOrdinal, .weekOfMonth, .weekOfYear, .year, .yearForWeekOfYear], from: iPadStevenoteDate) print("The original iPad Stevenote happened \(-iPadStevenoteDate.timeIntervalSinceNow) seconds ago.") print("Calendar: \(iPadStevenoteDateComponents.calendar!.identifier)") print("Day: \(iPadStevenoteDateComponents.day!)") print("Era: \(iPadStevenoteDateComponents.era!)") print("Hour: \(iPadStevenoteDateComponents.hour!)") print("Minute: \(iPadStevenoteDateComponents.minute!)") print("Month: \(iPadStevenoteDateComponents.month!)") print("Nanosecond: \(iPadStevenoteDateComponents.nanosecond!)") print("Quarter: \(iPadStevenoteDateComponents.quarter!)") print("Second: \(iPadStevenoteDateComponents.second!)") print("Time zone: \(iPadStevenoteDateComponents.timeZone!)") print("Weekday: \(iPadStevenoteDateComponents.weekday!)") print("Weekday ordinal: \(iPadStevenoteDateComponents.weekdayOrdinal!)") print("Week of month: \(iPadStevenoteDateComponents.weekOfMonth!)") print("Week of year: \(iPadStevenoteDateComponents.weekOfYear!)") print("Year: \(iPadStevenoteDateComponents.year!)") print("Year for week of year: \(iPadStevenoteDateComponents.yearForWeekOfYear!)")
When I ran it on my computer, the output was:
The original iPad Stevenote happened 325902655.723246 seconds ago.
Calendar: gregorian
Day: 27
Era: 1
Hour: 10
Minute: 0
Month: 1
Nanosecond: 0
Quarter: 0
Second: 0
Time zone: America/Los_Angeles (fixed)
Weekday: 4
Weekday ordinal: 4
Week of month: 5
Week of year: 5
Year: 2010
Year for week of year: 2010
Let’s take a look at each DateComponents
property and what it represents:
Property | Description |
---|---|
calendar |
The calendar system for the date represented by this set of DateComponents . We got these DateComponents by converting a Date using a Gregorian Calendar, so in this case, this value is gregorian. |
day |
The day number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 27. |
era |
The era for this particular date, which depends on the date’s calendar system. In this case, we’re using the Gregorian calendar, which has two eras:
|
hour |
The hour number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 13, because in my time zone, 18:00:00 UTC is 13:00:00. |
minute |
The minute number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 0. |
month |
The month number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 1. |
nanosecond |
The nanosecond number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 0. |
quarter |
The quarter number of this particular date and time. January 27, 2010, 18:00:00 UTC, is in the first quarter of the year, so this value is 0. |
second |
The second number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 0. |
timeZone |
The time zone of this particular date and time. I’m in the UTC-5 time zone (US Eastern), so this value is set to that time zone. |
weekday |
The day of the week of this particular date and time. In the Gregorian calendar, Sunday is 1, Monday is 2, Tuesday is 3, and so on. January 27, 2010, was a Wednesday, so this value is 4. |
weekdayOrdinal |
The position of the weekday within the next larger specified calendar unit, which in this case is a month. So this specifies nth weekday of the given month. Jauary 27, 2010 was on the 4th Wednesday of the month, so this value is 4. |
weekOfMonth |
The week of the month of this particular date and time. January 27, 2010 fell on the 5th week of January 2010, so this value is 5. |
weekOfYear |
The week of the year of this particular date and time. January 27, 2010 fell on the 5th week of 2010, so this value is 5. |
year |
The year number of this particular date and time. For January 27, 2010, 18:00:00 UTC, this value is 2010. |
yearForWeekOfYear |
Oh wow, this is so hard to explain that I’ll leave it to Apple’s docs. |
Wrapping it all up
Here’s the complete code for the playground containing all the code we just worked with while learning about dates and times in Swift 5:
import UIKit // To create a Date representing the current date and time, // simply initialize a new Date. let now = Date() // Contains the date and time that this object // was instantiated. // How many seconds have passed between the Date we just created // and the reference date of January 1, 2001, 00:00:00 UTC? print("It’s been \(now.timeIntervalSinceReferenceDate) seconds since the start of the Third Millennium.") // Use Date’s description property for debugging print(now.description) // YYYY-MM-DD HH:MM:SS +HHMM print(now.description(with: Locale(identifier: "en-US"))) // US English print(now.description(with: Locale(identifier: "en-GB"))) // UK English* print(now.description(with: Locale(identifier: "es"))) // Spanish print(now.description(with: Locale(identifier: "zh-Hans"))) // Simplified Chinese // * Yes, I know that “gb” means “Great Britain” and that it’s not the same thing // as the UK. I didn’t come up with these locale names! // Date’s other initializers expect arguments of type TimeInterval, // which is a typealias for Double. // To create a Date a specified number of seconds before or after // the current date and time, use the "timeIntervalSinceNow" initializer. let fiveMinutesAgo = Date(timeIntervalSinceNow: -5 * 60) let fiveMinutesFromNow = Date(timeIntervalSinceNow: 5 * 60) // Martin Cooper made the first cellular phone call on April 3, 1973. // We don't know the exact time the call was made, but it happened // sometime during business hours in New York City, in the U.S. Eastern // Time Zone (UTC-5). // // Let’s suppose that he made the call at 12:00 p.m.. That would mean that // he made the call 875,602,800 seconds BEFORE the reference date and time. let firstCellularCallDate = Date(timeIntervalSinceReferenceDate: -875_602_800) // The "Stevenote" where the iPhone was introduced started on January 9, 2007, // 10 a.m. Pacific time (UTC-7), 190,058,400 seconds AFTER the reference date and time. let iPhoneStevenoteDate = Date(timeIntervalSinceReferenceDate: 190_058_400) // Unix time (a.k.a. POSIX time or Epoch Time) is the way time is represented // by Unix, Unix-like, and other operating systems. It defines time as a // number of seconds after the Unix Epoch, January 1, 1970, 00:00:00 UTC. // To create a Date relative to the Unix Epoch, use the // "timeIntervalSince1970" initializer. let oneYear = TimeInterval(60 * 60 * 24 * 365) let newYears1971 = Date(timeIntervalSince1970: oneYear) let newYears1969 = Date(timeIntervalSince1970: -oneYear) // To create a Date relative to another Date, use the // "timeInterval:Since:" initializer. // // The "Stevenote" where the iPad was introduced started on January 27, 2010, // 10 a.m. Pacific time (UTC-7), 96,249,600 seconds after the start of the // iPhone Stevenote three years earlier. let secondsBetweeniPhoneAndiPadStevenote = TimeInterval(96_249_600) let iPadStevenoteDate = Date(timeInterval: secondsBetweeniPhoneAndiPadStevenote, since: iPhoneStevenoteDate) // To translate between Dates and DateComponents, you need a Calendar. // The user's Calendar is probably the one you’ll use most often, // as it incorporates the user's locale and time zone settings. let userCalendar = Calendar.current // March 10, 1876: The day Alexander Graham Bell // made the first phone call in Boston (UTC-5) // --------------------------------------------- // DateComponents' full initializer method is very thorough, but very long. let firstLandLineCallDateComponents = DateComponents( calendar: nil, timeZone: TimeZone(secondsFromGMT: -18000), era: nil, year: 1876, month: 3, day: 10, hour: 12, minute: 00, second: 00, nanosecond: nil, weekday: nil, weekdayOrdinal: nil, quarter: nil, weekOfMonth: nil, weekOfYear: nil, yearForWeekOfYear: nil) let firstLandLineCallDate = userCalendar.date(from: firstLandLineCallDateComponents)! print("The first land line phone call happened on \(firstLandLineCallDate.description(with: Locale(identifier: "en-US"))).") print("That’s \(firstLandLineCallDate.timeIntervalSinceReferenceDate) seconds since the start of the Third Millennium.") // December 9, 1968, 3:45 p.m. Pacific Time: // Douglas Englebart gives “The Mother of All Demos” // ------------------------------------------------- // This time, we’ll use only the DateComponents initializer parameters we need. let motherOfAllDemosDateComponents = DateComponents( timeZone: TimeZone(identifier: "America/Los_Angeles"), year: 1968, month: 12, day: 9, hour: 15, minute: 45 ) let motherOfAllDemosDate = userCalendar.date(from: motherOfAllDemosDateComponents)! print("The Mother of All Demos happened on \(motherOfAllDemosDate.description(with: Locale(identifier: "en-US"))).") print("That’s \(motherOfAllDemosDate.timeIntervalSince1970) seconds since the start of the Unix Epoch.") // April 3, 1973: Martin Cooper makes the first // cellular phone call // -------------------------------------------- var firstCellCallDateComponents = DateComponents() firstCellCallDateComponents.year = 1973 firstCellCallDateComponents.month = 4 firstCellCallDateComponents.day = 3 firstCellCallDateComponents.timeZone = TimeZone(abbreviation: "EST") let firstCellCallDate = userCalendar.date(from: firstCellCallDateComponents)! print("Martin Cooper made the first cellular call on \(firstCellCallDate.description(with: Locale(identifier: "en-US"))).") print("That’s \(firstCellCallDate.timeIntervalSince(motherOfAllDemosDate)) seconds since the Mother of All Demos.") // The first Friday in June, 2020: // National Donut Day // ------------------------------- let donutDay2020DateComponents = DateComponents( year: 2020, // We want a date in 2020, month: 6, // in June. weekday: 6, // We want a Friday; weekdayOrdinal: 1 // the first one. ) let donutDay2020Date = userCalendar.date(from: donutDay2020DateComponents)! print("Donut Day 2020 happens on \(donutDay2020Date.description(with: Locale(identifier: "en-US"))).") // Mystery Friday 2020 // ------------------------------- let mysteryFridayDateComponents = DateComponents( year: 2020, // We want a date in 2020: weekday: 6, // A Friday; weekdayOrdinal: 1 // the first one. ) let mysteryFridayDate = userCalendar.date(from: mysteryFridayDateComponents)! print("Mystery Friday happens on \(mysteryFridayDate.description(with: Locale(identifier: "en-US"))).") // 9:00 p.m. Tokyo time on the Thursday of the 27th week of 2020 // ------------------------------------------------------------- var relaxingSuntoryTimesDateComponents = DateComponents( timeZone: TimeZone(identifier: "Asia/Tokyo")!, year: 2020, hour: 21, weekday: 5, weekOfYear: 27 ) let relaxingSuntoryTimesDate = userCalendar.date(from: relaxingSuntoryTimesDateComponents)! print("Thursday on the 27th week of 2020 at 9:00 p.m. Tokyo time is \(relaxingSuntoryTimesDate.description(with: Locale(identifier: "en-US"))).") // 234th day of 2020 // ----------------- let day234DateComponents = DateComponents( year: 2020, // We want a date in 2020: day: 234 // the 234th day. ) let day234Date = userCalendar.date(from: day234DateComponents)! print("The 234th day of 2020 is \(day234Date.description(with: Locale(identifier: "en-US"))).") // 10000th hour of 2020 // ----------------- let hour10kDateComponents = DateComponents( year: 2020, // We want a date in 2020: hour: 10000 // the 10000th hour. ) let hour10kDate = userCalendar.date(from: hour10kDateComponents)! print("Your 10,000 hours would complete on \(hour10kDate.description(with: Locale(identifier: "en-US"))).") // September 50, 2020 // ------------------ var sept50DateComponents = DateComponents( year: 2020, month: 9, day: 50) let sept50Date = userCalendar.date(from: sept50DateComponents)! print("September 50, 2020 is actually \(sept50Date.description(with: Locale(identifier: "en-US"))).") // Date of the first land line phone call (March 10, 1876) // ------------------------------------------------------- // We want to extract the year, month, and day let alexanderGrahamBellDateComponents = userCalendar.dateComponents([.year, .month, .day], from: firstLandLineCallDate) print("The first land line phone call happened \(-firstLandLineCallDate.timeIntervalSinceNow) seconds ago.") print("Year: \(alexanderGrahamBellDateComponents.year!)") print("Month: \(alexanderGrahamBellDateComponents.month!)") print("Day: \(alexanderGrahamBellDateComponents.day!)") // The original iPhone Stevenote (10 a.m. Pacific time, // January 9, 2007) // ---------------------------------------------------- // We want to extract the year, month, day, hour, and minute from this date, // in local time for the event (which took place in San Francisco). // We also want to know what day of the week and week of the year // this date fell on. // Create a calendar set to Pacific standard time (UTC-8) var pacificCalendar = Calendar(identifier: .gregorian) pacificCalendar.timeZone = TimeZone(abbreviation: "PST")! let iPhoneStevenoteDateComponents = pacificCalendar.dateComponents([.year, .month, .day, .hour, .minute, .weekday, .weekOfYear], from: iPhoneStevenoteDate) print("The original iPhone Stevenote happened \(-iPhoneStevenoteDate.timeIntervalSinceNow) seconds ago.") print("Year: \(iPhoneStevenoteDateComponents.year!)") print("Month: \(iPhoneStevenoteDateComponents.month!)") print("Day: \(iPhoneStevenoteDateComponents.day!)") print("Hour: \(iPhoneStevenoteDateComponents.hour!)") print("Minute: \(iPhoneStevenoteDateComponents.minute!)") print("Weekday: \(iPhoneStevenoteDateComponents.weekday!)") print("Week of year: \(iPhoneStevenoteDateComponents.weekOfYear!)") // The original iPad Stevenote (10 a.m. Pacific time, // January 27, 2010) // ---------------------------------------------------- // We want to extract ALL the DateComponents for this date // in local time for the event (which took place in San Francisco). let iPadStevenoteDateComponents = pacificCalendar.dateComponents([.calendar, .day, .era, .hour, .minute, .month, .nanosecond, .quarter, .second, .timeZone, .weekday, .weekdayOrdinal, .weekOfMonth, .weekOfYear, .year, .yearForWeekOfYear], from: iPadStevenoteDate) print("The original iPad Stevenote happened \(-iPadStevenoteDate.timeIntervalSinceNow) seconds ago.") print("Calendar: \(iPadStevenoteDateComponents.calendar!.identifier)") print("Day: \(iPadStevenoteDateComponents.day!)") print("Era: \(iPadStevenoteDateComponents.era!)") print("Hour: \(iPadStevenoteDateComponents.hour!)") print("Minute: \(iPadStevenoteDateComponents.minute!)") print("Month: \(iPadStevenoteDateComponents.month!)") print("Nanosecond: \(iPadStevenoteDateComponents.nanosecond!)") print("Quarter: \(iPadStevenoteDateComponents.quarter!)") print("Second: \(iPadStevenoteDateComponents.second!)") print("Time zone: \(iPadStevenoteDateComponents.timeZone!)") print("Weekday: \(iPadStevenoteDateComponents.weekday!)") print("Weekday ordinal: \(iPadStevenoteDateComponents.weekdayOrdinal!)") print("Week of month: \(iPadStevenoteDateComponents.weekOfMonth!)") print("Week of year: \(iPadStevenoteDateComponents.weekOfYear!)") print("Year: \(iPadStevenoteDateComponents.year!)") print("Year for week of year: \(iPadStevenoteDateComponents.yearForWeekOfYear!)")
You can download the playground here (14KB, zipped Xcode playground file).
In the next installment in the How to work with dates and times in Swift 5 series, we’ll look at converting Date
s to String
s, and vice versa.
The Dates and times in Swift 5 series
Screenshot of the top my Stack Overflow story, as of May 24, 2020.
Tap the image to see the original.
In addition to updating my LinkedIn profile, I’ve also been updating my Stack Overflow developer story. I’m rather fond of the timeline that its Story View provides, and how it lets you highlight more than just positions, but applications you’ve released, your articles or videos, awards, certifications, and assessments, and other milestones:
Screenshot of my Stack Overflow story timeline, as of May 24, 2020.
Tap the image to see the full timeline.
As nice as its format is, I wonder if maintaining it is worth the effort. Does anybody else keep their Stack Overflow developer story up to date? Do people who are hiring look at them in the same way they look at LinkedIn profiles?
Greetings, Tampa Bay techies, entrepreneurs, and nerds! Welcome to week 9 of the Florida general stay-at-home order! I hope you’re managing and even thriving. There’s at least one online tech, entrepreneur, or nerd event each day this week. Keep an eye on this post; I update it when I hear about new events, it’s always changing. Stay safe, stay connected, and #MakeItTampaBay!
Monday, May 25
- Computer Coach Training Center — Monday Morning Coffee Talk @ 9:00 AM to 10:00 AM
- OK! TRANSMIT Art + Technology Meetups — Art+Tech Meetup No.18: OUR FIRST EVER VIRTUAL MEETUP @ 6:00 PM to 8:00 PM
- Thinkful Webinar | Learn UX/UI Design With Thinkful @ 9:00 PM to 11:00 PM
Tuesday, May 26
- Tampa Bay Agile — v-Lean Coffee @ 7:30 AM to 8:30 AM
- Clearwater Renaissance Speakers Toastmasters @ 12:00 PM to 1:00 PM
- Keystone Mastermind Alliance – KMA Network — ZOOM at NOON – Virtual Meeting @ 12:00 PM to 1:15 PM
- Tampa Bay Tech Career Advice Forum — LinkedIn for Job Seekers @ 3:00 PM to 4:30 PM
- Tampa Bay DevOps Meetup — TB not so DevOps meeting: Networking 101 Brand Development & Networking Strategy @ 5:00 PM to 7:00 PM
- Suncoast Developers Guild — Figma Tampa Meetup at SDG @ 6:00 PM to 8:00 PM
- Tampa HashiCorp User Group — Terraform Teaming at Scale @ 6:00 PM to 7:30 PM
- Tampa Bay Azure User Group — Infrastructure as Code at the World’s Largest Furniture Manufacturer @ 6:00 PM to 8:00 PM
- Tampa Hackerspace — Online Weekly Open Make Night @ 6:00 PM to 10:00 PM
- Tampa R Users Group — Chris Woodard presents via zoom: Writing Custom Geoms for ggplot2! @ 7:00 PM to 9:00 PM
Wednesday, May 27
- 1 Million Cups St. Pete @ 9:00 AM
- 1 Million Cups Tampa — Bridges / STEM Xposure @ 9:00 AM
- Cyber Security Summit – Power Hour – Get the Facts @ 10:30 AM to 12:00 PM
- Tampa Bay Agile — Practice Does Not Make Perfect: Why Agile Transformations Fail (Gil Broza) @ 12:00 PM to 1:00 PM
- Tech4Good Tampa — Webinar – Digital Accessibility: The What, Who, Why, When and How @ 2:00 PM to 3:00 PM
- ACES: Architects, Contractors, Engineers, & Site Developers — State of the Market @ 4:00 PM to 5:00 PM
- Tampa Bay Connections — Virtual Networking Mixer @ 5:00 PM to 7:00 PM
- Tampa Bay Tech Career Advice Forum — Hump Day Virtual Happy Hour @ 5:30 PM to 7:00 PM
- Tampa Tech and Beer — Data Science Development Series | Session 1: Machine Learning 101 @ 5:30 PM to 7:00 PM
- PLAYlive Nation Tyrone — Wednesday Night D&D Adventurers League @ 6:00 PM to 9:00 PM
- cYbor Security Meetup — Make Your Own Raspberry Pi case in Fusion 360 @ 6:00 PM to 8:00 PM
- ReactJS Tampa Bay — Lab: Deploying a virtual dev environment with AWS LightSail @ 6:30 PM to 8:00 PM
- Carrollwood Toastmasters Meetings now conducted Online using Zoom @ 7:00 PM to 8:30 PM
- Thinkful Webinar | Intro to Data Science: The Art of Visualizations — 8:00 PM to 10:00 PM
Thursday, May 28
- Bootstrappers Breakfast® – Tampa Bay Area — Bootstrappers Breakfast with Rob Fitzpatrick of “The Mom Test” @ 8:30 AM to 10:00 AM
- Tampa Bay WaVE — Wave Webinar: Building Employee Community and Engagement Through Wellness @ 10:00 AM to 11:00 AM
- Blacks in Technology – Central Florida Chapter — Introduction to BIT Central FL @ 12:00 PM to 1:00 PM
- Tampa Bay AWS User Group — Modernizing Apps with Serverless on AWS @ 12:00 PM to 1:00 PM
- Microsoft Tech Talks – Florida — [Remote] Microsoft Tech Talks – Process Power (with PowerAutomate) @ 1:00 PM to 2:30 PM
- Tampa Bay RPA — [Live Webinar] Using RPA to Help the Healthcare Industry’s Financial Recovery @ 1:00 PM to 2:00 PM
- Tampa Bay Women in Agile — Coaching to Success @ 6:00 PM to 8:00 PM
- Network After Work Tampa – Networking Events — How to Elevate Your Online Brand @ 6:00 PM to 8:00 PM
- Tampa Hackerspace — ONLINE Five Weeks of Arduino Goodness (week 1) @ 7:00 PM to 9:00 PM
- Tampa-Orlando Software QA/DEV Meetup — Software Testing Meetup and Networking Session (ONLINE) @ 8:30 PM to 10:30 PM
Friday, May 29
- Tampa Bay Tech Career Advice Forum — Resumes that Get Noticed: A Deep Dive into What Works & What Recruiters Look For @ 11:00 AM to 12:30 PM
- Saint Petersburg FileMaker Developers Meetup — Virtual FileMaker Tools, Tips, and Tricks @ 3:00 PM to 4:30 PM
- Learn Cybersecurity Tampa — {Virtual} What’s at Risk? Cyber Risk Management, Speaker Series @ 8:00 PM to 9:30 PM
Saturday, May 30
- R-Ladies Tampa — PT 1: Exploratory Data Analysis @ 10:00 AM to 12:00 PM
- Hack The Box Meetup: Tampa, FL — Hack The Box Meetup: Tampa (Remote) @ 11:30 AM to 4:00 PM
- Tampa-Orlando Software QA/DEV Meetup — Quick start to build web applications with React(Free Online Class) @ 1:00 PM to 3:00 PM
Sunday, May 31
Do you have any events or announcements that you’d like to see on this list?
Let me know at joey@joeydevilla.com!
Join the mailing list!
If you’d like to get this list in your email inbox every week, enter your email address below. You’ll only be emailed once a week, and the email will contain this list, plus links to any interesting news, upcoming events, and tech articles.
Join the Tampa Bay Tech Events list and always be informed of what’s coming up in Tampa Bay!
Programmer joke of the day
Don’t forget that there’s a really, really, really good deal on Python books for the next few days!
Thanks to Ryan Rossman for the find!
If you’ve been looking to set yourself apart by learning native mobile development — iOS development with Swift, Android development with Kotlin, or cross-platform development with Flutter — take advantage of RayWenderlich.com’s Learn at Home Sale and get the best mobile development books on the market for half price!
Let me tell you about some of the books…
iOS Apprentice, 8th Edition — co-authored by Yours Truly!
This book is a very special one for me, because I learned iOS development from an earlier edition. I put my heart and soul — and a lot of hours — into this book, which teaches you how to write iOS apps by writing iOS apps. Whether you’re completely new to programming or have experience with other programming languages (remember, I learned from this book, and I have a computer science degree), this book is an excellent starting point for writing apps for the iPhone and iPad!
It normally sells for $59.99, but for a limited time, it’s on sale at $29.99. Get it now!
Want a free downloadable sample from the book? Get it here.
Android Apprentice, 3rd edition
Want to learn Android development in Kotlin? This is the book for you. Like iOS Apprentice, this book teaches you how to make apps by having you make apps. You’ll build 4 apps, starting with a simple game to get you warmed up, and then you’ll go on to make a checklist app, a map-based app, and a podcast manager and player.
It normally sells for $59.99, but for a limited time, it’s on sale at $29.99. Get it now!
Want a free downloadable sample from the book? Get it here.
So many books and bundles!
Right now, all the books are on sale for half price at RayWenderlich.com. You can save even more by buying bundles! Check them out, get the books you need, and start upskilling!