- Published on
> Showing a relative "Time ago" date in SwiftUI
- Authors

- Name
- Mick MacCallum
- @0x7fs
Displaying dates as "5 minutes ago" or "yesterday" instead of raw timestamps makes your app feel more conversational and easier to scan. Foundation's RelativeDateTimeFormatter handles this out of the box, with full localization support and several formatting styles to match your UI's tone.
Basic Usage
The formatter compares two dates and produces a human-readable string describing their relationship:
let pastDate = Date.now.addingTimeInterval(-3600) // 1 hour ago
let formatter = RelativeDateTimeFormatter()
let relative = formatter.localizedString(for: pastDate, relativeTo: Date.now)
// "1 hour ago"
For future dates, the formatter automatically adjusts the phrasing:
let futureDate = Date.now.addingTimeInterval(86400) // 24 hours from now
formatter.localizedString(for: futureDate, relativeTo: Date.now)
// "in 1 day"
Customizing the Output Style
The formatter has two main properties that control its output: unitsStyle and dateTimeStyle.
The unitsStyle property determines how units are displayed. The default is .full, but you have several options:
let date = Date.now.addingTimeInterval(-7200) // 2 hours ago
formatter.unitsStyle = .full
// "2 hours ago"
formatter.unitsStyle = .short
// "2 hr. ago"
formatter.unitsStyle = .abbreviated
// "2 hr. ago"
formatter.unitsStyle = .spellOut
// "two hours ago"
The dateTimeStyle property controls whether the formatter uses numeric values or named references like "yesterday". The default is .numeric:
let yesterday = Date.now.addingTimeInterval(-86400)
formatter.dateTimeStyle = .numeric
// "1 day ago"
formatter.dateTimeStyle = .named
// "yesterday"
Named style works well for recent dates where terms like "yesterday" or "last week" feel natural. For older dates or when you need consistency, numeric style is more predictable.
Handling Capitalization
The formattingContext property handles capitalization based on where the text appears in a sentence:
formatter.formattingContext = .beginningOfSentence
// "In 5 minutes"
formatter.formattingContext = .middleOfSentence
// "in 5 minutes"
formatter.formattingContext = .standalone
// Default context
This is particularly useful when you're building sentences dynamically or displaying the relative time in different UI contexts.
Using It in SwiftUI
Here's a simple Text view that displays a relative timestamp:
struct TimeAgoText: View {
let date: Date
private var relativeString: String {
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
return formatter.localizedString(for: date, relativeTo: Date.now)
}
var body: some View {
Text(relativeString)
}
}
For timestamps that should update automatically, you can use a timer to refresh the view:
struct LiveTimeAgoText: View {
let date: Date
@State private var now = Date.now
private let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
private var relativeString: String {
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
return formatter.localizedString(for: date, relativeTo: now)
}
var body: some View {
Text(relativeString)
.onReceive(timer) { _ in
now = Date.now
}
}
}
Localization
The formatter automatically respects the user's locale settings, but you can override it if needed:
let formatter = RelativeDateTimeFormatter()
formatter.locale = Locale(identifier: "es")
formatter.localizedString(for: date, relativeTo: Date.now)
// "hace 2 horas"
This makes RelativeDateTimeFormatter ideal for apps that support multiple languages—you get properly localized relative times without maintaining translation tables for time units.
When to Use Something Else
RelativeDateTimeFormatter works best for recent dates within the past few months. For older dates, the output becomes less useful ("52 weeks ago" isn't particularly helpful). Consider falling back to a standard date format for anything older than a reasonable threshold, or use a combination approach where recent items show relative times and older items show actual dates.
// Continue_Learning
Supporting Dark Mode in a SwiftUI App
Learn how to properly support dark mode in SwiftUI using semantic colors, adaptive color assets, and color scheme detection.
Using SF Symbols in SwiftUI
Learn how to use SF Symbols in your SwiftUI apps, including sizing, coloring, animations, and finding the right symbol for your needs.
@State vs @Binding in SwiftUI: When to Use Each
Understand the difference between @State and @Binding in SwiftUI, when to use each, and how they work together to manage data flow between views.
// Stay Updated
Get notified when I publish new tutorials on Swift, SwiftUI, and iOS development. No spam, unsubscribe anytime.