とらのメモ

IT関係やガジェットについての雑記

FormatStyle覚え書き

https://developer.apple.com/documentation/foundation/formatstyle

iOS15.0+

fortee.jp

iOSDCでtreastrainさんのセッションを見て知ったので、色々試したのを覚え書き

概要

  • クラス型で指定できるので書きやすいメソッドチェーンを使うことでタイムゾーンや、ディジットなども指定可能地域をアメリカにすると月や日付表示がアメリカ向けに自動で変わる
  • IntervalFormatStyle
  • RelativeFormatStyle
    • 来月、1ヶ月後、一昨日 など
  • Anchore
    • 特定の日から日まで
  • FormatterPercent
  • Units
    • 単位の自動付与
  • Measurement
    • 値に単位を付与できる
  • UnitArea.squareKiloMaterPersonNameCompornent
    • 名前、イニシャルなどが生成可能URL
  • クエリやドメインだけを取得可能
  • ListFormatStyle
    • "〇〇、〇〇、または〇〇"みたいな変換が可能
  • 全部で29種類あるText(date, format: .dateTime())

簡単な例

playground実行

新旧 書き方の比較

旧:

private var dateFormatter: DateFormatter {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy年MM月dd日"
    formatter.locale = Locale(identifier: "ja_JP")
    return formatter
}
↓
Text(dateFormatter.string(from: Date()))

新:FormatStyle を使用:

Text(Date().formatted(
    .dateTime
        .year(.defaultDigits)
        .month(.twoDigits)
        .day(.twoDigits)
        .locale(Locale(identifier: "ja_JP"))
))
  • Locale を渡すだけで、言語やフォーマットが自動調整される
  • "yyyy年MM月dd日" のようなフォーマット文字列が不要になり、可読性・保守性が向上
  • SwiftUI の Text に直接渡せるのでコードも簡潔

他の変換例

相対日付表示(例:「昨日」「1か月後」など)

Text(store.selectedBirthDate.formatted(.relative(presentation: .named)))
// → 「1か月前」や「明日」など

パーセンテージ表示

let progress: Double = 0.82

Text(progress.formatted(.percent))
// → "82%"(ロケールにより「82%」や「82%」などに変化)

リストスタイル(ListFormatStyle)

let items = ["りんご", "みかん", "バナナ"]

Text(items.formatted(.list(type: .or)))
// → "りんご、みかん、またはバナナ"

URLスタイル(URLFormatStyle)

let url = URL(string: "https://example.com/page?ref=123")!

Text(url.formatted(.url.host))
// → "example.com"

Measurement(単位付き数値)

let distance = Measurement(value: 12.4, unit: UnitLength.kilometers)

Text(distance.formatted(.measurement(width: .wide)))
// → "12.4 kilometers"(ロケールにより「12.4キロメートル」などに変化)

名前スタイル(PersonNameComponentsFormatStyle)

var name = PersonNameComponents()
name.familyName = "田中"
name.givenName = "太郎"

Text(name.formatted(.name(style: .long)))
// → "田中太郎"

日付範囲表示(DateIntervalFormatStyle)

DateIntervalFormatter を使う場合

let formatter = DateIntervalFormatter()
formatter.dateStyle = .medium

let start = Calendar.current.date(byAdding: .day, value: -3, to: Date())!
let end = Date()

Text(formatter.string(from: start, to: end))
// → "2025/9/23 – 2025/9/26"

FormatStyle を使う場合

let start = Calendar.current.date(byAdding: .day, value: -3, to: Date())!
let end = Date()

Text(start.formatted(.interval(to: end, style: .date)))
// → "9/23 – 9/26"