When I run this in a playground:
var meDate = Calendar.current.date(from: DateComponents(year: 2024, hour: 7, weekday: 3, weekdayOrdinal: 2))!
print(meDate)
I see:
2024-01-09 15:00:00 +0000
This seems correct to me.
- jan 9th is the second Tuesday in 2024
- I'm in the pacific TZ, 07:00 PDT matches 15:00GMT
But then I do this:
meDate = Calendar.current.date(bySetting: .weekday, value: 4, of: meDate)!
print(meDate)
and I see: 2024-01-10 08:00:00 +0000
I would have expected my hour value (7PST/15GMT) to have been preserved. Is there a way I can update weekday, but not lose my hour?
As explained in doc, Changing a component’s value often will require higher or coupled components to change as well… The exact behavior of this method is implementation-defined:
Changing a component’s value often will require higher or coupled components to change as well. For example, setting the Weekday to Thursday usually will require the Day component to change its value, and possibly the Month and Year as well. If no such time exists, the next available time is returned (which could, for example, be in a different day, week, month, … than the nominal target date). Setting a component to something which would be inconsistent forces other components to change; for example, setting the Weekday to Thursday probably shifts the Day and possibly Month and Year. The exact behavior of this method is implementation-defined. For example, if changing the weekday to Thursday, does that move forward to the next, backward to the previous, or to the nearest Thursday? The algorithm will try to produce a result which is in the next-larger component to the one given (there’s a table of this mapping at the top of this document). So for the “set to Thursday” example, find the Thursday in the Week in which the given date resides (which could be a forwards or backwards move, and not necessarily the nearest Thursday). For more control over the exact behavior, use nextDate(after:matching:matchingPolicy:behavior:direction:).
Note that if you set the weekday to the same value (3), results are kept the same
meDate = Calendar.current.date(bySetting: .weekday, value: 3, of: meDate)!
Interesting discussion here: https://forums.swift.org/t/date-from-date-components-is-incorrect-after-changing-month/54192/5