Make App Pie

Training for Developers and Artists

Using Date, TimeInterval, and DateComponents in Swift 3

Working with dates in iOS10 can be a bit confusing. There are several different types associated with dates. You can use them for telling time, scheduling time and setting the differences between two times. In this lesson, let’s look at the different types of dates. I’ll use a playground to do this. You can download here the full lesson as a zip file if you wish, or just type along. The file has the entire lesson, so if you load it on iPad Playgrounds, it will format like this post.

The Basic Date

The simplest date representation is from the type Date. For the current date, instantiate a variable with the constructor like this:

var date = Date()
print(date)

Prints 2016-11-10 11:58:36 +0000 to the console.

Time Intervals

On the other hand, you might want a measure of time. For this, use the type TimeInterval. This is  a measure  of time using seconds. They are of Double type. I’ll set a few constants using time intervals for day, hour and minute.

let minute:TimeInterval = 60.0
let hour:TimeInterval = 60.0 * minute
let day:TimeInterval = 24 * hour

You can set a date based on the time interval. If you want a time interval different from now, use the constructor Date(timeIntervalSinceNow:)

date = Date(timeIntervalSinceNow: minute)
print(date)

Gives you a date one minute from now 2016-11-10 11:59:36 +0000. If you want a date where you add or subtract a time interval, use Date(timeInterval:since:)

date = Date(timeInterval: hour, since: date)
print(date)

Gives us a date an hour from now: 2016-11-10 12:59:36 +0000.

Date Formatters

The date looks ugly. Let’s make the date look better with a date formatter. Start with initializing a date formatter

let dateFormatter = DateFormatter()

Date formatters need you to set a style for the date using the dateStyle property and time property timeStyle. You have a choice of .full .long, .medium, .short, and .none

dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .short

There’s a function on date formatters, string(from:) that returns a string with the formatted date.

print(dateFormatter.string(from: date))

Prints Nov 10, 2016, 6:59 AM. Change the styles to .full

dateFormatter.dateStyle = .full
dateFormatter.timeStyle = .full
print(dateFormatter.string(from: date))

You’ll get a full date like Thursday, November 10, 2016 at 6:59:36 AM Central Standard Time. Change the styles to .short

dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
print(dateFormatter.string(from: date))

You’ll find printed something like 11/10/16, 7:20 AMon the console. If you want only a date or a time, use .none

dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .medium
print(dateFormatter.string(from: date))

Prints just the time 7:20:53 AM
Date formatters are locale dependent. They use the current locale by default. You can change the locale and use that locale’s format. For example If I want the time for some where with really authentic pizza,

dateFormatter.dateStyle = .medium
dateFormatter.locale = Locale(identifier: "it-it")
print (dateFormatter.string(from: date))

Prints to the console the Italian date format 10 nov 2016, 06:59:36

Date Components

This is good for relative dates from a time frame. What if you want an absolute date? That’s where DateComponents comes into play. A date component provides a way to add components for a date. Initialize DateComponents like this:

var dateComponents = DateComponents()

You assign to date componenets the date

dateComponents.year = 2016
dateComponents.month = 11
dateComponents.day = 04
dateComponents.hour = 13
dateComponents.minute = 8
dateComponents.second = 0

Date components are optional values. When a value is not set it returns nil. If you have a nil value for one component, operations on the dateComponents object will cause an nil error. There is a property isValidDate to confirm if you have all the information.

print(dateComponents.isValidDate)

Prints false. You don’t have enough components yet. Include the calendar used in a date componenets object. Usually this is the current calendar for the system. A calendar fills in the rest of the information the date componenets needs to make a valid date. You can get the current calendar using Calendar.current

dateComponents.calendar = Calendar.current
print(dateComponents.isValidDate)

The console prints true. The date components have a property date if you need a value of type Date. Of course you can format this way, changing the components back into dates.

date = dateComponents.date!
print(dateFormatter.string(from: date))

Prints 04 nov 2016, 13:08:00
You can also convert a date to date components. However, you do it from the current calendar, not the Date type. Make a set of Calendar components. For most cases, include the component .calendar to avoid a nil in the components.

let unitFlags:Set<Calendar.Components> = [
    .hour, .day, .month,
    .year,.minute,.hour,.second,
    .calendar]

Using the current calendar, get the components

dateComponents = Calendar.current.dateComponents(unitFlags, from: Date())

Print the date using the date formatter.

date = dateComponents.date!
print(dateFormatter.string(from: date))

Prints the date 10 nov 2016, 06:19:53.
Date components can be changed. The date components are all optional type Int. While it is easier to change them using Date and TimeInterval, you might need to do it this way if you’ve created a series of controls in your UI to set a date. For example, to add five days do this:

dateComponents.day = dateComponents.day! + 5
date = dateComponents.date!
print(dateFormatter.string(from: date))

The console prints 15 nov 2016, 06:19:53.
Each of these types have their purposes. Date is the simplest and best for the current date and dates based on the current date. To show an interval in seconds, use the TimeInterval. To work with indivdual date components, use DateComponents. You’ll find each of these in other API’s as well. For example, all three have purposes in the UserNotification framework as event triggers. Learing how to use all three will help you display time and schedule time throughout iOS.

 

The Whole code

You can download here the full lesson as a zip file.

//: Working with dates in iOS10 can be a bit confusing. There are several different types associated with dates. You can use them for telling time, scheduling time and setting the differences between two times. In this lesson, let's look at the different types of dates

import UIKit

//: #The basic date
//: The simplest date representation is from the type 'Date'. For the current date, instantiate a veriable with the constructor like this:

var date = Date()
print(date)

//: ##Time Intervals
//: On the other hand, you might want a measure of time. For this, use the type 'TimeInterval' This is measures of time using seconds. They are of 'Double' type. I'll set a few constants using time intervals.
let minute:TimeInterval = 60.0
let hour:TimeInterval = 60.0 * minute
let day:TimeInterval = 24 * hour

//:You can set a date based on the time interval. If you want a time interval different from now use the  constructor 'Date(timeIntervalSinceNow:)'
date = Date(timeIntervalSinceNow: minute)
print(date)
//: Gives you a date one minute from now. If you want a date where you add or subtract a time interval, use 'Date(timeInterval:since:)'
date = Date(timeInterval: hour, since: date)
print(date)
//: Gives us a date an hour from the previous date.

//: #Date Formatters
//: The date looks ugly. Let's make the date look better with a *date formatter*.  Start with initializing a date formatter
let dateFormatter = DateFormatter()

//: Date formatters require you to set a style for the date using the 'dateStyle' property and time property 'timeStyle'. You have a choice of '.full' '.long', '.medium', '.short', and '.none'
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .short
//:  There's a function on date formatters, 'string(from:)' that return a string with the formatted date.
print(dateFormatter.string(from: date))

//: By changing the styles from '.full'
dateFormatter.dateStyle = .full
dateFormatter.timeStyle = .full
print(dateFormatter.string(from: date))

//:to '.short'

dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
print(dateFormatter.string(from: date))

//:Provides for different formats. If you want only a date or a time, use '.none'
dateFormatter.dateStyle = .none
dateFormatter.timeStyle = .medium
print(dateFormatter.string(from: date))

//: Date formatters are locale dependent. They uses the current locale by default. You can change the locale and use that locale's format.
dateFormatter.dateStyle = .medium
dateFormatter.locale = Locale(identifier: "it-it")
print (dateFormatter.string(from: date))
//: #Date Componenets
//: This is all good for relative dates from a time frame. What if you want an absolute date? that's where 'DateComponents' comes into play. A date component provides a way to add componenets for a date. Initialize 'DateComponents' like this:

var dateComponents = DateComponents()
//: You assign to date componenets the date
dateComponents.year = 2016
dateComponents.month = 11
dateComponents.day = 04
dateComponents.hour = 13
dateComponents.minute = 8
dateComponents.second = 0

//: The date components are optional values. When a value is not set it returns 'nil'. If you have a nil value for one componenet, operations on the 'dateComponents' object will cause an nil error.  There is a property 'isValidDate' to confirm if you have all of the information.
print(dateComponents.isValidDate)
//: Include the calendar used in a date componenets object. Usually this is the current calendar for the system. A calendar fills in the rest of the information the date componenets needs to make a valid date. You can get the current calendar using 'Calendar.current'
dateComponents.calendar = Calendar.current
print(dateComponents.isValidDate)

//: The date components have a property 'date', if you need a value of type Date. Of course you can format this way, changing the components back into dates.
date = dateComponents.date!
print(dateFormatter.string(from: date))

//: You can also convert a date to date components. However you do it from the current calendar, not the 'Date' type. Make a set of Calendar components. For most cases include the component .calendar to avoid a nil in the components.
let unitFlags:Set<Calendar.Component> = [.hour, .day, .month, .year,.minute,.hour,.second, .calendar]

//: Using the current calendar, get the components
dateComponents = Calendar.current.dateComponents(unitFlags, from: Date())
//: Print the date using the date formatter.
date = dateComponents.date!
print(dateFormatter.string(from: date))

//: Date components can be changed. The date componenets are all of type 'Int!'. While it is easier to change them using 'Date' and 'TimeInterval', you might need to to do it this way. For example, to add five days.
dateComponents.day = dateComponents.day! + 5
date = dateComponents.date!
print(dateFormatter.string(from: date))

//:Each of these types have their purposes. 'Date'  is the simplest and best for the current date and dates based on the current date. To indicate an interval in seconds, use the 'TimeInterval'. To work with indivdual date components, use 'DateComponents'. You'll find each of these in other API's as well. For example, all three have purposes in the UserNotification framework as event triggers. Learing how to use all three will help you display time and schedule time throughout iOS.

5 responses to “Using Date, TimeInterval, and DateComponents in Swift 3”

  1. […] did get a post done before all this. You can find a link to my post on the time and date object in Swift 3 in the show notes. I’ll cover Date, TimeInterval, DateFormatter and […]

  2. At this step, there is a small problem :
    “let unitFlags:Set = [
    .hour, .day, .month,
    .year,.minute,.hour,.second,
    .calendar]

    1. Sometimes I really hate Worpress’ editor. It doesn’t completely understand code tags, so it deleted the important part. Set should have after it a < then the type Calendar.Component then a > It should look like the same as the line in the whole code or downloads.
      let unitFlags:Set <Calendar.Components> = [.hour, .day, .month, .year,.minute,.hour,.second, .calendar]

  3. I am creating a timer, so how do I add like 52 minutes to a Date?

    1. Everything, well NSTimeInterval, is in seconds. If you are wanting to fire the timer in 52 minutes, add 52 minutes of seconds (52 * 60 = 3120 seconds) to a date is one way. Counting by seconds to 3120 is another, invalidating the timer at 3120 seconds counted, if you want to repeat through the timer every second.

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 )

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.

%d bloggers like this: