Date Range Styles
Interval Date Style (Date Range) Xcode 13+
Shows the earliest and last dates in aRange
, similar options to the Date and Time single date format style.
For a given Range<Date>
, this format will output the earliest and last days.
Symbol | Description |
---|---|
.day() |
The numerical day relative to the month |
.hour() |
The hour |
.minute() |
The minute |
.month() |
The month of the year |
.second() |
The second |
.timeZone |
The time zone |
.weekday() |
The named day of the week |
.year() |
The year |
let range = Date(timeIntervalSince1970: 0)..<Date(timeIntervalSinceReferenceDate: 2837)
range.formatted(.interval) // "12/31/69, 5:00 PM – 12/31/00, 5:47 PM"
range.formatted(.interval.day()) // "12/31/1969 – 12/31/2000"
range.formatted(.interval.hour()) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
range.formatted(.interval.hour(.conversationalDefaultDigits(amPM: .abbreviated))) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
range.formatted(.interval.hour(.conversationalDefaultDigits(amPM: .narrow))) // "12/31/1969, 5 p – 12/31/2000, 5 p"
range.formatted(.interval.hour(.conversationalDefaultDigits(amPM: .omitted))) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
range.formatted(.interval.hour(.conversationalDefaultDigits(amPM: .wide))) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
range.formatted(.interval.minute()) // "12/31/1969, 0 – 12/31/2000, 47"
range.formatted(.interval.month(.defaultDigits)) // "12/1969 – 12/2000"
range.formatted(.interval.month(.twoDigits)) // "12/1969 – 12/2000"
range.formatted(.interval.month(.wide)) // "December 1969 – December 2000"
range.formatted(.interval.month(.narrow)) // "D 1969 – D 2000"
range.formatted(.interval.month(.abbreviated)) // "Dec 1969 – Dec 2000"
range.formatted(.interval.second()) // "12/31/1969, 0 – 12/31/2000, 17"
range.formatted(.interval.timeZone()) // "12/31/1969, MST – 12/31/2000, MT"
range.formatted(.interval.timeZone(.exemplarLocation)) // "12/31/1969, Edmonton – 12/31/2000, Edmonton"
range.formatted(.interval.timeZone(.genericLocation)) // "12/31/1969, Edmonton Time – 12/31/2000, Edmonton Time"
range.formatted(.interval.timeZone(.genericName(.long))) // "12/31/1969, Mountain Standard Time – 12/31/2000, Mountain Time"
range.formatted(.interval.timeZone(.genericName(.short))) // "12/31/1969, MST – 12/31/2000, MT"
range.formatted(.interval.timeZone(.identifier(.short))) // "12/31/1969, caedm – 12/31/2000, caedm"
range.formatted(.interval.timeZone(.identifier(.long))) // "12/31/1969, America/Edmonton – 12/31/2000, America/Edmonton"
range.formatted(.interval.timeZone(.iso8601(.short))) // "12/31/1969, -0700 – 12/31/2000, -0700"
range.formatted(.interval.timeZone(.iso8601(.long))) // "12/31/1969, -07:00 – 12/31/2000, -07:00"
range.formatted(.interval.timeZone(.localizedGMT(.short))) // "GMT-7"
range.formatted(.interval.timeZone(.localizedGMT(.long))) // "12/31/1969, GMT-07:00 – 12/31/2000, GMT-07:00"
range.formatted(.interval.timeZone(.specificName(.long))) // "12/31/1969, Mountain Standard Time – 12/31/2000, Mountain Standard Time"
range.formatted(.interval.timeZone(.specificName(.short))) // "12/31/1969, MST – 12/31/2000, MST"
range.formatted(.interval.year()) //"1969 – 2000"
Date.IntervalFormatStyle().day().format(range) // "12/31/1969 – 12/31/2000"
Date.IntervalFormatStyle().hour().format(range) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
Date.IntervalFormatStyle().hour(.conversationalDefaultDigits(amPM: .abbreviated)).format(range) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
Date.IntervalFormatStyle().hour(.conversationalDefaultDigits(amPM: .narrow)).format(range) // "12/31/1969, 5 p – 12/31/2000, 5 p"
Date.IntervalFormatStyle().hour(.conversationalDefaultDigits(amPM: .omitted)).format(range) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
Date.IntervalFormatStyle().hour(.conversationalDefaultDigits(amPM: .wide)).format(range) // "12/31/1969, 5 PM – 12/31/2000, 5 PM"
Date.IntervalFormatStyle().minute().format(range) // "12/31/1969, 0 – 12/31/2000, 47"
Date.IntervalFormatStyle().month(.defaultDigits).format(range) // "12/1969 – 12/2000"
Date.IntervalFormatStyle().month(.twoDigits).format(range) // "12/1969 – 12/2000"
Date.IntervalFormatStyle().month(.wide).format(range) // "December 1969 – December 2000"
Date.IntervalFormatStyle().month(.narrow).format(range) // "D 1969 – D 2000"
Date.IntervalFormatStyle().month(.abbreviated).format(range) // "Dec 1969 – Dec 2000"
Date.IntervalFormatStyle().second().format(range) // "12/31/1969, 0 – 12/31/2000, 17"
Date.IntervalFormatStyle().timeZone().format(range) // "12/31/1969, MST – 12/31/2000, MT"
Date.IntervalFormatStyle().timeZone(.exemplarLocation).format(range) // "12/31/1969, Edmonton – 12/31/2000, Edmonton"
Date.IntervalFormatStyle().timeZone(.genericLocation).format(range) // "12/31/1969, Edmonton Time – 12/31/2000, Edmonton Time"
Date.IntervalFormatStyle().timeZone(.genericName(.long)).format(range) // "12/31/1969, Mountain Standard Time – 12/31/2000, Mountain Time"
Date.IntervalFormatStyle().timeZone(.genericName(.short)).format(range) // "12/31/1969, MST – 12/31/2000, MT"
Date.IntervalFormatStyle().timeZone(.identifier(.short)).format(range) // "12/31/1969, caedm – 12/31/2000, caedm"
Date.IntervalFormatStyle().timeZone(.identifier(.long)).format(range) // "12/31/1969, America/Edmonton – 12/31/2000, America/Edmonton"
Date.IntervalFormatStyle().timeZone(.iso8601(.short)).format(range) // "12/31/1969, -0700 – 12/31/2000, -0700"
Date.IntervalFormatStyle().timeZone(.iso8601(.long)).format(range) // "12/31/1969, -07:00 – 12/31/2000, -07:00"
Date.IntervalFormatStyle().timeZone(.localizedGMT(.short)).format(range) // "GMT-7"
Date.IntervalFormatStyle().timeZone(.localizedGMT(.long)).format(range) // "12/31/1969, GMT-07:00 – 12/31/2000, GMT-07:00"
Date.IntervalFormatStyle().timeZone(.specificName(.long)).format(range) // "12/31/1969, Mountain Standard Time – 12/31/2000, Mountain Standard Time"
Date.IntervalFormatStyle().timeZone(.specificName(.short)).format(range) // "12/31/1969, MST – 12/31/2000, MST"
Date.IntervalFormatStyle().year().format(range) //"1969 – 2000"
You can customize the locale of the output by appending the localized()
method onto the style.
let franceLocale = Locale(identifier: "fr_FR")
range.formatted(.interval.locale(franceLocale)) // "31/12/1969 à 17:00 – 31/12/2000 à 17:47"
DateStyle | Description |
---|---|
.omitted |
Excludes the date part. |
.numeric |
Shows date components in their numeric form. For example, “10/21/2015”. |
.abbreviated |
Shows date components in their abbreviated form if possible. For example, “Oct 21, 2015”. |
.long |
Shows date components in their long form if possible. For example, “October 21, 2015”. |
.complete |
Shows the complete day. For example, “Wednesday, October 21, 2015”. |
TimeStyle | Description |
---|---|
.omitted |
Excludes the time part. |
.shortened |
For example, 04:29 PM , 16:29 . |
.standard |
For example, 4:29:24 PM , 16:29:24 . |
.complete |
For example, 4:29:24 PM PDT , 16:29:24 GMT . |
struct NarrowIntervalStyle: FormatStyle {
static let interval = Date.IntervalFormatStyle(
date: .abbreviated,
time: .shortened,
locale: Locale(identifier: "en_US"),
calendar: Calendar(identifier: .gregorian),
timeZone: TimeZone(secondsFromGMT: 0)!
)
func format(_ value: Range<Date>) -> String {
NarrowIntervalStyle.interval.format(value)
}
}
extension FormatStyle where Self == NarrowIntervalStyle {
static var narrowInterval: NarrowIntervalStyle { .init() }
}
range.formatted(.narrowInterval)
Components Date Style (Date Range) Xcode 13+
Shows the distance between the earliest and latest dates in a range, similar to the Relative Date style for single dates.
For a given Range<Date>
, you can display the distance between the earliest and latest dates using specific units.
For all given fields, the system will only display the unit if it’s not a 0 value. Including the field will only specify that the unit might be used.
day
hour
minute
month
second
week
year
Style Option | Description |
---|---|
wide | Shows the fields in their full spelling. For example, “2 hour, 10 minutes”, “2小時10分鐘” |
abbreviated | Shows the fields in the abbreviation. For example, “2 hr, 10 min”, “2小時10分鐘” |
condensedAbbreviated | Uses the abbreviated form but condensed if possible. For example, “2hr 10min”, “2小時10分鐘” |
narrow | Shows the fields in the shortest form possible. For example, “2h 10m”, “2時10分” |
spellOut | Values are spelled out and fields are displayed in their full name. For example, “two hours, ten minutes”, “2小時10分鐘” |
let testRange = Date(timeIntervalSince1970: 0) ..< Date(timeIntervalSinceReferenceDate: 0)
testRange.formatted(.components(style: .abbreviated, fields: [.day])) // "11,323 days"
testRange.formatted(.components(style: .narrow, fields: [.day])) // "11,323days"
testRange.formatted(.components(style: .wide, fields: [.day])) // "11,323 days"
testRange.formatted(.components(style: .spellOut, fields: [.day])) // "eleven thousand three hundred twenty-three days"
testRange.formatted(.components(style: .condensedAbbreviated, fields: [.day])) // "11,323d"
testRange.formatted(.components(style: .abbreviated, fields: [.year])
.calendar(Calendar(identifier: .coptic))) // "31 yrs"
testRange.formatted(.components(style: .condensedAbbreviated, fields: [.day, .month, .year, .hour, .second, .week])) // "31y"
let appleReferenceDay = Date(timeIntervalSinceReferenceDate: 0)
let twosday = Calendar(identifier: .gregorian).date(from: twosdayDateComponents)!
let secondRange = appleReferenceDay .. <twosday
// 21 yrs, 1 mth, 3 wks, 9 hr, 1,342 sec
secondRange.formatted(.components(style: .abbreviated, fields: [.day, .month, .year, .hour, .second, .week]))
// 21yrs 1mth 3wks 9hr 1,342sec
secondRange.formatted(.components(style: .narrow, fields: [.day, .month, .year, .hour, .second, .week]))
// 21 years, 1 month, 3 weeks, 9 hours, 1,342 seconds
secondRange.formatted(.components(style: .wide, fields: [.day, .month, .year, .hour, .second, .week]))
// twenty-one years, one month, three weeks, nine hours, one thousand three hundred forty-two seconds
secondRange.formatted(.components(style: .spellOut, fields: [.day, .month, .year, .hour, .second, .week]))
// 21y 1mo 3w 9h 1,342s
secondRange.formatted(.components(style: .condensedAbbreviated, fields: [.day, .month, .year, .hour, .second, .week]))
You can set the locale by appending the locale()
method onto the end of the format style.
let franceLocale = Locale(identifier: "fr_FR")
// vingt-et-un ans, un mois, trois semaines, neuf heures et mille trois cent quarante-deux secondes
secondRange.formatted(.components(style: .spellOut, fields: [.day, .month, .year, .hour, .second, .week]).locale(franceLocale))
You can set the calendar by using the Date.ComponentFormatStyle
initializer and using the resulting format style.
let componentsFormat = Date.ComponentsFormatStyle(
style: .wide,
locale: Locale(identifier: "fr_FR"),
calendar: Calendar(identifier: .gregorian),
fields: [
.day,
.month,
.year,
.hour,
.second,
.week,
]
)
componentsFormat.format(secondRange) // "21 ans, 1 mois, 3 semaines, 9 heures et 1 342 secondes"
secondRange.formatted(componentsFormat) // "21 ans, 1 mois, 3 semaines, 9 heures et 1 342 secondes"
struct InFrench: FormatStyle {
typealias FormatInput = Range<Date>
typealias FormatOutput = String
static let componentsFormat = Date.ComponentsFormatStyle(
style: .wide,
locale: Locale(identifier: "fr_FR"),
calendar: Calendar(identifier: .gregorian),
fields: [
.day,
.month,
.year,
.hour,
.second,
.week,
]
)
func format(_ value: Range<Date>) -> String {
InFrench.componentsFormat.format(value)
}
}
extension FormatStyle where Self == InFrench {
static var inFrench: InFrench { .init() }
}
secondRange.formatted(.inFrench) // "21 ans, 1 mois, 3 semaines, 9 heures et 1 342 secondes"