When you take on a goal as ambitious as the Great Renaming it is a challenge to ensure that all of the reference documentation is updated. As of September 20, 2016, for example, the DateFormatter documentation contains inconsistencies and references to Swift 2.3-style APIs. As time passes this will undoubtedly be corrected, but in the meantime here are a few examples for formatting dates with the Date
and DateFormatter
.
The current example in the above-reference documentation is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
let dateFormatter = DateFormatter() dateFormatter.dateStyle = .mediumStyle dateFormatter.timeStyle = .noStyle let date = Date(timeIntervalSinceReferenceDate: 118800) // US English Locale (en_US) dateFormatter.locale = Locale(localeIdentifier: "en_US") NSLog("%@", dateFormatter.stringFromDate(date)) // Jan 2, 2001 // French Locale (fr_FR) dateFormatter.locale = Locale(localeIdentifier: "fr_FR") NSLog("%@", dateFormatter.stringFromDate(date)) // 2 janv. 2001 // Japanese Locale (ja_JP) dateFormatter.locale = Locale(localeIdentifier: "ja_JP") NSLog("%@", dateFormatter.stringFromDate(date)) // 2001/01/02 |
In Swift 3.0 this changes to:
1 2 3 |
let dateFormatter = DateFormatter() dateFormatter.dateStyle = .medium dateFormatter.timeStyle = .none |
Notice that .mediumStyle
is dropped in favor of .medium
. This is in line with simplified naming; we know that the type is of DateFormatter.Style
so there is no reason to repeat the word Style
. The same applies for .none
as opposed to .noStyle
.
Now, let’s look at the changes to setting the formatter’s locale:
1 2 3 4 5 6 7 8 9 10 11 |
// US English Locale (en_US) dateFormatter.locale = Locale(identifier: "en_US") print(dateFormatter.string(from:date)) // Jan 2, 2001 // French Locale (fr_FR) dateFormatter.locale = Locale(identifier: "fr_FR") print(dateFormatter.string(from:date)) // 2 janv. 2001 // Japanese Locale (ja_JP) dateFormatter.locale = Locale(identifier: "ja_JP") print(dateFormatter.string(from:date)) // 2001/01/02 |
Again, we see the simplification from Locale(localeIdentifier:)
to Locale(identifier:)
. Less typing and to the point. Likewise the stringFromDate
method of the DateFormatter
has been streamlined to string(from:)
, which if you use the entire signature is string(from:Date)
. See the pattern?
Moving on to creating a Date
from a String
representation, the Apple documentation has this example:
1 2 3 4 5 6 7 |
let RFC3339DateFormatter = DateFormatter() RFC3339DateFormatter.locale = Locale(localeIdentifier: "en_US_POSIX") RFC3339DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" RFC3339DateFormatter.timeZone = TimeZone(forSecondsFromGMT: 0) let string = "1996-12-19T16:39:57-08:00" let date = RFC3339DateFormatter.dateFromString(string) |
Applying the principle of reducing verbiage and unnecessary words we arrive at:
1 2 3 4 5 6 7 |
let RFC3339DateFormatter = DateFormatter() RFC3339DateFormatter.locale = Locale(identifier: "en_US_POSIX") RFC3339DateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" RFC3339DateFormatter.timeZone = TimeZone(secondsFromGMT: 0) let string = "1996-12-19T16:39:57-08:00" let date = RFC3339DateFormatter.date(from:string) |
The TimeZone
initializer drops an extraneous three characters (for
), and as expected the dateFromString
method becomes date(from:)
.
Rules of Thumb
It should be apparent that the general rule of thumb when transitioning from Swift 2 to Swift 3 is to remove superfluous words. If you were used to writing formatter.timeStyle = .fullStyle
before, get used to writing formatter.timeStyle = .full
. If you see someTypeFromAnotherType()
it’s likely been replaced with someType(from:AnotherType)
.
Speaking from experience, after working with Swift 3 for several months now, going back to Swift 2 feels overly verbose, and this is coming from someone who actually likes verbose languages. Once you get the hang of it you’ll be embracing Hemingway and eschewing Tolstoy.
Happy Swifting!