In a previous tip you learned about the Date
, DateFormatter
and TimeInterval
classes. However they don’t help with specific times or localization of time zones. That’s where the DateComponents
and TimeZone
classes comes into play. A date component provides a way to add components for a date. We’ll add a few functions to get a date.
Download and open the example playground. I set up a date and a date formatter. It probably runs by itself now, so set it to Manual Run and make the viewer pane a bit bigger
To change time zones, DateFormatter
s has a timeZone
property, which takes a TimeZone
object. The simplest TimeZone
object is the current
time zone, which gives you the time zone based on localization settings.
var timeZone = TimeZone.current
Playgrounds returns an identifier. Identifiers for a time zone takes the form of a country, In my case America and a large city, Chicago. Identifiers give a time zone based on a location. There’s a dictionary of identifiers in the system along with abbreviations for time zones. You can also set the timeZone
with an identifier. For example the identifier for Pacific Time in the U.S. Is :
timeZone = TimeZone(identifier: "America/Los Angeles")!
I added the exclamation point here as this is an optional value, returning nil
if that identifier is not found as it is here. Running this you’ll find the value is nil
. For cities with spaces in their names use an underscore
timeZone = TimeZone(identifier: "America/Los_Angeles")!
You can also use an abbreviation of the time zone such as:
timeZone = TimeZone(abbreviation: "PDT")!
Change your date formatter by assigning the time zone to the date formatter’s time zone property:
dateFormatter.timeZone = timeZone
You’ll see in the console we’ve changed the time zone of the date displayed. But what if I know a date and time, say June 4 2018 at 10:00 AM in Cupertino California, and want to know the time of this event in Chicago? The Date
object can’t do that easily, but DateComponents
can. You’ll need to instantiate a date component object, and they can be a bit of a pain. Try instantiating one with the DateComponents
Initializer:
var dateComponents = DateComponents(calendar: Calendar?, timeZone: TimeZone, era: Int?, year: Int?, month: Int?, day: Int?, hour: Int?, minute: Int?, second: Int?, nanosecond: Int?, weekday: Int?, weekdayOrdinal: Int?, quarter: Int?, weekOfMonth: Int?, weekOfYear: Int?, yearForWeekOfYear: Int?)
There’s 16 parameters in its initializers. Even though they are optional values, dateComponents
won’t work easily without filling them all out. Delete that mess.
So here’s a trick: get the current dateComponents
from the Calendar
object.
var dateComponents = Calendar.current.dateComponents(in: TimeZone.current, from: Date())
This takes a TimeZone
and a Date
. I took the current ones to start with. Now I can change the properties of dateComponents
to June 4 2018 at 10:00:00 PDT
dateComponents.timeZone = timeZone dateComponents.year = 2018 dateComponents.month = 6 dateComponents.day = 4 dateComponents.hour = 10 dateComponents.minute = 0 dateComponents.second = 0
To use the date formatter or any of the Date
object functions, I’ll get the date property from the date components
date = dateComponents.date!
Again, it’s optional, in case all the components are not filled out, so I need to unwrap it.
That give me my date in Cupertino. I’ll change my DateFormatter
to my current time zone, which is Chicago
dateFormatter.timeZone = TimeZone.current
Run this and the date is noon in Chicago. This is a simple demo of a very robust series of objects in Foundation. Between all your date options, you’ll find one that works for you.
The Whole Code
Here’s a listing of the code used above. You can also download the finished project on Github at http://bit.ly/TimeZoneEnd
//:# Time Zones and Date Components //: A playground to play with advanced date classes import UIKit //: A date and a date formatter for use with this lesson var date = Date() let dateFormatter = DateFormatter() dateFormatter.dateStyle = .medium dateFormatter.timeStyle = .full //: Type your code here var timeZone = TimeZone.current timeZone = TimeZone(identifier: "America/Los_Angeles")! timeZone = TimeZone(abbreviation: "PDT")! dateFormatter.timeZone = TimeZone.current var dateComponents = Calendar.current.dateComponents(in: timeZone, from: Date()) dateComponents.year = 2018 dateComponents.month = 6 dateComponents.day = 4 dateComponents.hour = 10 dateComponents.minute = 0 dateComponents.second = 0 date = dateComponents.date! //: This will print the date print(dateFormatter.string(from: date))
Leave a Reply