NSDate
Swift programming
iOS development
time manipulation
date handling

NSDate beginning of day and end of day

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

NSDate or Date represents an absolute point in time, not a calendar-aware "day boundary" by itself. To get the beginning or end of a day, you need a Calendar and a time zone context, because day boundaries depend on locale and daylight saving transitions rather than on the raw timestamp alone.

Start Of Day Is A Calendar Operation

In modern Swift, the cleanest way to get the beginning of the day is startOfDay(for:).

swift
1import Foundation
2
3let now = Date()
4let calendar = Calendar.current
5let start = calendar.startOfDay(for: now)
6
7print(start)

This returns the first valid moment of that day in the calendar's current time zone.

That is safer than trying to manually subtract hours, minutes, and seconds because calendars are not uniform across all dates and zones.

Compute The End Of Day Safely

A common mistake is trying to define the end of day as 23:59:59. That can work superficially, but a safer pattern is to compute the start of the next day and subtract a small amount if you really need an inclusive endpoint.

swift
1import Foundation
2
3let calendar = Calendar.current
4let now = Date()
5let startOfToday = calendar.startOfDay(for: now)
6let startOfTomorrow = calendar.date(byAdding: .day, value: 1, to: startOfToday)!
7let endOfToday = startOfTomorrow.addingTimeInterval(-1)
8
9print(startOfToday)
10print(endOfToday)

This gives you the last second before the next day begins.

Even better, for filtering and database queries, use a half-open range rather than an explicit end-of-day second.

Prefer Half-Open Ranges In Real Logic

Instead of saying:

  • from start of day to 23:59:59

prefer:

  • from start of day inclusive
  • to start of next day exclusive

Example:

swift
1let start = calendar.startOfDay(for: now)
2let nextStart = calendar.date(byAdding: .day, value: 1, to: start)!
3
4let isToday = (start ..< nextStart).contains(now)
5print(isToday)

This pattern avoids awkward edge cases around seconds, sub-second precision, and daylight saving transitions.

It is usually the best design whenever you are filtering records by day.

If You Still Work With NSDate

Older Objective-C or older Swift examples may use NSDate and NSCalendar directly. The concept is the same.

Objective-C style:

objc
1NSDate *now = [NSDate date];
2NSCalendar *calendar = [NSCalendar currentCalendar];
3NSDate *startOfDay;
4[calendar rangeOfUnit:NSCalendarUnitDay startDate:&startOfDay interval:NULL forDate:now];
5NSLog(@"%@", startOfDay);

That gives you the beginning of the day. The API is older, but the principle remains: let the calendar calculate the boundary rather than hardcoding clock math.

Time Zone And DST Matter

Day boundaries depend on time zone. A given absolute Date may belong to different local calendar days depending on which time zone you use.

That is why Calendar.current and a custom calendar with a chosen time zone can produce different answers.

Example:

swift
1var utcCalendar = Calendar(identifier: .gregorian)
2utcCalendar.timeZone = TimeZone(secondsFromGMT: 0)!
3
4let utcStart = utcCalendar.startOfDay(for: now)
5print(utcStart)

This is crucial for:

  • analytics grouped by user-local day
  • server-side reporting in UTC
  • cross-time-zone scheduling

A "day" is not universal until you define the time zone.

When You Need Date Components Instead

Sometimes you do not need an exact timestamp boundary at all. You just need the calendar components.

swift
let components = calendar.dateComponents([.year, .month, .day], from: now)
print(components)

This can be useful for labeling, grouping, or formatting, but if you need an actual time range for comparisons, use startOfDay and next-day boundaries.

Common Pitfalls

The biggest mistake is assuming Date itself knows what "beginning of day" means. It does not; that is a calendar interpretation.

Another mistake is hardcoding 23:59:59 as if every day has a simple fixed final second in every time zone context. Daylight saving transitions can make direct clock assumptions fragile.

People also forget to define the time zone explicitly when the business rule depends on UTC or another non-device-local zone.

Finally, for filtering, inclusive end-of-day timestamps are often harder to reason about than half-open ranges using the next day's start.

Summary

  • 'Date is an absolute instant; calendar day boundaries come from Calendar.'
  • Use calendar.startOfDay(for:) to get the beginning of a day.
  • For end-of-day logic, prefer the start of the next day and half-open ranges.
  • Time zone and daylight saving rules affect what a "day" means.
  • Avoid manual hour-minute-second math when the calendar API can compute the boundary correctly.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.