【Swift】DateFormatterの使い方!書式や日付形式の調整方法

この記事からわかること
- SwiftのDateFormatterとは?
- 日付や日時書式の変更方法
- dateStyle/timeStyleの設定値
- プロパティの種類
- Date()構造体で当日以外の日付を取得する
index
[open]
\ アプリをリリースしました /
Swiftで日付を表示する際の書式や形式を定義できるDateFormatter
の使い方をまとめていきたいと思います。
DateFormatterの使い方
日付や時間を表示する際の形式は状況や環境によって別の形を使うことが多いです。swiftでは日時のフォーマットを定義できるDateFormatter
を使うことで簡単に書式や形式の操作が可能になっています。
暦(西暦:.gregorian
や和暦:.japanese
)やロケール、タイムゾーンは明示的に任意の値に変更でき、設定しない場合は端末に設定されている値が使用されます。
let df = DateFormatter()
df.calendar = Calendar(identifier: .gregorian)
df.locale = Locale(identifier: "ja_JP")
df.timeZone = TimeZone(identifier: "Asia/Tokyo")
DateFormatter
のプロパティには日付の形式を操作できるdateStyle
と時間の形式を操作できるtimeStyle
が用意されています。これらのプロパティはlocale
プロパティにセットされているロケールに準じたフォーマットに自動変換してくれます。
let df = DateFormatter()
df.locale = Locale(identifier: "ja_JP")
df.dateStyle = .full
df.timeStyle = .short
print(df.string(from: Date()))
// "2022年6月19日 日曜日 15:21\n"
DateFormatter
はインスタンス化して使用するので変数df
の中に格納しておきます。その後設定したいロケール(地域などのこと)をlocale
にセットします。
dateStyle
とtimeStyle
で書式を決めたらstring
プロパティに表示させたい日付を渡します。現在時刻を渡すにはDate()
で取得できます。
DateFormatterの使い方〜まとめ〜
- DateFormatter()を変数に格納
- ロケールを設定
- 日付と時間の書式を設定
- stringプロパティの引数に日時を渡す
おすすめ記事:【Swift】Date構造体の使い方!日付の計算や比較方法
dateStyleやtimeStyleに設定できる書式
dateStyle
とtimeStyle
には決められた.full
/.long
/.medium
/.short
/.none
の5つの書式から選択して設定します。
df.dateStyle = .full // 2022年6月19日 日曜日
df.dateStyle = .long // 2022年6月19日
df.dateStyle = .medium // 2022/06/19
df.dateStyle = .short // 2022/06/19
df.dateStyle = .none // 出力しない
df.timeStyle = .full // 15時29分41秒 日本標準時
df.timeStyle = .long // 15:30:27 JST
df.timeStyle = .medium // 15:30:40
df.timeStyle = .short // 15:30
df.timeStyle = .none // 出力しない
日時の書式を自由にカスタマイズする:dateFormat
dateFormat
プロパティを使うとより自由に日時形式をカスタマイズすることができます。
let df = DateFormatter()
df.locale = Locale(identifier: "ja_JP")
df.calendar = Calendar(identifier: .japanese)
df.dateFormat = "令和yy年M月dd日 EEEE HH時mm分"
print(df.string(from: Date()))
// 令和4年6月19日 日曜日 15時41分\n"
年月日や時間はyy
やEEEE
などといったフォーマットパターンがあらかじめ定義されています。上記のように令和◯年といった和暦(4年)で年数を取得する場合はcalendar
プロパティの値を変更します。デフォルトは西暦(2022年)になっています。
和暦(元号)で表示させる
追記:2023/2/22
年数を西暦ではなく和暦かつ元号も表示させたい場合は日時のフォーマットでGy
と指定することで表示させることができました。
let df = DateFormatter()
df.locale = Locale(identifier: "ja_JP")
df.calendar = Calendar(identifier: .japanese)
df.dateFormat = "Gy年M月dd日 EEEE HH時mm分"
print(df.string(from: Date()))
// 令和4年6月19日 日曜日 15時41分\n"
近日の場合は「今日」や「昨日」と表示させる
doesRelativeDateFormatting
プロパティにtrue
を渡すと当日の日付なら「今日」といったような表示にさせることができます。対応しているのは±2日で「一昨日」〜「明後日」までが表示されます。
let df = DateFormatter()
df.locale = Locale(identifier: "ja_JP")
df.dateStyle = .full
df.timeStyle = .none
df.doesRelativeDateFormatting = true
print(df.string(from: Date()))
// 今日
任意の日付文字列でDateFormatterを使用する
文字列として渡された任意の日付情報をDateFormatter
として操作してみます。渡された日付文字列とdateFormat
で指定した形式が異なるとエラーに、オプショナル型になるようで!
で強制的にアンラップしないとエラーになりました。
let df = DateFormatter()
let now = "2022/6/18"
df.dateFormat = "yyyy/MM/dd 誕生"
df.locale = Locale(identifier: "ja_JP")
let date = df.date(from: now)!
print(df.string(from: date))
// 2022/06/18 誕生
Date()構造体で現在時刻以外を指定する
Date()構造体を使って当日以外の日付を指定するにはtimeIntervalSinceNow
に差分を渡せばOKです。60 * 60 * 24
は秒 * 分 * 時
です。
let df = DateFormatter()
let tomorrow = Date(timeIntervalSinceNow: 60 * 60 * 24)
df.dateFormat = "yyyy/MM/dd"
df.locale = Locale(identifier: "ja_JP")
print(df.string(from: tomorrow))
// "2022/06/20"
実際のアプリ開発で日付を用いてみる
使い方は理解できたので実際にSwift UIでiOSアプリを開発する際に使用してみたいと思います。
今回は構造体のプロパティとして日付情報を保持させたいと思います。その日付情報は指定せずともデフォルト値として現在の時刻が格納され、表示するのは時間のみに整形するように作っていきます。
作成したい日付のポイント
- 構造体のプロパティとして
- デフォルト値で現在時刻を格納
- フォーマットは「hh:mm」
- プロパティには文字列型とする
- もちろん日本時間
Xcodeで新規のプロジェクトを作成したら最初から用意されている「ContentView.swift」とは別に構造体を定義するためのSwiftファイルを作成します。
中には以下のように記述します。
struct CashData: Identifiable,Codable{
var id = UUID() // 一意の値
var cash:Int // 金額情報
var memo:String = "" // MEMO
// 初期値に現在の日付
var time:String = {
let df = DateFormatter()
df.calendar = Calendar(identifier: .gregorian)
df.locale = Locale(identifier: "ja_JP")
df.timeZone = TimeZone(identifier: "Asia/Tokyo")
df.dateStyle = .none
df.timeStyle = .short
return df.string(from: Date())
}()
}
今回の構造体はプロパティはList
を使って表示するため「Identifiableプロトコル」に、別JSON形式に変換したいため「Codableプロトコル」に準拠させてきますがDateFormatter
とは無関係であり、重要になってくるのは以下の部分です。
var time:String = {
let df = DateFormatter()
df.calendar = Calendar(identifier: .gregorian)
df.locale = Locale(identifier: "ja_JP")
df.timeZone = TimeZone(identifier: "Asia/Tokyo")
df.dateStyle = .none
df.timeStyle = .short
return df.string(from: Date())
}()
最初はDateFormatter
をインスタンス化してロケールやタイムゾーンを設定する処理を構造体の外に記述しましたが、「Expressions are not allowed at the top level
」というエラーになってしまいました。
なのでプロパティをコンピューテッドプロパティにして、中でロケールなどの初期設定を行います。あとはこれまでの使い方に倣って記述するだけです。
今回は敢えて文字列型として返しましたが、日付型の場合に返す方法がよく分からず力技でなんとか返すこともできました。良い方法があったら教えてください。
return df.date(from: df.string(from: Date()))
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。