Skip to content

Instantly share code, notes, and snippets.

@brettohland
Created March 12, 2022 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brettohland/0bafc12c89143d5e493e349341b31e9e to your computer and use it in GitHub Desktop.
Save brettohland/0bafc12c89143d5e493e349341b31e9e to your computer and use it in GitHub Desktop.
FormatStyle Deep
struct ToYen: FormatStyle {
typealias FormatInput = Int
typealias FormatOutput = String
func format(_ value: Int) -> String {
Decimal(value * 100).formatted(.currency(code: "jpy"))
}
}
extension FormatStyle where Self == ToYen {
static var toYen: ToYen { .init() }
}
30.formatted(.toYen) // "¥3,000"
import Foundation
// MARK: - Setup
let twosdayDateComponents = DateComponents(
year: 2022,
month: 2,
day: 22,
hour: 2,
minute: 22,
second: 22,
nanosecond: 22
)
let twosday = Calendar(identifier: .gregorian).date(from: twosdayDateComponents)!
// MARK: - The Basics
twosday.formatted() // "2/22/2022, 2:22 AM"
// MARK: - DateStyle
twosday.formatted(date: .abbreviated, time: .omitted) // "Feb 22, 2022"
twosday.formatted(date: .complete, time: .omitted) // "Tuesday, February 22, 2022"
twosday.formatted(date: .long, time: .omitted) // "February 22, 2022"
twosday.formatted(date: .numeric, time: .omitted) // "2/22/2022"
// MARK: - TimeStyle
twosday.formatted(date: .omitted, time: .complete) // "2:22:22 AM MST"
twosday.formatted(date: .omitted, time: .shortened) // "2:22 AM"
twosday.formatted(date: .omitted, time: .standard) // "2:22:22 AM"
// MARK: - DateStyle & TimeStyle
twosday.formatted(date: .abbreviated, time: .complete) // "Feb 22, 2022, 2:22:22 AM MST"
twosday.formatted(date: .abbreviated, time: .shortened) // "Feb 22, 2022, 2:22 AM"
twosday.formatted(date: .abbreviated, time: .standard) // "Feb 22, 2022, 2:22:22 AM"
twosday.formatted(date: .complete, time: .complete) // "Tuesday, February 22, 2022, 2:22:22 AM MST"
twosday.formatted(date: .complete, time: .shortened) // "Tuesday, February 22, 2022, 2:22 AM"
twosday.formatted(date: .complete, time: .standard) // "Tuesday, February 22, 2022, 2:22:22 AM"
twosday.formatted(date: .long, time: .complete) // "February 22, 2022, 2:22:22 AM MST"
twosday.formatted(date: .long, time: .shortened) // "February 22, 2022, 2:22 AM"
twosday.formatted(date: .long, time: .standard) // "February 22, 2022, 2:22:22 AM"
twosday.formatted(date: .numeric, time: .complete) // "2/22/2022, 2:22:22 AM MST"
twosday.formatted(date: .numeric, time: .shortened) // "2/22/2022, 2:22 AM"
twosday.formatted(date: .numeric, time: .standard) // "2/22/2022, 2:22:22 AM"
// MARK: - Components
twosday.formatted(.dateTime.day()) // "22"
twosday.formatted(.dateTime.dayOfYear()) // "53"
twosday.formatted(.dateTime.era()) // "AD"
twosday.formatted(.dateTime.hour()) // "2 AM"
twosday.formatted(.dateTime.minute()) // "22"
twosday.formatted(.dateTime.month()) // "Feb"
twosday.formatted(.dateTime.quarter()) // "Q1"
twosday.formatted(.dateTime.second()) // "22"
twosday.formatted(.dateTime.timeZone()) // "MST"
twosday.formatted(.dateTime.week()) // "9"
twosday.formatted(.dateTime.weekday()) // "Tue"
twosday.formatted(.dateTime.year()) // "2022"
// MARK: - Compositing
twosday.formatted(.dateTime.year().month().day().hour().minute().second()) // "Feb 22, 2022, 2:22:22 AM"
twosday.formatted(.dateTime.second().minute().hour().day().month().year()) // "Feb 22, 2022, 2:22:22 AM"
// MARK: - Formatting Individual Components
twosday.formatted(.dateTime.day(.twoDigits)) // "22"
twosday.formatted(.dateTime.day(.ordinalOfDayInMonth)) // "4"
twosday.formatted(.dateTime.day(.defaultDigits)) // "22"
// MARK: - Custom Date.FormatStyle
let frenchHebrew = Date.FormatStyle(
date: .complete,
time: .complete,
locale: Locale(identifier: "fr_FR"),
calendar: Calendar(identifier: .hebrew),
timeZone: TimeZone(secondsFromGMT: 0)!,
capitalizationContext: .standalone
)
twosday.formatted(frenchHebrew) // "Mardi 22 février 2022 ap. J.-C. 9:22:22 UTC"
frenchHebrew.format(twosday) // "Mardi 22 février 2022 ap. J.-C. 9:22:22 UTC"
// MARK: - Custom Date.FormatStyle wrapped in custom FormatStyle extension
struct FrenchHebrewStyle: FormatStyle {
typealias FormatInput = Date
typealias FormatOutput = String
static let frenchHebrew = Date.FormatStyle(
date: .complete,
time: .complete,
locale: Locale(identifier: "fr_FR"),
calendar: Calendar(identifier: .hebrew),
timeZone: TimeZone(secondsFromGMT: 0)!,
capitalizationContext: .standalone
)
func format(_ value: Date) -> String {
FrenchHebrewStyle.frenchHebrew.format(value)
}
}
extension FormatStyle where Self == FrenchHebrewStyle {
static var frenchHebrew: FrenchHebrewStyle { .init() }
}
twosday.formatted(.frenchHebrew) // "Mardi 22 février 2022 ap. J.-C. 9:22:22 UTC"
// MARK: - Custom FormatStyle
/// Returns the date in the most useless way ever
struct ReversedDateFormat: FormatStyle {
typealias FormatInput = Date
typealias FormatOutput = String
func format(_ value: Date) -> String {
"\(value.formatted(.dateTime.second())):" +
"\(value.formatted(.dateTime.minute())):" +
"\(value.formatted(.dateTime.hour())) " +
"\(value.formatted(.dateTime.day())) " +
"\(value.formatted(.dateTime.month())) " +
"\(value.formatted(.dateTime.year())) "
}
}
extension FormatStyle where Self == ReversedDateFormat {
static var reversedDate: ReversedDateFormat { .init() }
}
twosday.formatted(.reversedDate) // "22:22:2 AM 22 Feb 2022"
import Foundation
let thePast = Calendar(identifier: .gregorian).date(byAdding: .day, value: -14, to: Date())!
// MARK: - Without Units
thePast.formatted(.relative(presentation: .numeric)) // "2 weeks ago"
thePast.formatted(.relative(presentation: .named)) // "2 weeks ago"
// MARK: - Including Units
thePast.formatted(.relative(presentation: .numeric, unitsStyle: .abbreviated)) // "2 wk. ago"
thePast.formatted(.relative(presentation: .numeric, unitsStyle: .narrow)) // "2 wk. ago"
thePast.formatted(.relative(presentation: .numeric, unitsStyle: .spellOut)) // "two weeks ago"
thePast.formatted(.relative(presentation: .numeric, unitsStyle: .wide)) // "2 weeks ago"
thePast.formatted(.relative(presentation: .named, unitsStyle: .abbreviated)) // "2 wk. ago"
thePast.formatted(.relative(presentation: .named, unitsStyle: .narrow)) // "2 wk. ago"
thePast.formatted(.relative(presentation: .named, unitsStyle: .spellOut)) // "two weeks ago"
thePast.formatted(.relative(presentation: .named, unitsStyle: .wide)) // "2 weeks ago"
// MARK: - Custom RelativeFormatStyle
let relativeInFrench = Date.RelativeFormatStyle(
presentation: .named,
unitsStyle: .spellOut,
locale: Locale(identifier: "fr_FR"),
calendar: Calendar(identifier: .gregorian),
capitalizationContext: .beginningOfSentence
)
thePast.formatted(relativeInFrench) // "Il y a deux semaines"
relativeInFrench.format(thePast) // "Il y a deux semaines"
// MARK: - Extending FormatStyle
struct InFrench: FormatStyle {
typealias FormatInput = Date
typealias FormatOutput = String
static let relativeInFrench = Date.RelativeFormatStyle(
presentation: .named,
unitsStyle: .spellOut,
locale: Locale(identifier: "fr_FR"),
calendar: Calendar(identifier: .gregorian),
capitalizationContext: .beginningOfSentence
)
func format(_ value: Date) -> String {
InFrench.relativeInFrench.format(value)
}
}
extension FormatStyle where Self == InFrench {
static var inFrench: InFrench { .init() }
}
thePast.formatted(.inFrench) // "Il y a deux semaines"
// Dates
Date(timeIntervalSinceReferenceDate: 0).formatted() // "12/31/2000, 5:00 PM"
// Measurements
Measurement(value: 20, unit: UnitDuration.minutes).formatted() // "20 min"
Measurement(value: 300, unit: UnitLength.miles).formatted() // "300 mi"
Measurement(value: 10, unit: UnitMass.kilograms).formatted() // "22 lb"
Measurement(value: 100, unit: UnitTemperature.celsius).formatted() // "212°F"
// Numbers
32.formatted() // "32"
Decimal(20.0).formatted() // "20"
Float(10.0).formatted() // "10"
Int(2).formatted() // "2"
Double(100.0003).formatted() // "100.0003"
// Names
PersonNameComponents(givenName: "Johnny", familyName: "Appleseed").formatted() // "Johnny Appleseed"
// Lists
["Alba", "Bruce", "Carol", "Billson"].formatted() // "Alba, Bruce, Carol, and Billson"
// TimeInterval
let referenceDay = Date(timeIntervalSinceReferenceDate: 0)
(referenceDay ..< referenceDay.addingTimeInterval(200)).formatted() // "12/31/00, 5:00 – 5:03 PM"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment