Swiftにおける曜日と週の扱い方を解説します。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.6.1
【iOS】15.5
【macOS】Monterey バージョン 12.3
曜日の取得方法
Dateから曜日を取得するにはCalendar構造体のcomponentメソッドを使用します。
1 2 3 |
Calendar.component(.weekday, from: Date) |
【引数】
第一引数(component)
取得する要素として「曜日」を示す、.weekdayを指定します。
from
曜日を取得したい対象日をDate型で指定します。
【戻り値】
曜日を示すInt型の識別子を返します。(1〜7、1=日曜日)
曜日名の取得
曜日名(文字列)の一覧はCalendar構造体のプロパティから取得します。
1 2 3 4 5 |
Calendar.weekdaySymbols // 通常の曜日名を返すプロパティ Calendar.shortWeekdaySymbols // 短縮形の曜日名を返すプロパティ |
【戻り値】
曜日名を示す文字列の配列を返します。
文字列の表記はCalendar.localeの「言語」に依存します。
例えば、
localeが"en_US"の場合は["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]が
"ja_JP"の場合は["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"]が返ります。
使用例
特定の日付の曜日名を返すサンプルコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// 西暦カレンダー(gregorian)生成 var calendar = Calendar(identifier: .gregorian) // カレンダーのlocaleを「日本語、日本地域」に設定 calendar.locale = Locale(identifier: "ja_JP") // 生成したカレンダーを使って 2022/7/1 の日付生成 let date = calendar.date(from: DateComponents(year: 2022, month: 7, day: 1)) // 対象日付の曜日識別子を取得 let weekday = calendar.component(.weekday, from: date!) // => 6(金曜日) // 対象日付の曜日を表示 print(calendar.weekdaySymbols[weekday-1]) // "金曜日" |
週の考え方
週の開始日について
一週間は何曜日から始まるのでしょうか?
日本の一般的なカレンダーは日曜日から始まっているものが多いですが、業界や会社によっては月曜日始まりのカレンダーが採用されているケースが少なくありません。
ビジネス手帳などでも日曜始まりのものと月曜日始まりのものがあります。
また、地域によっても違いがあり、フランスやドイツなどのヨーロッパでは月曜日始まり、イスラム圏では土曜日始まりの国もあるようです。
週番号について
第n週目などと表す週番号についても地域によって数え方が変わります。
日本では通常各月の1日目が含まれる週を第1週目とカウントしますが、ヨーロッパ等では最初の木曜日を含む週を第1週目とカウントします。
例えば、次に示す2022年7月のカレンダーを見ると、1日目は金曜日から始まっています。
日本では7/1を含む週が第1週目とカウントしますが、ヨーロッパでは2行目の7/4から始まる週がその月の第1週目とカウントします。
そして、7/1〜7/3の週は、ヨーロッパでは7月の第0週目になります。
年間の週番号の考え方は、また少し異なります。
2022年1月は、以下のように土曜日から始まっていますが、日本では1/1を含む週を2022年の第1週目とカウントします。
対してヨーロッパでは2行目の1/3から始まる週をその年の第1週目とカウントし、1/1〜1/2は2021年の最終週(=52週目)とカウントします。
国際規格(ISO8601)
日付と時刻の表記に関する国際規格(ISO8601)では週に関して次のように定義されています。
・週の始まりは月曜日。
・最初の木曜日を含む週をその年の第1週とする。
先の例でいくとヨーロッパなどの地域は、国際規格に準じているのがわかります。
Swiftでの週の定義
前述のように週の考え方は地域や業界などによって、方式が異なりますが、Swiftでは状況に合わせて柔軟に方式を変更できる仕組みになっています。
具体的には、日付と時間の計算を行うCalendar構造体に次のプロパティで定義します。
Calendar.firstWeekday
カレンダーの最初の曜日を示します。(1〜7、1=日曜日)
日本やアメリカでは1(日曜日)、ヨーロッパ式では2(月曜日)になります。
Calendar.minimumDaysInFirstWeek
最初の週の最小日数を示します。
日本やアメリカでは1、ヨーロッパ式では4になります。
各項目はCalendar.localeを変更すると自動的に初期値が設定されます。
値は後から個別に変更できますが、週の定義をカスタムで変更する場合の注意点で説明するような注意が必要です。
週番号の取得方法
Dateから週番号を取得するにはCalendar構造体のcomponentメソッドを使用します。
1 2 3 4 |
Calendar.component(.weekOfMonth, from: Date) Calendar.component(.weekOfYear, from: Date) |
【引数】
第一引数(component)
月単位の週番号を取得する場合は.weekOfMonthを、年単位の週番号を取得する場合は.weekOfYearを指定します。
from
曜日を取得したい対象日をDate型で指定します。
【戻り値】
週番号を示すInt型の識別子を返します。
年単位週番号の基準年(yearForWeekOfYear)
週番号についてで解説したように、地域によって年単位の週番号が変わります。
日本やアメリカでは2022年1月1日は2022年の1週目ですが、ヨーロッパでは2021年の52週目になります。
つまり年単位週番号の基準となる年が実際の年とは異なるケースがあるわけです。
この基準年を取得するには識別子.yearForWeekOfYearを使用します。
1 2 3 |
Calendar.component(.yearForWeekOfYear, from: Date) |
【引数】
第一引数(component)
年単位週番号(.weekOfYear)の基準年を示す.yearForWeekOfYearを指定します。
from
曜日を取得したい対象日をDate型で指定します。
【戻り値】
年単位週番号の基準年をInt型で返します。
使用例
対象の地域によって各プロパティが変わるのが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import Foundation /// 週番号関連情報の表示 /// - Parameters: /// - calendar: カレンダー /// - date: 対象日付 func showWeekInfo(_ calendar: Calendar, _ date: Date) { print("firstWeekday : \(calendar.firstWeekday)") print("minimumDaysInFirstWeek : \(calendar.minimumDaysInFirstWeek)") print("weekOfMonth : \(calendar.component(.weekOfMonth, from: date))") print("weekOfYear : \(calendar.component(.weekOfYear, from: date))") print("yearForWeekOfYear : \(calendar.component(.yearForWeekOfYear, from: date))") } var calendar = Calendar(identifier: .gregorian) // 西暦カレンダーを生成 let date = calendar.date(from: DateComponents(year: 2022, month: 1, day: 1)) // 2022/1/1のDate型インスタンス生成 print("*** 米国地域(Locale = \"en_US\") ***") calendar.locale = Locale(identifier: "en_US") showWeekInfo(calendar, date!) print("\n*** フランス地域(Locale = \"fr_Fr\") ***") calendar.locale = Locale(identifier: "fr_FR") showWeekInfo(calendar, date!) |
出力結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
*** 米国地域(Locale = "en_US") *** firstWeekday : 1 minimumDaysInFirstWeek : 1 weekOfMonth : 1 weekOfYear : 1 yearForWeekOfYear : 2022 *** フランス地域(Locale = "fr_Fr") *** firstWeekday : 2 minimumDaysInFirstWeek : 4 weekOfMonth : 0 weekOfYear : 52 yearForWeekOfYear : 2021 |
国際規格(ISO8601)に準拠する
Calendar生成時に、iso8601を指定すると国際規格に準拠したプロパティ(firstWeekday = 2, minimumDaysInFirstWeek = 4)が初期値として設定されます。
この時、カスタムで個別の変更は可能ですが、Localeを設定し直すと設定した地域に関係なく再び初期値(国際規格)に戻ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import Foundation /// 週番号関連情報の表示 /// - Parameters: /// - calendar: カレンダー /// - date: 対象日付 func showWeekInfo(_ calendar: Calendar) { print("firstWeekday : \(calendar.firstWeekday)") print("minimumDaysInFirstWeek : \(calendar.minimumDaysInFirstWeek)") } var calendar = Calendar(identifier: .iso8601) // 国際規格カレンダーを生成 print("*** 初期値 → 国際規格(ISO8601)に準拠***") showWeekInfo(calendar) print("\n*** 米国地域(Locale = \"en_US\") → 国際規格と異なるLocaleを設定しても初期値のまま ***") calendar.locale = Locale(identifier: "en_US") showWeekInfo(calendar) print("\n*** 週の定義をカスタム設定 → 個別設定は可能 ***") calendar.firstWeekday = 1 calendar.minimumDaysInFirstWeek = 1 showWeekInfo(calendar) print("\n*** 米国地域(Locale = \"en_US\") → Localeを設定すると初期値に戻る***") calendar.locale = Locale(identifier: "en_US") showWeekInfo(calendar) |
出力結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
*** 初期値 → 国際規格(ISO8601)に準拠*** firstWeekday : 2 minimumDaysInFirstWeek : 4 *** 米国地域(Locale = "en_US") → 国際規格と異なるLocaleを設定しても初期値のまま *** firstWeekday : 2 minimumDaysInFirstWeek : 4 *** 週の定義をカスタム設定 → 個別設定は可能 *** firstWeekday : 1 minimumDaysInFirstWeek : 1 *** 米国地域(Locale = "en_US") → Localeを設定すると初期値に戻る*** firstWeekday : 2 minimumDaysInFirstWeek : 4 |
週の定義をカスタムで変更する場合の注意点
Calendar.firstWeekdayとCalendar.minimumDaysInFirstWeekへの値設定で、週の定義を任意に変更できます。
注意点として、Calendar.firstWeekdayを設定した後に、必ずCalendar.minimumDaysInFirstWeekも値を設定し直してください。
下記例のように、Calendar.firstWeekdayのみに値を設定、あるいは設定の順番を逆にした場合、週番号が正しく算出されません。
理由は不明ですが、おそらくなんらかのバグと思われます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import Foundation /// 週番号関連情報の表示 /// - Parameters: /// - calendar: カレンダー /// - date: 対象日付 func showWeekInfo(_ calendar: Calendar, _ date: Date) { print("firstWeekday : \(calendar.firstWeekday)") print("minimumDaysInFirstWeek : \(calendar.minimumDaysInFirstWeek)") print("weekOfMonth : \(calendar.component(.weekOfMonth, from: date))") print("weekOfYear : \(calendar.component(.weekOfYear, from: date))") print("yearForWeekOfYear : \(calendar.component(.yearForWeekOfYear, from: date))") } var calendar = Calendar(identifier: .gregorian) // 西暦カレンダーを生成 let date = calendar.date(from: DateComponents(year: 2022, month: 1, day: 1)) // 2022/1/1のDate型インスタンス生成 print("*** 米国地域(Locale = \"en_US\") ***") calendar.locale = Locale(identifier: "en_US") showWeekInfo(calendar, date!) print("\n*** 週の定義をカスタム設定 ***") calendar.firstWeekday = 2 calendar.minimumDaysInFirstWeek = 4 showWeekInfo(calendar, date!) print("\n*** 週番号が正しく算出されない ***") calendar.firstWeekday = 2 //calendar.minimumDaysInFirstWeek = 4 showWeekInfo(calendar, date!) |
出力結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
*** 米国地域(Locale = "en_US") *** firstWeekday : 1 minimumDaysInFirstWeek : 1 weekOfMonth : 1 weekOfYear : 1 yearForWeekOfYear : 2022 *** 週の定義をカスタム設定 *** firstWeekday : 2 minimumDaysInFirstWeek : 4 weekOfMonth : 0 weekOfYear : 52 yearForWeekOfYear : 2021 *** 週番号が正しく算出されない *** firstWeekday : 2 minimumDaysInFirstWeek : 4 weekOfMonth : 1 weekOfYear : 1 yearForWeekOfYear : 2022 |