Working with dates in Swift

Sai Koneru
4 min readSep 5, 2021

--

Swift has powerful built-in functions which makes it easy to work with dates

Photo by Claudio Schwarz on Unsplash

Let’s start with the basics

Getting current date

let date = Date()

This gives the system date using the current user locale

Getting date components

To get different components from the date (i.e. day, month, year etc.) we can use dateComponents function from current Calendar instance

let components = Calendar.current.dateComponents(
[.day, .month, .year], from: date)

This gives the requested components in this case day, month, year from the given date. We can access them as below

let day = components.day
let month = components.month
let year = components.year

These are optionals so make sure to properly unwrap them before using

In addition to day, month & year there are several others components that can be obtained from a given date

Some of the most commonly used are

  • .timezone to get Timezone information
  • .hour, .minute, .second to get time information
  • .weekday to get the number indicating the current day of the week
  • .weekOfYear to get week number in the year

We can also use component(_:from:) function to get a single component from the given date

Creating date from Date Components

You can also create a new date from Date Components

var components = DateComponents()
components.timeZone = TimeZone(abbreviation: “GMT”)
components.day = 2
components.month = 8
components.year = 2021
let date = Calendar.current.date(from: components)

Calendar.current.date(from:) returns an optional

You can also create components using DateComponents constructor. But I prefer the above approach 😬

let components = DateComponents(
timeZone: TimeZone(abbreviation: “GMT”),
year: 2021,
month: 8,
day: 2)

Comparing & advancing dates

You can compare the dates using the comparison operators (<, >, ≤, ≥, ==, !=)

To advance the date by a specific interval we can use either addTimeInterval or addingTimeInterval instance methods on date object. While the former changes the date in place, the later gives a new date object.

We need to pass no. of seconds to advance as the parameter to both these functions.

// Changing date in-place
var date = Date()
// advancing by one day
date.addTimeInterval(86400)
// Creating new date
var date = Date()
let newDate = date.addingTimeInterval(-86400)

If we pass negative number as parameter then the date goes backwards. There is also one more method advanced(by:) which is same as addTimeInterval

Difference between two dates

Most often we want to know difference between two given dates. Swift has an instance method called distance(to:) just for this purpose. This method gives the difference in number of seconds

let today = Date()let date = Calendar.current.date(
from: DateComponents(timeZone: TimeZone(abbreviation: “GMT”),
year: 2021, month: 8, day: 2))!
date.distance(to: today)

This will give the no. of seconds as output. We can divide it by 86400 i.e. no. of seconds in a day to get the difference in days

Getting next / previous dates

We can find the next or previous date matching a certain criteria using Calendar’s nextDate function. It return an optional Date

nextDate(after:, matching:, matchingPolicy:, repeatedTimePolicy:, direction:) -> Date?

Let’s explore in detail how this function works

after starting date from which the next / previous date need to be calculated

matching → date components used to search

matchingPolicymatching technique used by the search algorithm, it is defaulted to .nextTime

repeatedTimePolicywhen multiple dates are found by search algorithm this attribute specify which date to return, it is defaulted to .first

directionindicate whether to search forward or backward from the given date, it is defaulted to .forward

It might be daunting to look, but it’s easy to understand in code. Let’s see it in action.

Finding next date

The following example finds the next date matching the day component of the given date. For example if today date is September 5th 2021 then nextDate will give us October 5th 2021 as the result when matching day component

let today = Date()let components = Calendar.current.dateComponents([.day],
from: today)
let nextDate = Calendar.current.nextDate(
after: today,
matching: components,
matchingPolicy: .nextTime,
repeatedTimePolicy: .first,
direction: .forward)

Finding previous date

If we want to go back from the given date we just need to specify the direction parameter as .backward.

let lastDate = Calendar.current.nextDate(
after: today,
matching: components,
matchingPolicy: .nextTime,
repeatedTimePolicy: .first,
direction: .backward)

Finding list of matching dates

As we have seen in the previous example we can find next or previous date using nextDate function. But what if we want to find let’s say next 10 dates that match the criteria. How about looping through nextDate function 10 times?

Swift has a much cleaner way to achieve this. We can use enumerateDates Calendar function

It is similar to nextDate function except it takes an additional parameter a closure.

Let’s see it in action

let today = Date()let components = Calendar.current.dateComponents(
[.day], from: today)
var count = 0Calendar.current.enumerateDates(
startingAfter: today,
matching: components,
matchingPolicy: .nextTime,
repeatedTimePolicy: .first,
direction: .forward) { (date, strict, stop) in
count += 1 print(date) if count == 10 {
stop = true
}
}

The trailing closure has 3 parameters

The 1st parameter is the date that matched the criteria. It is an optional.

The 2nd parameter is the matching policy

The 3rd parameter is an inout Bool. If we want to stop the search we need to set its value to true inside the closure. Failing to set it may result in an infinite loop.

Conclusion

Swift’s Calendar and Date structs have many functions and properties that you can use to make your life easy when working with dates

Pro Tip: When you are comparing two dates make sure they are in the same timezone :)

--

--

Sai Koneru
Sai Koneru

Written by Sai Koneru

An avid reader 📚, programmer 👨🏻‍💻 currently living & working in Netherlands. I ❤️ reading books, writing / tinkering with code in my free time.

No responses yet