Tips: Time Zones and Date Components

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, DateFormatters 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

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.