LoginSignup
13
13

More than 3 years have passed since last update.

DateFormatter使うときはもちろん12時間表示のこと考えてますよね?

Last updated at Posted at 2019-02-27

iOSの設定 > 日付と時刻には悪魔の設定があります。
そう、12時間表示です
IMG_3D59590EACDF-1.jpeg

今回はDateFormatterを使っていて陥った12時間表示の罠と、その解決策を備忘録としてまとめました。

DateFormatterの落とし穴

わかりやすくDate型を下記のようにDateFormatterを使って時間だけを表示したい場合
を考えたい思います。

let formatter = DateFormatter()
formatter.timeZone = .current
formatter.locale = .current
formatter.timeStyle = .short
formatter.dateStyle = .none

let timeLabel = formatter.string(from: Date())
print(timeLabel)
// 理想の出力) "23:59"

12時間表示

ユーザが12時間表示設定している端末では、上記の出力は

//端末は12時間表示設定

let formatter = DateFormatter()
formatter.timeZone = .current
formatter.timeStyle = .short
formatter.dateStyle = .none

formatter.locale = Locale(identifier: "ja_JP")
let timeLabel = formatter.string(from: Date())
print(timeLabel)
// 出力) "午後11:59"

formatter.locale = Locale(identifier: "en_US")
let timeLabel2 = formatter.string(from: Date())
print(timeLabel2)
// 出力) "PM11:59"

なんだか余計な"午後"や"PM"といった文字がくっついてきますね。
textLabelの長さが言語によって変わってしまうのでUIによっては不便だと思います。

冒頭に書いた純正カレンダー内でも、書き込み時にGoogle Calender APIに渡すDate型の文字列
がバグってしまってることが想像できます。

"hh:mm"とか"HH:mm"とかで指定できなかったっけ?

まず考えたのが、なんかフォーマットを大文字の"HH"で指定したら24時間表示にならなかったっけ?
ということです。

実際ICU User Guideを参照すると

Symbol Meaning Example(s) output
h hour in am/pm (1~12) h,hh 7,07
H hour in day (0~23) H,HH 0,00
k hour in day (1~24) k,kk 24,24
K hour in am/pm (0~11) K,KK 0,00

HHkkなんかが使えそうです。
あとは、
formatter.dateFormat = "HH:mm"
のようにフォーマットを指定すればうまくいきそうですね。
.dateFormatを指定するのはアンチパターンだというのは有名ですが、
時間を抜き出す目的ならば問題なさそうです。









しかし、結論から言えばこれは失敗します!
これでは午前・午後がついたままで、出力は先ほどと同様です。(これが仕様なのかはわからないです)

解決策

.localeNSLocale.systemを指定することで上手くいきます。

定義をNSLocale.localeと比べてみると

.system
A locale representing the generic root values with little localization.

.locale
A locale representing the user's region settings at the time the property is read.

とあり、どうやらgeneric root valuesが24時間表記で固定されているようです。

//端末は12時間表示設定

let formatter = DateFormatter()
formatter.timeZone = .current
formatter.timeStyle = .short
formatter.dateStyle = .none
formatter.locale = NSLocale.system
let timeLabel = formatter.string(from: Date())
print(timeLabel)
// 出力) "11:59"
13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13