📆

SwiftでDateを自然な方法でフォーマットする【SwiftUI】

2024/08/30に公開

iOS18では日付を参照する新しいフォーマットスタイルが追加され、特定の日付を自然な方法でフォーマットできるようになりました。

特定の日付を言及する時、その日付までの距離によってフォーマットを変えるのが自然な方法です。

例えば10分後にイベントが始まる場合は相対的に、イベントは「10分後に」始まる。と書くのが自然です。しかし
例えば10分後にイベントが始まる時、多くの人は相対的に「10分後」イベントが始まると言うでしょう。日付が非常に遠い未来や過去の場合、絶対的な方法で言及する方が簡単になります。例えば、初代iPhoneは「2007年1月に」発表されたと言うでしょう。

新しいフォーマッター

iOS18からはSystemFormatStyle.DateReferenceが追加され、便利な機能を使うことができます。
例えば10分後の日付を参照する際は相対的に言及するのが自然なため「10分後」と表示されます。
言語設定が日本語以外でも自動でローカライズしてくれるので、ハードコードする量が減って安心です。

let tenMinutesLaterDate = Date().addingTimeInterval(600)

// in SwiftUI View
Text(.currentDate, format: .reference(to: tenMinutesLaterDate))

フォーマットされた日付と他の文章を繋げる

実際のユースケースとして、「10分後にイベントが始まります」のように「10分後」と"イベントが始まります"をつなげて使いたい場合があります。

SwiftUIでは2通りのやり方があります。

Textの入れ子

Textの中にTextを埋め込むことができます。

Text("\(Text(.currentDate, format: .reference(to: tenMinutesLaterDate))にイベントが始まります)")

Text同士を + でつなげる

Text() + Text()のように、複数のTextを連結することもできます。
こちらの方法はそれぞれにforegroundStylefontなどのModifierを指定できるので柔軟性が高いです。

Text(.currentDate, format: .reference(to: tenMinutesLaterDate))
+ Text("にイベントが始まります。)

参考資料はこちら

https://www.yururiwork.net/archives/2034
https://gist.github.com/takoikatakotako/5dc94f517af174926ee513e2cca4b354
https://qiita.com/imk2o/items/d34b5f69274350255925

フォーマットされた日付をローカライズする

SystemFormatStyle.DateReferenceがせっかくデバイスの言語設定に応じて日付をローカライズしてくれるので、"にイベントが始まります。"の部分もローカライズしましょう

Strings Catalog等で各言語ごとにローカライズされた文章を用意します

ローカライズできているか確認してみましょう。
.environment(\.locale, Local(identifier: ...))で日本語環境、英語環境でフォーマットされているか確認してみます。

VStack {
    ForEach(["ja_JP", "en_US"], id: \.self) { localeID in
        HStack {
            Image(systemName: "calendar.badge.clock")

            Text("next event is up \(Text(.now, format: .reference(to: tenMinutesLaterDate)))")
                .environment(\.locale, Locale(identifier: localeID))
        }
        .bold()
        .foregroundStyle(.white)
        .padding(16)
        .background(.pink.gradient)
        .clipShape(.capsule(style: .continuous))
        .padding()
    }
}


いい感じにローカライズされました

参考・関連資料

https://youtu.be/CNMRV0F0w74?si=1ZoOtUP8l54Z5nD-&t=689
https://developer.apple.com/documentation/swiftui/systemformatstyle/datereference
https://developer.apple.com/documentation/swiftui/text/init(_:format:)-9d2x4
https://dev.classmethod.jp/articles/swiftui-localization/
https://developer.apple.com/documentation/swiftui/environmentvalues/

Discussion