**Update, August 26, 2015:** I’ve updated this article so that its code works with Swift 2. It compiles under the latest version of Xcode 7, beta 6.

In the previous installment in this series that looks at working with dates and times in Cocoa, we looked at:

- The
**NSDate**class, which is the heart of date and time in Cocoa, and represents a single point in time relative to the start of the third millennium (midnight, January 1, 2001) - the
**NSCalendar**class, which provides a context for dates and the ability to do date arithmetic, - the
**NSDateComponents**class, which represents the parts that make up either a date or a span of time, and - the
**NSDateFormatter**class, which turns dates into string representations and vice versa.

We also covered creating dates, converting components into dates and vice versa, and converting dates into strings and vice versa. With this knowledge under our belts, let’s get to this article’s topic: doing date calculations.

### Creating a couple of dates to work with

Start with a fresh playground, and enter or paste the following code so it looks like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Playground - noun: a place where people can play import UIKit let userCalendar = NSCalendar.currentCalendar() // Let's create an NSDate for Valentine's Day // using NSDateComponents let valentinesDayComponents = NSDateComponents() valentinesDayComponents.year = 2015 valentinesDayComponents.month = 2 valentinesDayComponents.day = 14 let valentinesDay = userCalendar.dateFromComponents(valentinesDayComponents)! // Let's create an NSDate for St. Patrick's Day // using NSDateFormatter let dateMakerFormatter = NSDateFormatter() dateMakerFormatter.calendar = userCalendar dateMakerFormatter.dateFormat = "yyyy/MM/dd" let stPatricksDay = dateMakerFormatter.dateFromString("2015/03/17")! |

In the code above, we’re creating two dates in two different ways (which we covered in the previous article):

- We’re creating Valentine’s Day (February 14 for those of you in places where it’s not celebrated) by setting up date components and then using the user’s calendar to convert the components into a date.
- We’re creating St. Patrick’s Day (March 17 for those of you in places where it’s not celebrated) by converting a string representing that date into a date by means of a date formatter. You may find that if you need to instantiate a large number of dates in code, you may want to do so this way, as you can do it in far fewer lines than by using date components.

Now that we have a couple of date objects, let’s do some date arithmetic!

### Which came first?

`NSDate`

has two methods, `earlierDate`

and `laterDate`

, which compare one date to another and return the appropriate date. Add the highlighted code below so that your playground looks like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// Playground - noun: a place where people can play import UIKit let userCalendar = NSCalendar.currentCalendar() // Let's create an NSDate for Valentine's Day // using NSDateComponents let valentinesDayComponents = NSDateComponents() valentinesDayComponents.year = 2015 valentinesDayComponents.month = 2 valentinesDayComponents.day = 14 let valentinesDay = userCalendar.dateFromComponents(valentinesDayComponents)! // Let's create an NSDate for St. Patrick's Day // using NSDateFormatter let dateMakerFormatter = NSDateFormatter() dateMakerFormatter.calendar = userCalendar dateMakerFormatter.dateFormat = "yyyy/MM/dd" let stPatricksDay = dateMakerFormatter.dateFromString("2015/03/17")! // Which date comes first? Which comes last? valentinesDay.earlierDate(stPatricksDay) valentinesDay.laterDate(stPatricksDay) |

This is pretty straightforward: `valentinesDay.earlierDate(stPatricksDay)`

returns the `valentinesDay`

instance, while `valentinesDay.laterDate(stPatricksDay)`

returns `stPatricksDay`

.

`NSDate`

has a `compare`

method that works in a way similar to a lot of other “compare” methods (such as C’s `strcmp`

) that compare a value *a* and *b*, where:

- If
*a*<*b*, it returns a negative number - if
*a*==*b*, it returns 0 - if
*a*>*b*, it returns a positive number

Cocoa comparison methods return values of type `NSComparisonResult`

, so that when you’re comparing two values *a* and *b*:

- If
*a*<*b*, it returns`NSOrderedAscending`

- if
*a*==*b*, it returns`NSOrderedSame`

- if
*a*>*b*, it returns`NSOrderedDescending`

Let’s take it out for a spin. Add the highlighted code below so that your playground looks like this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// Playground - noun: a place where people can play import UIKit let userCalendar = NSCalendar.currentCalendar() // Let's create an NSDate for Valentine's Day // using NSDateComponents let valentinesDayComponents = NSDateComponents() valentinesDayComponents.year = 2015 valentinesDayComponents.month = 2 valentinesDayComponents.day = 14 let valentinesDay = userCalendar.dateFromComponents(valentinesDayComponents)! // Let's create an NSDate for St. Patrick's Day // using NSDateFormatter let dateMakerFormatter = NSDateFormatter() dateMakerFormatter.calendar = userCalendar dateMakerFormatter.dateFormat = "yyyy/MM/dd" let stPatricksDay = dateMakerFormatter.dateFromString("2015/03/17")! // Which date comes first? Which comes last? valentinesDay.earlierDate(stPatricksDay) valentinesDay.laterDate(stPatricksDay) // Another way to compare dates let dayOrder = valentinesDay.compare(stPatricksDay) if dayOrder == .OrderedAscending { print("Valentine's Day comes before St. Patrick's Day.") } else if dayOrder == .OrderedDescending { print("Valentine's Day comes after St. Patrick's Day.") } else if dayOrder == .OrderedSame { print("They're the same day!") } else { print("Something weird happened.") } |

Valentine’s Day comes before St. Patrick’s Day, so the result you see the in sidebar should be *Valentine’s Day comes before St. Patrick’s Day.*

### Date arithmetic: How far apart are two dates and times?

`NSDate`

has the `timeIntervalSinceDate`

method, which gives you the difference between 2 dates…in seconds.

1 2 3 4 5 |
// (Previous code goes here) // Not all that useful valentinesDay.timeIntervalSinceDate(stPatricksDay) stPatricksDay.timeIntervalSinceDate(valentinesDay) |

Since Valentine’s Day comes before St. Patrick’s Day, the first value is negative, while the second value is positive. Most users won’t find knowing that there are nearly 2.7 million seconds between the two days. How can we find out the number of *days* between Valentine’s and St. Patrick’s?

That’s where date components come in. I mentioned last time that date components can represent either:

- A specific point in time, or
- a duration of time.

We’re going to use date components for the second purpose in this example. We need to do the following:

- Specify the units of time that we want from the calculation, which in this case is days, and
- Provide those units of time and the two dates to
`NSCalendar`

‘s`components`

method:

1 2 3 4 5 6 7 8 9 10 11 |
// (Previous code goes here) // How many days between Valentine's Day and St. Patrick's Day? let dayCalendarUnit: NSCalendarUnit = [.Day] let stPatricksValentinesDayDifference = userCalendar.components( dayCalendarUnit, fromDate: valentinesDay, toDate: stPatricksDay, options: []) // The result should be 31 stPatricksValentinesDayDifference.day |

This version of `NSCalendar`

‘s `components`

method takes the following arguments:

`unitFlags`

: An option set of components we want to retrieve. Since we want to know the number of days between Valentine’s and St. Patrick’s, there’s only one option in the set:`.Day`

.`fromDate`

: The start date in the calculation.`toDate`

: The end date in the calculation.`options`

: In most cases, you’ll want this set to`[]`

, which means no options. This causes overflows in a unit to carry to the next higher unit. For example, if you specify in`unitFlags`

that you want your result expressed in minutes and seconds, and the calculation’s result is 61 seconds, the result will be changed to 1 minute, 1 second.

Let’s try another calculation: what’s the time difference between 10:45 a.m. and 12:00 noon?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// (Previous code goes here) // How many hours and minutes between 10:45 a.m. and 12:00 noon? dateMakerFormatter.dateFormat = "yyyy/MM/dd hh:mm a Z" let startTime = dateMakerFormatter.dateFromString("2015/01/27 10:45 AM -05:00")! let endTime = dateMakerFormatter.dateFromString("2015/01/27 12:00 PM -05:00")! let hourMinuteComponents: NSCalendarUnit = [.Hour, .Minute] let timeDifference = userCalendar.components( hourMinuteComponents, fromDate: startTime, toDate: endTime, options: []) timeDifference.hour timeDifference.minute |

You should see in the sidebar that `timeDifference.hour`

‘s value is **1** and `timeDifference.minute`

‘s value is **15**.

### Date addition and subtraction

If you’re writing some kind of reminder app, you might want to be able to let the user say “give me a reminder in 10 days”, which means you’ll need to calculate what the date and time will be 10 days from now. Since we’re doing date addition with only one unit, we can perform this calculation by using `NSCalendar`

‘s `dateByAddingUnit`

method:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// (Previous code goes here) // What will the date and time be be ten days from now? let tenDaysFromNow = userCalendar.dateByAddingUnit( [.Day], value: 10, toDate: NSDate(), options: [])! // What weekday (Sunday through Saturday) will it be ten days from now, and // which weekday of the month will it be -- the 1st, 2nd, 3rd...? let weekdayAndWeekdayOrdinal: NSCalendarUnit = [.Weekday, .WeekdayOrdinal] let tenDaysFromNowComponents = userCalendar.components( weekdayAndWeekdayOrdinal, fromDate: tenDaysFromNow) tenDaysFromNowComponents.weekday tenDaysFromNowComponents.weekdayOrdinal |

`dateByAddingUnit`

expects the following parameters:

`unit`

: The type of unit to be added to the date. We want to add days, so we’re setting this value to`[.Day]`

.`value`

: The number of`unit`

s to be added to the date. We want to know what the date will be 10 days from now, so we set this to*10*.`toDate`

: The date to which we’ll be adding units. We want to add 10 days to today, so we set this to a new`NSDate`

(remember, instantiating an`NSDate`

object without parameters creates an instance that refers to the current date and time).`options`

: In most cases, you’ll want to set this to`[]`

.

I ran the code on January 28, 2015 at 11:29 p.m., so the resulting date stored in `tenDaysFromNow`

is displayed in my playground’s sidebar as *Feb 7, 2015, 11:29 PM*.

I wanted to know what day of the week it would be 10 days from now, and which weekday of the month (the first, second, third…?) so I used the version of `NSCalendar`

‘s components method that takes a single date and use it to extract the `weekday`

and `weekdayOrdinal`

components from `tenDaysFromNow`

. At the time I ran the code, `tenDaysFromNowComponents.weekday`

‘s value was *7* (Saturday) and `tenDaysFromNowComponents.weekdayOrdinal`

‘s value was *1* (meaning that it’s the first Saturday of the month).

Here’s another calculation: what was the date and time 3 days, 10 hours, 42 minutes, and 5 seconds ago? We’re doing date arithmetic with more than one kind of unit — days, hours, minutes, and seconds — so we need `NSCalendar`

‘s `dateByAddingComponents`

method instead:

1 2 3 4 5 6 7 8 9 10 11 12 |
// (Previous code goes here) // What was the date and time 3 days, 10 hours, 42 minutes, and 5 seconds ago? let periodComponents = NSDateComponents() periodComponents.day = -3 periodComponents.hour = -10 periodComponents.minute = -42 periodComponents.second = -5 let then = userCalendar.dateByAddingComponents( periodComponents, toDate: NSDate(), options: [])! |

`dateByAddingComponents`

expects the following parameters:

`comps`

: the date components that we want to add to the given date. Note that since we’re performing date subtraction, all the components are expressed as negative numbers.`toDate`

: The date from which we’ll be adding (or in this case, subtracting). We want to subtract from the current date and time, so we set this to a new`NSDate`

object instantiated without parameters (which, as I’ve said before, gives an instance representing the current date and time).`options`

: In most cases, you’ll want to set this to`[]`

.

I ran the code on January 28, 2015 at 11:52 p.m., so the resulting date stored in then is displayed in my playground’s sidebar as *Jan 25, 2015, 1:10 PM*.

### In closing

In this article, we covered:

- Comparing two dates to see which one is the earlier on and which is the later one,
- finding out how far apart two dates are, and
- adding and subtracting from dates.

In the next installment, we’ll a closer look at date calculations and see some convenience methods that make date and time calculations simpler.

## Related articles

**A very brief introduction to date formatting in Swift and iOS:** The oversight in a mostly-good book on Swift programming led me down the path of writing articles about dates and times in Swift, starting with this one, where I look at`NSDateFormatter`

.

**How to work with dates and times in Swift, part one:** An introduction of Cocoa’s date and time classes, and how they work together. This article covers UTC (Coordinated Universal Time), and the key classes: `NSDate`

, `NSCalendar`

, `NSDateComponents`

.

**How to work with dates and times in Swift, part three: Making date arithmetic more Swift-like:** Cocoa’s date and time classes have an Objective-C heritage, which in the Swift context, feel kind of clunky. In this article, I look at ways — and by ways, I mean helper functions and class extensions — to make date calculations feel more like Swift.

**How to work with dates and times in Swift, part four: A more Swift-like way to get the time interval between two dates:** This quick article shows you how to make an operator overload that makes getting the time interval between two dates more like subtraction.

{ 1 comment… read it below or add one }

Awesome article! Thanks so much for this.

I’ve managed to convert my date strings into the date conventions of “Just now”, “x minutes ago”, “x hours ago” etc. I’ve been struggling with it for a couple of days…20 minutes reading this article and I’ve nailed it!

Thanks.

{ 4 trackbacks }