in CoreFoundation/Locale.subproj/CFCalendar.c [2533:2740]
static CFRange __CFCalendarGetRangeOfUnit3(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
if (!calendar->_cal) {
__CFCalendarSetupCal(calendar);
if (!calendar->_cal) {
return CFRangeMake(kCFNotFound, kCFNotFound);
}
}
#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (biggerUnit) {
case kCFCalendarUnitCalendar:
case kCFCalendarUnitTimeZone:
case kCFCalendarUnitWeekdayOrdinal:
case kCFCalendarUnitNanosecond:
return CFRangeMake(kCFNotFound, kCFNotFound);
}
#pragma GCC diagnostic pop // See 10693376
#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (smallerUnit) {
case kCFCalendarUnitWeekday:
switch (biggerUnit) {
case kCFCalendarUnitSecond:
case kCFCalendarUnitMinute:
case kCFCalendarUnitHour:
case kCFCalendarUnitDay:
case kCFCalendarUnitWeekday:
return CFRangeMake(kCFNotFound, kCFNotFound);
}
return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
case kCFCalendarUnitHour:
switch (biggerUnit) {
case kCFCalendarUnitSecond:
case kCFCalendarUnitMinute:
case kCFCalendarUnitHour:
return CFRangeMake(kCFNotFound, kCFNotFound);
}
return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
case kCFCalendarUnitMinute:
switch (biggerUnit) {
case kCFCalendarUnitSecond:
case kCFCalendarUnitMinute:
return CFRangeMake(kCFNotFound, kCFNotFound);
}
return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
case kCFCalendarUnitSecond:
switch (biggerUnit) {
case kCFCalendarUnitSecond:
return CFRangeMake(kCFNotFound, kCFNotFound);
}
return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
case kCFCalendarUnitNanosecond:
return CFCalendarGetMaximumRangeOfUnit(calendar, smallerUnit);
}
#pragma GCC diagnostic pop // See 10693376
#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (biggerUnit) {
case kCFCalendarUnitEra:
// assume it cycles through every possible combination in an era
// at least once; this is a little dodgy for the Japanese calendar
// but this calculation isn't terribly useful either
switch (smallerUnit) {
case kCFCalendarUnitYear: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitYear);
case kCFCalendarUnitQuarter: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitQuarter);
case kCFCalendarUnitMonth: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitMonth);
case kCFCalendarUnitWeek_Deprecated: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitWeek_Deprecated);
case kCFCalendarUnitWeekOfYear: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitWeekOfYear);
case kCFCalendarUnitWeekOfMonth: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitWeekOfMonth);
case kCFCalendarUnitDay: return CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitDay);
case kCFCalendarUnitWeekdayOrdinal: {
CFRange r = CFCalendarGetMaximumRangeOfUnit(calendar, kCFCalendarUnitDay);
return CFRangeMake(1, (r.location + r.length - 1 + 6) / 7);
}
}
break;
case kCFCalendarUnitYear:
switch (smallerUnit) {
case kCFCalendarUnitQuarter:
case kCFCalendarUnitMonth:
case kCFCalendarUnitWeekOfYear:
case kCFCalendarUnitWeek_Deprecated: algorithmA: {
CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
CFAbsoluteTime start = 0.0;
CFTimeInterval ti = 0.0;
Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &start, &ti);
if (!b) return result;
CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, biggerUnit, start + 0.1);
if (kCFNotFound == ord1) return result;
CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, biggerUnit, start + ti - 0.1);
if (kCFNotFound == ord2) return result;
return CFRangeMake(ord1, ord2 + 1 - ord1);
}
case kCFCalendarUnitWeekOfMonth:
case kCFCalendarUnitDay:
case kCFCalendarUnitWeekdayOrdinal: algorithmB: {
CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
CFAbsoluteTime start = 0.0;
CFTimeInterval ti = 0.0;
Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &start, &ti);
if (!b) return result;
CFIndex counter = 15; // stopgap in case something goes wrong
CFAbsoluteTime end = start + ti - 1.0;
CFAbsoluteTime current = start + 1.0;
do {
CFAbsoluteTime startM = 0.0;
CFTimeInterval tiM = 0.0;
b = CFCalendarGetTimeRangeOfUnit(calendar, kCFCalendarUnitMonth, current, &startM, &tiM);
if (!b) return result;
CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, startM + 0.1);
if (kCFNotFound == ord1) return result;
CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, startM + tiM - 0.1);
if (kCFNotFound == ord2) return result;
if ((kCFNotFound == result.location) || (kCFNotFound == result.length)) {
result = CFRangeMake(ord1, ord2 + 1 - ord1);
} else {
CFIndex mn = result.location;
if (ord1 < mn) mn = ord1;
result.location = mn;
result.length += ord2;
}
counter--;
current = startM + tiM + 1.0;
} while (current < end && 0 < counter);
return result;
}
}
break;
case kCFCalendarUnitYearForWeekOfYear:
switch (smallerUnit) {
case kCFCalendarUnitQuarter:
case kCFCalendarUnitMonth:
case kCFCalendarUnitWeekOfYear:
case kCFCalendarUnitWeek_Deprecated:
goto algorithmA; // some of these are going to return (kCFNotFound, kCFNotFound)
case kCFCalendarUnitWeekOfMonth:
break;
case kCFCalendarUnitDay:
case kCFCalendarUnitWeekdayOrdinal:
goto algorithmB; // this question is odd to ask
}
break;
case kCFCalendarUnitQuarter:
switch (smallerUnit) {
case kCFCalendarUnitMonth:
case kCFCalendarUnitWeekOfYear:
case kCFCalendarUnitWeek_Deprecated: algorithmC: {
CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
CFAbsoluteTime start = 0.0;
CFTimeInterval ti = 0.0;
Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &start, &ti);
if (!b) return result;
CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitYear, start + 0.1);
if (kCFNotFound == ord1) return result;
CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitYear, start + ti - 0.1);
if (kCFNotFound == ord2) return result;
return CFRangeMake(ord1, ord2 + 1 - ord1);
}
case kCFCalendarUnitWeekOfMonth:
case kCFCalendarUnitDay:
case kCFCalendarUnitWeekdayOrdinal:
goto algorithmB;
}
break;
case kCFCalendarUnitMonth:
switch (smallerUnit) {
case kCFCalendarUnitWeekOfYear:
case kCFCalendarUnitWeek_Deprecated:
goto algorithmC;
case kCFCalendarUnitWeekOfMonth:
case kCFCalendarUnitDay:
case kCFCalendarUnitWeekdayOrdinal:
goto algorithmA;
}
break;
case kCFCalendarUnitWeekOfYear:
break;
case kCFCalendarUnitWeekOfMonth:
case kCFCalendarUnitWeek_Deprecated:
#pragma GCC diagnostic push // See 10693376
#pragma GCC diagnostic ignored "-Wswitch-enum"
switch (smallerUnit) {
case kCFCalendarUnitDay: {
CFRange result = CFRangeMake(kCFNotFound, kCFNotFound);
CFAbsoluteTime startW = 0.0, startM = 0.0;
CFTimeInterval tiW = 0.0, tiM = 0.0;
Boolean b = CFCalendarGetTimeRangeOfUnit(calendar, biggerUnit, at, &startW, &tiW);
if (!b) return result;
b = CFCalendarGetTimeRangeOfUnit(calendar, kCFCalendarUnitMonth, at, &startM, &tiM);
if (!b) return result;
CFAbsoluteTime start = (startW < startM) ? (startM) : (startW);
CFAbsoluteTime end = (startW + tiW < startM + tiM) ? (startW + tiW) : (startM + tiM);
CFIndex ord1 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, start + 0.1);
if (kCFNotFound == ord1) return result;
CFIndex ord2 = CFCalendarGetOrdinalityOfUnit(calendar, smallerUnit, kCFCalendarUnitMonth, end - 0.1);
if (kCFNotFound == ord2) return result;
return CFRangeMake(ord1, ord2 + 1 - ord1);
}
}
#pragma GCC diagnostic pop // See 10693376
break;
}
#pragma GCC diagnostic pop // See 10693376
return CFRangeMake(kCFNotFound, kCFNotFound);
}