SwiftでiOSアプリを開発する際、現在日時を特定の書式に変換して利用する場面は頻繁にあります。
DateFormatter はそのための標準的なクラスですが、一見すると正しく動作しているように見え
ても、ユーザーのデバイス設定によっては予期せぬ問題を引き起こす可能性があります。
本記事では、DateFormatter の dateFormat を使用する際に、iPhoneの「24時間表示」設定が原因で発生する問題と、その具体的な解決策について解説します。
問題となりうる事例
まず、どのような問題が発生するのかを見ていきましょう。
Date() で取得した現在日時を、"yyyyMMddHHmmssSSS" という形式の文字列に変換する以下のようなコードを考えます。この文字列は、例えば一時ファイル名の一部として使用するケースなど を想定しています。
Swift
let date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMddHHmmssSSS" // 年月日時分秒ミリ秒
let dateString = formatter.string(from: date)
print(dateString)
使用デバイスの設定(「設定」アプリ →「一般」→「日付と時刻」で「24時間表示」がONの場合) では、このコードは期待通りに動作し、以下のような文字列が出力されます。
出力結果:
20260213231057941
しかし、ユーザーが「24時間表示」をOFFにしている場合、同じコードの出力結果が次のように 変わってしまいます。
出力結果(想定外):
20260213午後111057941
このように、dateFormat で "HH"(0-23時)を指定しているにもかかわらず、"午後" といった 文字列が挿入されて出力されてしまいます。
この文字列を画面に表示するだけならまだしも、ファイル名として利用したり、後続処理で日付 としてパースしたりする場合、予期せぬエラーやデータ不整合の原因となり得ます。
解決策
この問題は、DateFormatter のロケール(地域や言語の設定)が、デバイスの現在の設定に影響
されるために発生します。
これを回避するには、ロケールを明示的に指定します。POSIX形式で固定するのが最も安全で、意図しない変換を防ぐことができます。
Swift
let date = Date()
let formatter = DateFormatter()
// ロケールを "en_US_POSIX" に固定する
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyyMMddHHmmssSSS"
let dateString = formatter.string(from: date)
print(dateString) // "20260213231057941" のように、常に期待通りの形式で出力される
Locale(identifier: "en_US_POSIX") を設定することで、DateFormatter はユーザーのデバイス 設定(12時間/24時間表示、言語など)を無視し、機械処理に適した形式の文字列を返します。
まとめ
この問題事例から、次のような教訓を得ることができます。
1.前提を疑い、仕様を再確認する
dateFormat を設定するだけで、常にその通りの文字列が得られると思い込んでしまうと潜在的な
不具合を混入する可能性があり危険です。
ライブラリやAPIを利用する際は、たとえ直感的に使えたとしても一度は公式ドキュメントや使用例
を確認し、前提条件や注意点がないかを把握しておくことが、品質を高く維持するためには不可欠
となります。
2.できる限り多様なデバイス設定でテストする
開発時には、「24時間表示」のON/OFF以外にも、「外観モード(ダーク/ライト)」の切り替え、「テキストサイズ」の変更など、アプリの動作に影響しうる様々なデバイス設定を試しながらテス
トを実施することで、潜在的な不具合の発見につながります。
また、iOSバージョンが上がることでアプリに影響するデバイス設定が増える場合もあるため、バージョンアップに伴う設定項目の変化にも着目し、影響確認を怠らないことが重要になります。
Swift開発に携わる中で、開発期間が長くなろうとも学ぶべきことは無数にあると改めて感じます。
初心を忘れず、丁寧な開発を心がけていきたいものです。

