your3i’s blog

iOSエンジニア。頑張る⚉

Swiftでの日付フォーマットのメモ

アプリでDateの扱いは2パターンある

  • APIの日付文字列をDate型にマッピング
  • Date型をユーザーに見せるStringに変換

この2つのタイミングで、DateFormatterが使われる。DateFormatterにはdateFormat, calendarやlocaleを設定必要があり、どんなタイミングでどんな値を設定すれば?って感じに混乱になる。

各ものの概念の理解

calendar -> 年月日などの要素の数え方と関係

dateFormat -> 日付情報はどういう風に並んでるのか

locale -> 地域のこと。これで並び方や表記が変わる。localizationが行われる

timezone -> timezoneを設定することで、時間がそのtimezoneの時間に変換される

 

ここで、私は最初localeがtimezoneの機能持っていると間違えしてた。

localeはあくまでも表示に使われる。

 

↓すごいいい感じのまとめです。ありがとうございます!

【Swift】Calendar, Locale, TimeZoneなど、国際化周りのクラスを整理 - しめ鯖日記


String -> Date

 フォーマット固定の日付文字列を正しい日付のDate型に変換。

let formatter = DateFormatter()
// dateFormatをAPIのフォーマットに合わせて設定(rfc3339)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"
// localeをen_US_POSIXに設定
formatter.locale = Locale(identifier: "en_US_POSIX")
// calendarを日付文字列だ使ってるcalendarに設定
formatter.calendar = Calendar(identifier: .gregorian)
let date = formatter.date(from: "2018-06-16 19:27:30...")

en_US_POSIXとは↓、よくわからないけど…

a locale that's specifically designed to yield US English results regardless of both user and system preferences

rfc3339とはネット上でよく使われてるフォーマットのポリシーみたいなものかな、iso8601もあるけど、どっちがどっちかも正直わからない…rfc3339はiso8601からのものだけわかった

timezoneは文字列に含まれてるため、設定しなくてもいいかな。

Date型をユーザーに見せるStringに変換

Stringに変換するとき、変わるかもって考える必要があるのは2つ

  • 表記
  • 表示される時間

[表記]
表記はdateFormatを設定することで、固定なフォーマットで表示することができる。しかし、地域によって慣れてる表記が違うため、固定しちゃうとよくない。例えば、地域Aの表記は月/日/年で、地域Bの方が日/月/年の見方が多い場合、固定したフォーマットで月/日/年で表示した場合(06/07/2018)間違えた日付が地域Bのユーザーに取られる。そのため、ちゃんとlocalizationをやる必要がある。

[表示される時間]
timezoneは特に指定する必要がないと思う。ユーザーのtimezoneが使われるはず。

Date -> String

// styleを使う
// Localeはcurrentが使われるだしょう
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short
let localizedString = formatter.string(from: Date())
// templateを使う
// 必要な要素を設定すれば、localizationが勝手にやってくれる
let formatter = DateFormatter()
formatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "yyyyMM", options: 0, locale: nil)
return formatter.string(from: self)

templateのcheatsheet

f:id:your3i:20180616200417p:plain