Date is just a point in time, so it has no hour property. Ask a Calendar for the component instead: Calendar.current.component(.hour, from: Date()). Use dateComponents(_:from:) when you need several fields at once, and a DateFormatter only when you need a display string.Why this happens
Date (the Swift name for NSDate) stores a single Double: the number of seconds since the reference date of 1 January 2001, 00:00:00 UTC. You can see that raw value with Date().timeIntervalSinceReferenceDate. It is a timestamp, not a calendar record, so there is no hour, day or month to read from it.
An hour only exists relative to a calendar and a time zone. 14:00 in Tokyo and 14:00 in Los Angeles are different instants, and even the same instant can be “3 PM” or “15:00” depending on how you format it. That context lives in Calendar, which is why every correct answer routes through it.
If you have seen dateWithCalendarFormat mentioned, that is a legacy API from the early Cocoa date-formatting era. It is not the modern path and is not exposed to Swift. Ignore it and use Calendar.
How to fix it
1. Ask Calendar for a single component
This is the direct replacement for the date.hour you were looking for.
import Foundation
let now = Date()
let calendar = Calendar.current
let hour = calendar.component(.hour, from: now) // 0...23
let minute = calendar.component(.minute, from: now) // 0...59
let second = calendar.component(.second, from: now) // 0...59
print("It is \(hour):\(minute)")
component(_:from:) returns an Int, not a string, so you can compare it, do arithmetic on it, or feed it into your own logic. Note that .hour is always 0–23 here. The user’s 12-hour/24-hour preference only affects formatting, never the component value.
2. Read several fields in one pass
Calling component(_:from:) five times works, but dateComponents(_:from:) is cleaner and does a single calendar calculation.
let components = Calendar.current.dateComponents(
[.year, .month, .day, .hour, .minute],
from: Date()
)
if let hour = components.hour, let minute = components.minute {
print("Now: \(hour):\(minute)")
}
The properties on DateComponents are optional because you only asked for some of them, so unwrap before using them.
3. Pin the time zone when it matters
Calendar.current follows the device’s region and time zone. For a clock that must show a fixed zone — a server timestamp, a schedule in another country — build the calendar explicitly.
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "Asia/Tokyo") ?? .current
let tokyoHour = calendar.component(.hour, from: Date())
If the app should react when the user changes time zone or calendar while it is running, use Calendar.autoupdatingCurrent instead of Calendar.current. current is a snapshot taken when you read it; autoupdatingCurrent keeps tracking changes.
4. Use DateFormatter only when you need a string
Formatting is a presentation concern. If the goal is to show “14:05” on screen, a formatter is the right tool — but set the locale and time zone deliberately so the output does not shift under you.
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "HH:mm"
let stamp = formatter.string(from: Date()) // "14:05"
HH is 24-hour, hh is 12-hour. For anything the user reads, prefer formatter.timeStyle = .short and let the system apply their locale conventions instead of hard-coding a pattern.
5. Going the other way: build a Date from components
When you need a specific moment rather than the current one, assemble DateComponents and let the calendar resolve them.
var components = DateComponents()
components.year = 2026
components.month = 7
components.day = 11
components.hour = 8
components.minute = 34
components.timeZone = TimeZone(identifier: "Asia/Tokyo")
let calendar = Calendar(identifier: .gregorian)
if let date = calendar.date(from: components) {
print(date)
}
date(from:) returns Date? because some component combinations are invalid (31 February, for example). Always handle the optional.
How to prevent it
- Never do arithmetic on
Dateto add hours or days. Usecalendar.date(byAdding: .hour, value: 1, to: date)so daylight saving transitions are handled. - Do not read
hourfrom a formatted string. Parse or compute withCalendarand format only at the edge of your UI. - Set
localeandtimeZoneon everyDateFormatterused for fixed-format output; the device defaults will otherwise change your result. - Prefer
Calendar.autoupdatingCurrentfor long-lived objects that display local time. - Keep
Datein your model layer and convert to components or strings in the view layer.
FAQ
Why is there no date.hour in Swift?
Because Date is a timestamp measured in seconds from a reference point, not a calendar date. Converting that instant into year/month/day/hour requires a calendar and a time zone, which is exactly what Calendar.component(_:from:) supplies.
Does component(.hour, from:) return 12-hour or 24-hour time?
It always returns 0 through 23. The 12-hour/24-hour setting in Settings is a display preference applied by DateFormatter, not by calendar components, so your logic stays stable regardless of the user’s region.
Can I use DateFormatter to get the hour as a number?
You can, by formatting to a string and converting back with Int(...), but it is fragile: the pattern, locale and time zone all have to be right, and it fails silently on unexpected input. Use Calendar for numbers and DateFormatter for text.
Parts of this guide are adapted from content licensed under CC BY-SA 3.0; this article is shared under the same license.
