I'm working on a calendar view (Cocoa macOS app) that shows the current month. When I try to calculate the week number for a given date, I get different results based on the calendar and locale.
For January 1st, 2021, some calls return week 0
, others week 1
:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
let jan2021 = formatter.date(from: "2021-01-01")!
var deCalendar = Calendar(identifier: .gregorian)
deCalendar.locale = Locale(identifier: "de_de")
var usCalendar = Calendar(identifier: .gregorian)
usCalendar.locale = Locale(identifier: "en_us")
var deIsoCalendar = Calendar(identifier: .iso8601)
deIsoCalendar.locale = Locale(identifier: "de_de")
var usIso = Calendar(identifier: .iso8601)
usIso.locale = Locale(identifier: "en_us")
deCalendar.component(.weekOfMonth, from: jan2021) // 0
deIsoCalendar.component(.weekOfMonth, from: jan2021) // 0
usCalendar.component(.weekOfMonth, from: jan2021) // 1 ??
usIso.component(.weekOfMonth, from: jan2021) // 0
January 1st, 2021 is a Friday so I would expect that the "week of month" is 0
(or 1
, depending on if the particular API is zero-based or not).
For February 1st, 2021, which is a Monday, all calls above return week 1
!
Just for kicks, Jan 31st, 2021: the us/gregorian calendar returns "week 6", all others "week 4".
Bug?, feature?, what am I missing?
For reference:
It depends on 2 things in a particular calendar:
minimumDaysInFirstWeek
firstWeekday
If you look at calendars you used
deCalendar: minimumDaysInFirstWeek=4, firstWeekday=2
deIsoCalendar: minimumDaysInFirstWeek=4, firstWeekday=2
usCalendar: minimumDaysInFirstWeek=1, firstWeekday=1
usIso: minimumDaysInFirstWeek=4, firstWeekday=2
So 3 calendars require at least 4 days to consider it a first week, and they start from Monday (day 2 in US locale). Hence 3-day week is not going to be considered a first week.
Calendar 3 has only 1 day requirement for the week, hence even 1-day is a week.