Open davedelong opened 6 months ago
In terms of fixing this, I would suggest looking at the incoming DateComponents
and determining its overall granularity: nothing on my DateComponents is more granular than a week, so it strikes me as unusual that the default behavior is to fully set the fields on the UCalendar
all the way down to the milliseconds.
Shouldn't the code only be setting the UCalendar
fields that correspond to the specified components in the DateComponents
?
Indeed, this works as expected:
for (int32_t week = 1; week <= 5; week++) {
ucal_clear(ucalendar);
ucal_set(ucalendar, UCAL_YEAR, 2024);
ucal_set(ucalendar, UCAL_MONTH, 0);
ucal_set(ucalendar, UCAL_WEEK_OF_MONTH, week);
UDate udate = ucal_getMillis(ucalendar, &error);
NSDate *d = [NSDate dateWithTimeIntervalSince1970:udate / 1000];
printf("%s\n", d.debugDescription.UTF8String);
}
Foundation already conditionally resets fields on the UCalendar
based on what's in the incoming DateComponents
… why does it also hard-code certain values?
I was trying to iterate through all the weeks in a month, like so:
However, this printed some unexpected results:
After some digging into the implementation, I discovered that the
date(from:)
method is incorrectly setting theUCAL_DAY_OF_MONTH
field on the clearedUCalendar
, which is messing up the calculation.I verified this by testing the logic myself:
When the
UCAL_DAY_OF_MONTH
field is set, this prints:When the line is commented out, it prints:
Setting the
UCAL_DAY_OF_MONTH
field on theUCalendar
causes operations around finding the weekOfMonth and weekOfYear to fail and return the first week of the month/year, instead of the desired week.