iOS Development
Time Calculation
Date Manipulation
Swift Programming
Mobile App Development

How to calculate time in hours between two dates in iOS

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In iOS, calculating the hours between two dates can mean two slightly different things: exact elapsed time or calendar-based hour difference. If you want raw elapsed duration, use timeIntervalSince and divide by 3600. If you want whole-hour differences according to calendar rules, such as local time and daylight saving transitions, use Calendar and DateComponents.

Exact Elapsed Hours

A Date in Swift represents an absolute point in time. That makes exact duration calculations straightforward.

swift
1import Foundation
2
3let start = Date(timeIntervalSince1970: 1_700_000_000)
4let end = start.addingTimeInterval(9_000)
5
6let hours = end.timeIntervalSince(start) / 3600
7print(hours)

This returns 2.5 because 9,000 seconds is two and a half hours.

Use this approach when you care about actual elapsed time, such as a timer, a subscription duration, or a job runtime.

Whole-Hour Difference with Calendar

If you want the difference expressed as calendar components, ask Calendar for the .hour component.

swift
1import Foundation
2
3let formatter = DateFormatter()
4formatter.dateFormat = "yyyy-MM-dd HH:mm"
5formatter.timeZone = TimeZone(identifier: "America/Toronto")
6
7let start = formatter.date(from: "2026-03-10 08:00")!
8let end = formatter.date(from: "2026-03-10 13:45")!
9
10let hours = Calendar.current.dateComponents([.hour], from: start, to: end).hour!
11print(hours)

This prints 5, because DateComponents gives the whole-hour difference as a calendar component, not the fractional elapsed hours.

That distinction matters. If you need 5.75 hours, use timeIntervalSince instead.

Choose the Right Meaning of "Hours"

There are three common interpretations:

  • exact fractional hours, such as 2.5
  • whole elapsed hours, such as 2
  • calendar component difference, which may be affected by local calendar rules

A good implementation starts by picking the correct meaning instead of reaching for Calendar automatically.

Daylight Saving Time Can Change the Result

Calendar-aware calculations can behave differently across daylight saving boundaries.

For example, a local clock jump can make the calendar difference in apparent hours different from a naive assumption based on wall-clock labels.

That is why duration code should be explicit:

  • use timeIntervalSince for physical elapsed time
  • use Calendar when business rules depend on local calendar interpretation

If you are calculating times for scheduling, appointments, or local date logic, Calendar is usually the correct abstraction. For stopwatch-style durations, Date interval math is usually better.

Parsing Dates Correctly

Many bugs come from date parsing rather than the difference calculation itself. If you use DateFormatter, make sure the format, locale, and time zone are explicit.

swift
1let formatter = DateFormatter()
2formatter.locale = Locale(identifier: "en_US_POSIX")
3formatter.timeZone = TimeZone(secondsFromGMT: 0)
4formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

Without explicit settings, the same input string can be interpreted differently across devices or regions.

A Reusable Helper

swift
1import Foundation
2
3func elapsedHours(from start: Date, to end: Date) -> Double {
4    end.timeIntervalSince(start) / 3600
5}
6
7func calendarHours(from start: Date, to end: Date, calendar: Calendar = .current) -> Int {
8    calendar.dateComponents([.hour], from: start, to: end).hour ?? 0
9}

This keeps the two meanings separate and avoids mixing calendar logic with duration math.

Common Pitfalls

The biggest mistake is not deciding whether you want exact elapsed hours or calendar-based whole hours.

Another mistake is dividing by 3600 and expecting the result to follow local calendar rules such as daylight saving time changes.

A third issue is parsing input dates with an implicit locale or time zone and then blaming the difference calculation when the real bug is in the parsing step.

Summary

  • Use timeIntervalSince divided by 3600 for exact elapsed hours
  • Use Calendar.dateComponents([.hour], from:to:) for calendar-based whole-hour differences
  • Be explicit about which meaning of "hours" the app actually needs
  • Time zone and daylight saving behavior matter for calendar-based calculations
  • Many date bugs come from parsing and formatter configuration rather than the subtraction itself

Course illustration
Course illustration

All Rights Reserved.