ISO8601とは
日付や時間を文字列形式で表現する際のフォーマット1です。
WebサービスのAPIなどでよく使われます。
表記方法には、大きく分けると基本形式と拡張形式の2つがあります。
iOSでの書式指定 | 出力例 | |
---|---|---|
基本形式 | yyyyMMdd'T'HHmmssZZZZZ |
20180214T003318+09:00 |
拡張形式 | yyyy-MM-dd'T'HH:mm:ssZZZZZ |
2018-02-14T00:33:18+09:00 |
※ 余談ですが、iOSでの書式指定では、年(yyyy
)と日(dd
)の部分は必ず小文字にしましょう。
iOSでの変換方法
通常、iOSで日付(Date
)と文字列の相互変換にはDateFormatter
を使います。上の表に記載したのと同じ書式を指定すればISO8601形式も変換できます。
iOS10またはmacOS10.12以降であれば、ISO8601形式の場合は専用のISO8601DateFormatter
が使えます。
Xcode9.2時点ではDateFormatter
の動作も問題なさそうですが、Appleのドキュメントでは、
と記載されているので、使える場合はISO8601DateFormatter
を使った方が良いです。
ISO8601DateFormatterの使い方
ISO8601DateFormatter
はDateFormatter
とよく似ています。
基本的な使い方は、
let fmt = ISO8601DateFormatter()
という様に生成してから、
// ISO8601表記の文字列から日付(Date)へ変換
fmt.date(from: "2018-02-14T00:51:31+09:00")
// 日付(Date)からISO8601表記の文字列へ変換
fmt.string(from: Date()) // 2018-02-13T15:51:31Z
となります。
フォーマット指定
デフォルトでのフォーマットは、拡張形式(yyyy-MM-dd'T'HH:mm:ssZZZZZ
)となります。
フォーマットを変更したい場合は、ISO8601DateFormatter.Options
2を指定します。
例えば、日付のみを"-"区切りで表示したい場合は、
let fmt = ISO8601DateFormatter()
fmt.formatOptions = .withFullDate
fmt.string(from: Date()) // 2018-02-14
と指定できます。
RFC 3339形式
RFC33393形式の表記にしたい場合は、ISO8601DateFormatter.Options.withInternetDateTime
を指定します。
タイムゾーンの指定
特に何も指定しなかった場合、タイムゾーンはUTC
として扱われます。
現地時間での表記にしたい場合は、次の様にtimeZone
を指定します。
fmt.timeZone = TimeZone.current
この場合、端末のタイムゾーンが日本(JST
)になっていれば、+09:00
での表記となります。
yyyyMMdd'T'HHmmssZZZZZ形式
ISO8601の基本形式で表記したい場合は、少し工夫が必要となります。
というのも、デフォルトの形式から"-"や":"を取り除いたものが基本形式となりますが、フォーマットのオプションとしてそれらを取り除く様なオプションが存在していないからです。
では、どうするかというと以下の様に指定します。
let fmt = ISO8601DateFormatter()
var opt: ISO8601DateFormatter.Options = [.withFullDate, .withFullTime]
opt.remove([.withDashSeparatorInDate, .withColonSeparatorInTime, .withColonSeparatorInTimeZone])
fmt.formatOptions = opt
fmt.timeZone = TimeZone.current // 現地時間表記の場合
fmt.string(from: Date()) // 20180214T005131+0900
ポイントは、opt.remove()
の部分です。このremove
で、指定したオプションを除外しています。
例えば、.withFullDate
には元から.withDashSeparatorInDate
の指定が含まれている為、日付の表記には"-"が入ってしまいます。それでremove
を使い、.withDashSeparatorInDate
の指定を取り除くことで"-"のない表記にしています。
これは、ISO8601DateFormatter.Options
がOptionSet
という型なのでできる方法です。このOptionSet
はいわゆるビットフラグと同じ仕組みで、特定のオプションを追加するだけでなく、簡単に除外することも可能です。便利ですね。
まとめ
ISO8601形式の表記を扱う時は、ISO8601DateFormatter
を使いましょう。
yyyyMMdd
の表記の場合の様に細かいことを考えなくて良いので楽です。
OptionSet
を上手く使えば、柔軟なフォーマットの設定も可能です。
ちなみに、通常のDateFormatter
との速度の違いは見ていません・・・