しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

【Swift】Calendar, Locale, TimeZoneなど、国際化周りのクラスを整理

国際化対応の時、Calendar, Locale, TimeZoneなど様々なクラスが出てきて混乱したのでそれぞれのクラスの役割について調べてみました。

Calendar

Calendar - Foundation | Apple Developer Documentation

A definition of the relationships between calendar units (such as eras, years, and weekdays) and absolute points in time, providing features for calculation and comparison of dates.

公式ドキュメントによると、Calendarの役割は上の通りです。
絶対時間の管理や日付の差分計算などを行います。

実際、次のようなコードで1日先のDateを取得できます。

var components = DateComponents()
components.day = 1
let date = Calendar.current.date(byAdding: components, to: Date())

下のようにDateからDateComponentsを生成する事もできます。

let components = Calendar.current.dateComponents([.day], from: Date())

Calendarでは西暦・和暦の切り替えをする事もできます。
下のようにidentifierを.japaneseにすると和暦のDateComponentsを取得できます。

let components = Calendar(identifier: .japanese).dateComponents([.year], from: Date())
components.year // → 29

DateFormatterもCalendarを.japaneseにする事で和暦に切り替える事ができます。

let formatter = DateFormatter()
formatter.dateFormat = "y年"
formatter.calendar = Calendar(identifier: .japanese)
formatter.string(from: Date()) // 29年

Locale

Locale - Foundation | Apple Developer Documentation

Information about linguistic, cultural, and technological conventions for use in formatting data for presentation.

公式ドキュメントでの説明は上の通りです。
Localeは現在の言語を扱うもののようです。

下のようにidentifierを見る事で現在の言語を判定する事ができます。

Locale.current.identifier // → "en_US"

国ごとのDateFormatを取得したい時にも使えます。

let format = DateFormatter.dateFormat(fromTemplate: "MMMMyyyy", options: 0, locale: Locale(identifier: "en")) // → MMMM yyyy

let format = DateFormatter.dateFormat(fromTemplate: "MMMMyyyy", options: 0, locale: Locale(identifier: "ja")) // → yyyy年MM月

TimeZone

TimeZone - Foundation | Apple Developer Documentation

Information about standard time conventions associated with a specific geopolitical region.

TimeZoneは名前の通りTimeZoneを扱うクラスです。

DateFormatterのTimeZoneを変更すれば、そのTimeZoneでの出力をしてくれます。

let formatter = DateFormatter()
formatter.dateFormat = "HH"
formatter.timeZone = TimeZone(identifier: "Asia/Shanghai")
formatter.string(from: Date()) // → 13
formatter.timeZone = TimeZone(identifier: "Asia/Tokyo")
formatter.string(from: Date()) // → 14

DateComponentsのTimeZoneを変更すれば、DateComponentsからDateへの変換に影響を与えます。

var components = Calendar.current.dateComponents([.calendar, .year, .month, .day, .hour], from: Date())
components.timeZone = TimeZone(identifier: "Asia/Shanghai")
components.date // 15:00のDate
components.timeZone = TimeZone(identifier: "Asia/Tokyo")
components.date // 14:00のDate