logo サブスレッド

NSDataFormatterで気をつけること

はじめに

しみずです。どうぞよろしく。

iOSの開発をしている時に、和暦表示にしたり本体設定の24時間表示をOFFにした場合
NSDateFormatterの挙動に気をつけることがあったので、書き残しておきます。

24時間表示をOFFにした場合の挙動

本体設定から24時間表示をOFFにできます。
一般 > 日付と時刻 > 24時間表示 これをOFFに。


ちなみにシミュレータからはこの設定できないようですので実機で確認しましょう。

24時間OFFにした場合、きちんと対策をしないと NSDateFormatter の dateFromString で nil が返ってきてしまいます。

// NSDateFormatter初期化
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

// 文字列 > NSDate へ変換
let date = formatter.dateFromString("2017-03-09 10:00:00")
// date => nil

date が nil なので、その後のコードの書き方次第で
最悪アプリが落ちてしまう事も考えられますね。

和暦表示にした場合の挙動

こちらも本体設定から和暦表示に設定を行えます。
一般 > 日付と時刻 > 歴法 これを和暦に。


こちらはシミュレータでも設定できるようです。

和暦にした場合、NSDateFormatter の年の部分が和暦で扱われます。
例えば、本日の日付をNSDateFormatterを用いて文字列にした場合
今年は平成29年なので、年の部分が29になります。

// NSDateFormatter初期化
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

// 本日を文字列に変換
let dateString = formatter.stringFromDate(NSDate())
// dateString => "0029-03-09 20:16:13"

上記コードでは、年の部分を yyyy と4桁にしているので
年は 0029 となっています。

また、逆に文字列からNSDateに変換する時も年の部分は和暦なので
西暦で指定してしまうと凄い値になってしまいます。

let date = formatter.dateFromString("2017-03-09 10:00:00")
// date => 4005-03-09 10:00:00(JST)

年が 4005年になってますね。
平成元年が 1989年から始まっているので、そこから2016年後の値(平成元年分マイナス1しています)になります。
1989 + 2016 = 4005 ですね。

修正方法

24時間表示、和暦共に以下のように、locale プロパティに “en_US_POSIX” を指定すれば
本体設定に関わらず常に同じ値が取れてくるようになります。
コード上は常に西暦&24時間で扱います。

// NSDateFormatter初期化
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")  // ← コレを追加

// 文字列 > NSDate へ変換
let date = formatter.dateFromString("2017-03-09 10:00:00")
// date => 2017-03-09 10:00:00(JST)

// 本日を文字列に変換
let dateString = formatter.stringFromDate(NSDate())
// dateString => "2017-03-09 20:16:13"

参考:https://developer.apple.com/library/content/qa/qa1480/_index.html

おわりに

たまに不具合が出てしまうNSDateFormatter関連のお話でした。
これに早く気づくために、テスト用端末の数台には和暦表示や24時間表示OFFにしておくと良いですね。

現在の位置:サブスレッド ホーム > 技術ブログ > NSDataFormatterで気をつけること