Boolean CFCalendarGetTimeRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit unit, CFAbsoluteTime at, CFAbsoluteTime *startp, CFTimeInterval *tip) {
    CF_OBJC_FUNCDISPATCH4(CFCalendarGetTypeID(), Boolean, calendar, "_rangeOfUnit:startTime:interval:forAT:", unit, startp, tip, at);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (kCFCalendarUnitWeekdayOrdinal == unit) return false;
    if (kCFCalendarUnitWeekday == unit) unit = kCFCalendarUnitDay;
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) {
        ucal_clear(calendar->_cal);
        __CFCalendarSetToFirstInstant(calendar, unit, at);
        UErrorCode status = U_ZERO_ERROR;
        UDate start = ucal_getMillis(calendar->_cal, &status);
	UCalendarDateFields field = __CFCalendarGetICUFieldCode(unit);
	ucal_add(calendar->_cal, field, 1, &status);
        UDate end = ucal_getMillis(calendar->_cal, &status);
	if (end == start && kCFCalendarUnitEra == unit) {
            // ICU refuses to do the addition, probably because we are
            // at the limit of UCAL_ERA.  Use alternate strategy.
            CFIndex limit = ucal_getLimit(calendar->_cal, UCAL_YEAR, UCAL_MAXIMUM, &status);
            if (100000 < limit) limit = 100000;
            ucal_add(calendar->_cal, UCAL_YEAR, limit, &status);
	    end = ucal_getMillis(calendar->_cal, &status);
	}
	if (U_SUCCESS(status)) {
	    if (startp) *startp = (double)start / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
	    if (tip) *tip = (double)(end - start) / 1000.0;
	    return true;
	}
    }

    return false;
}
Example #2
0
void CFCalendarSetFirstWeekday(CFCalendarRef calendar, CFIndex wkdy) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setFirstWeekday:wkdy);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) {
	ucal_setAttribute(calendar->_cal, UCAL_FIRST_DAY_OF_WEEK, wkdy);
    }
}
Example #3
0
CFIndex CFCalendarGetFirstWeekday(CFCalendarRef calendar) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFIndex, calendar, firstWeekday);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) {
	return ucal_getAttribute(calendar->_cal, UCAL_FIRST_DAY_OF_WEEK);
    }
    return -1;
}
CFIndex CFCalendarGetOrdinalityOfUnit(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
    CFIndex result = kCFNotFound;
    if (!__validUnits(smallerUnit, biggerUnit)) return result;
    CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), CFIndex, calendar, "_ordinalityOfUnit:inUnit:forAT:", smallerUnit, biggerUnit, at);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) {
	UErrorCode status = U_ZERO_ERROR;
	ucal_clear(calendar->_cal);
	if (kCFCalendarUnitWeek == smallerUnit && kCFCalendarUnitYear == biggerUnit) {
	    UDate udate = floor((at + kCFAbsoluteTimeIntervalSince1970) * 1000.0);
	    ucal_setMillis(calendar->_cal, udate, &status);
	    int32_t val = ucal_get(calendar->_cal, UCAL_WEEK_OF_YEAR, &status);
	    return val;
	} else if (kCFCalendarUnitWeek == smallerUnit && kCFCalendarUnitMonth == biggerUnit) {
	    UDate udate = floor((at + kCFAbsoluteTimeIntervalSince1970) * 1000.0);
	    ucal_setMillis(calendar->_cal, udate, &status);
	    int32_t val = ucal_get(calendar->_cal, UCAL_WEEK_OF_MONTH, &status);
	    return val;
	}
	UCalendarDateFields smallField = __CFCalendarGetICUFieldCode(smallerUnit);
	// Set calendar to first instant of big unit
	__CFCalendarSetToFirstInstant(calendar, biggerUnit, at);
	UDate curr = ucal_getMillis(calendar->_cal, &status);
        UDate goal = floor((at + kCFAbsoluteTimeIntervalSince1970) * 1000.0);
	result = 1;
	const int multiple_table[] = {0, 0, 16, 19, 24, 26, 24, 28, 14, 14, 14};
	int multiple = (1 << multiple_table[flsl(smallerUnit) - 1]);
	Boolean divide = false, alwaysDivide = false;
	while (curr < goal) {
	    ucal_add(calendar->_cal, smallField, multiple, &status);
	    UDate newcurr = ucal_getMillis(calendar->_cal, &status);
	    if (curr < newcurr && newcurr <= goal) {
		result += multiple;
		curr = newcurr;
	    } else {
		// Either newcurr is going backwards, or not making
		// progress, or has overshot the goal; reset date
		// and try smaller multiples.
		ucal_setMillis(calendar->_cal, curr, &status);
		divide = true;
		// once we start overshooting the goal, the add at
		// smaller multiples will succeed at most once for
		// each multiple, so we reduce it every time through
		// the loop.
		if (goal < newcurr) alwaysDivide = true;
	    }
	    if (divide) {
		multiple = multiple / 2;
		if (0 == multiple) break;
		divide = alwaysDivide;
	    }
	}
    }
    return result;
}
Example #5
0
void CFCalendarSetTimeZone(CFCalendarRef calendar, CFTimeZoneRef tz) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setTimeZone:tz);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (tz) __CFGenericValidateType(tz, CFTimeZoneGetTypeID());
    if (tz != calendar->_tz) {
	CFRelease(calendar->_tz);
	calendar->_tz = tz ? (CFTimeZoneRef)CFRetain(tz) : CFTimeZoneCopyDefault();
        if (calendar->_cal) __CFCalendarZapCal(calendar);
    }
}
Example #6
0
void CFCalendarSetLocale(CFCalendarRef calendar, CFLocaleRef locale) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setLocale:locale);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    __CFGenericValidateType(locale, CFLocaleGetTypeID());
    CFStringRef localeID = CFLocaleGetIdentifier(locale);
    if (localeID != calendar->_localeID) {
	CFRelease(calendar->_localeID);
	CFRetain(localeID);
	calendar->_localeID = localeID;
        if (calendar->_cal) __CFCalendarZapCal(calendar);
    }
}
Example #7
0
CFDateRef CFCalendarCopyGregorianStartDate(CFCalendarRef calendar) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFDateRef, calendar, _gregorianStartDate);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    UErrorCode status = U_ZERO_ERROR;
    UDate udate = calendar->_cal ? ucal_getGregorianChange(calendar->_cal, &status) : 0;
    if (calendar->_cal && U_SUCCESS(status)) {
	CFAbsoluteTime at = (double)udate / 1000.0 - kCFAbsoluteTimeIntervalSince1970;
	return CFDateCreate(CFGetAllocator(calendar), at);
    }
    return NULL;
}
Boolean CFCalendarAddComponents(CFCalendarRef calendar, /* inout */ CFAbsoluteTime *atp, CFOptionFlags options, const char *componentDesc, ...) {
    va_list args;
    va_start(args, componentDesc);
    CF_OBJC_FUNCDISPATCH4(CFCalendarGetTypeID(), Boolean, calendar, "_addComponents::::", atp, options, componentDesc, args);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    int idx, cnt = strlen((char *)componentDesc);
    STACK_BUFFER_DECL(int, vector, cnt);
    for (idx = 0; idx < cnt; idx++) {
	int arg = va_arg(args, int);
	vector[idx] = arg;
    }
    va_end(args);
    return _CFCalendarAddComponentsV(calendar, atp, options, componentDesc, vector, cnt);    
}
Boolean CFCalendarDecomposeAbsoluteTime(CFCalendarRef calendar, CFAbsoluteTime at, const char *componentDesc, ...) {
    va_list args;
    va_start(args, componentDesc);
    CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), Boolean, calendar, "_decomposeAbsoluteTime:::", at, componentDesc, args);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    int idx, cnt = strlen((char *)componentDesc);
    STACK_BUFFER_DECL(int *, vector, cnt);
    for (idx = 0; idx < cnt; idx++) {
	int *arg = va_arg(args, int *);
	vector[idx] = arg;
    }
    va_end(args);
    return _CFCalendarDecomposeAbsoluteTimeV(calendar, at, componentDesc, vector, cnt);
}
Boolean CFCalendarGetComponentDifference(CFCalendarRef calendar, CFAbsoluteTime startingAT, CFAbsoluteTime resultAT, CFOptionFlags options, const char *componentDesc, ...) {
    va_list args;
    va_start(args, componentDesc);
    CF_OBJC_FUNCDISPATCH5(CFCalendarGetTypeID(), Boolean, calendar, "_diffComponents:::::", startingAT, resultAT, options, componentDesc, args);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    int idx, cnt = strlen((char *)componentDesc);
    STACK_BUFFER_DECL(int *, vector, cnt);
    for (idx = 0; idx < cnt; idx++) {
	int *arg = va_arg(args, int *);
	vector[idx] = arg;
    }
    va_end(args);
    Boolean ret = _CFCalendarGetComponentDifferenceV(calendar, startingAT, resultAT, options, componentDesc, vector, cnt);
    return ret;
}
Example #11
0
CFCalendarRef CFCalendarCreateWithIdentifier(CFAllocatorRef allocator, CFStringRef identifier) {
    if (allocator == NULL) allocator = __CFGetDefaultAllocator();
    __CFGenericValidateType(allocator, CFAllocatorGetTypeID());
    __CFGenericValidateType(identifier, CFStringGetTypeID());
    // return NULL until Chinese calendar is available
    if (identifier != kCFGregorianCalendar && identifier != kCFBuddhistCalendar && identifier != kCFJapaneseCalendar && identifier != kCFIslamicCalendar && identifier != kCFIslamicCivilCalendar && identifier != kCFHebrewCalendar) {
//    if (identifier != kCFGregorianCalendar && identifier != kCFBuddhistCalendar && identifier != kCFJapaneseCalendar && identifier != kCFIslamicCalendar && identifier != kCFIslamicCivilCalendar && identifier != kCFHebrewCalendar && identifier != kCFChineseCalendar) {
	if (CFEqual(kCFGregorianCalendar, identifier)) identifier = kCFGregorianCalendar;
	else if (CFEqual(kCFBuddhistCalendar, identifier)) identifier = kCFBuddhistCalendar;
	else if (CFEqual(kCFJapaneseCalendar, identifier)) identifier = kCFJapaneseCalendar;
	else if (CFEqual(kCFIslamicCalendar, identifier)) identifier = kCFIslamicCalendar;
	else if (CFEqual(kCFIslamicCivilCalendar, identifier)) identifier = kCFIslamicCivilCalendar;
	else if (CFEqual(kCFHebrewCalendar, identifier)) identifier = kCFHebrewCalendar;
//	else if (CFEqual(kCFChineseCalendar, identifier)) identifier = kCFChineseCalendar;
	else return NULL;
    }
    struct __CFCalendar *calendar = NULL;
    uint32_t size = sizeof(struct __CFCalendar) - sizeof(CFRuntimeBase);
    calendar = (struct __CFCalendar *)_CFRuntimeCreateInstance(allocator, CFCalendarGetTypeID(), size, NULL);
    if (NULL == calendar) {
	return NULL;
    }
    calendar->_identifier = (CFStringRef)CFRetain(identifier);
    calendar->_locale = NULL;
    calendar->_localeID = CFLocaleGetIdentifier(CFLocaleGetSystem());
    calendar->_tz = CFTimeZoneCopyDefault();
    calendar->_cal = NULL;
    return (CFCalendarRef)calendar;
}
CFRange CFCalendarGetMaximumRangeOfUnit(CFCalendarRef calendar, CFCalendarUnit unit) {
    CF_OBJC_FUNCDISPATCH1(CFCalendarGetTypeID(), CFRange, calendar, "_maximumRangeOfUnit:", unit);
    CFRange range = {kCFNotFound, kCFNotFound};
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) {
	ucal_clear(calendar->_cal);
	UCalendarDateFields field = __CFCalendarGetICUFieldCode(unit);
	UErrorCode status = U_ZERO_ERROR;
	range.location = ucal_getLimit(calendar->_cal, field, UCAL_MINIMUM, &status);
	range.length = ucal_getLimit(calendar->_cal, field, UCAL_MAXIMUM, &status) - range.location + 1;
	if (UCAL_MONTH == field) range.location++;
	if (100000 < range.length) range.length = 100000;
    }
    return range;
}
Example #13
0
void CFCalendarSetGregorianStartDate(CFCalendarRef calendar, CFDateRef date) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, _setGregorianStartDate:date);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (date) __CFGenericValidateType(date, CFDateGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (!calendar->_cal) return;
    if (!date) {
	UErrorCode status = U_ZERO_ERROR;
	UCalendar *cal = __CFCalendarCreateUCalendar(calendar->_identifier, calendar->_localeID, calendar->_tz);
	UDate udate = cal ? ucal_getGregorianChange(cal, &status) : 0;
	if (cal && U_SUCCESS(status)) {
	    status = U_ZERO_ERROR;
	    if (calendar->_cal) ucal_setGregorianChange(calendar->_cal, udate, &status);
	}
	if (cal) ucal_close(cal);
    } else {
	CFAbsoluteTime at = CFDateGetAbsoluteTime(date);
	UDate udate = (at + kCFAbsoluteTimeIntervalSince1970) * 1000.0;
	UErrorCode status = U_ZERO_ERROR;
	if (calendar->_cal) ucal_setGregorianChange(calendar->_cal, udate, &status);
    }
}
static CFRange __CFCalendarGetRangeOfUnit1(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
    CFRange range = {kCFNotFound, kCFNotFound};
    if (!__validUnits(smallerUnit, biggerUnit)) return range;
    CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), CFRange, calendar, "_rangeOfUnit:inUnit:forAT:", smallerUnit, biggerUnit, at);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) {
	int32_t dow = -1;
	ucal_clear(calendar->_cal);
	UCalendarDateFields smallField = __CFCalendarGetICUFieldCode(smallerUnit);
	UCalendarDateFields bigField = __CFCalendarGetICUFieldCode(biggerUnit);
	if (kCFCalendarUnitWeekdayOrdinal == smallerUnit) {
	    UErrorCode status = U_ZERO_ERROR;
	    UDate udate = floor((at + kCFAbsoluteTimeIntervalSince1970) * 1000.0);
	    ucal_setMillis(calendar->_cal, udate, &status);
	    dow = ucal_get(calendar->_cal, UCAL_DAY_OF_WEEK, &status);
	}
	// Set calendar to first instant of big unit
	__CFCalendarSetToFirstInstant(calendar, biggerUnit, at);
	UErrorCode status = U_ZERO_ERROR;
	UDate start = ucal_getMillis(calendar->_cal, &status);
	if (kCFCalendarUnitWeek == biggerUnit) {
	    range.location = ucal_get(calendar->_cal, smallField, &status);
	    if (kCFCalendarUnitMonth == smallerUnit) range.location++;
	} else {
	    range.location = (kCFCalendarUnitHour == smallerUnit || kCFCalendarUnitMinute == smallerUnit || kCFCalendarUnitSecond == smallerUnit) ? 0 : 1;
	}
	// Set calendar to first instant of next value of big unit
	if (UCAL_ERA == bigField) {
	    // ICU refuses to do the addition, probably because we are
	    // at the limit of UCAL_ERA.  Use alternate strategy.
	    CFIndex limit = ucal_getLimit(calendar->_cal, UCAL_YEAR, UCAL_MAXIMUM, &status);
	    if (100000 < limit) limit = 100000;
	    ucal_add(calendar->_cal, UCAL_YEAR, limit, &status);
	} else {
	    ucal_add(calendar->_cal, bigField, 1, &status);
	}
	if (kCFCalendarUnitWeek == smallerUnit && kCFCalendarUnitYear == biggerUnit) {
	    ucal_add(calendar->_cal, UCAL_SECOND, -1, &status);
	    range.length = ucal_get(calendar->_cal, UCAL_WEEK_OF_YEAR, &status);
	    while (1 == range.length) {
		ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, -1, &status);
		range.length = ucal_get(calendar->_cal, UCAL_WEEK_OF_YEAR, &status);
	    }
	    range.location = 1;
	    return range;
	} else if (kCFCalendarUnitWeek == smallerUnit && kCFCalendarUnitMonth == biggerUnit) {
	    ucal_add(calendar->_cal, UCAL_SECOND, -1, &status);
	    range.length = ucal_get(calendar->_cal, UCAL_WEEK_OF_YEAR, &status);
	    range.location = 1;
	    return range;
	}
	UDate goal = ucal_getMillis(calendar->_cal, &status);
	// Set calendar back to first instant of big unit
	ucal_setMillis(calendar->_cal, start, &status);
	if (kCFCalendarUnitWeekdayOrdinal == smallerUnit) {
	    // roll day forward to first 'dow'
	    while (ucal_get(calendar->_cal, (kCFCalendarUnitMonth == biggerUnit) ? UCAL_WEEK_OF_MONTH : UCAL_WEEK_OF_YEAR, &status) != 1) {
		ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, 1, &status);
	    }
	    while (ucal_get(calendar->_cal, UCAL_DAY_OF_WEEK, &status) != dow) {
		ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, 1, &status);
	    }
	    start = ucal_getMillis(calendar->_cal, &status);
	    goal -= 1000;
	    range.location = 1;  // constant here works around ICU -- see 3948293
	}
	UDate curr = start;
	range.length = 	(kCFCalendarUnitWeekdayOrdinal == smallerUnit) ? 1 : 0;
	const int multiple_table[] = {0, 0, 16, 19, 24, 26, 24, 28, 14, 14, 14};
	int multiple = (1 << multiple_table[flsl(smallerUnit) - 1]);
	Boolean divide = false, alwaysDivide = false;
	while (curr < goal) {
	    ucal_add(calendar->_cal, smallField, multiple, &status);
	    UDate newcurr = ucal_getMillis(calendar->_cal, &status);
	    if (curr < newcurr && newcurr <= goal) {
		range.length += multiple;
		curr = newcurr;
	    } else {
		// Either newcurr is going backwards, or not making
		// progress, or has overshot the goal; reset date
		// and try smaller multiples.
		ucal_setMillis(calendar->_cal, curr, &status);
		divide = true;
		// once we start overshooting the goal, the add at
		// smaller multiples will succeed at most once for
		// each multiple, so we reduce it every time through
		// the loop.
		if (goal < newcurr) alwaysDivide = true;
	    }
	    if (divide) {
		multiple = multiple / 2;
		if (0 == multiple) break;
		divide = alwaysDivide;
	    }
	}
    }
    return range;
}
Example #15
0
CFLocaleRef CFCalendarCopyLocale(CFCalendarRef calendar) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFLocaleRef, calendar, _copyLocale);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    return (CFLocaleRef)CFLocaleCreate(kCFAllocatorSystemDefault, calendar->_localeID);
}
Example #16
0
void CFCalendarSetMinimumDaysInFirstWeek(CFCalendarRef calendar, CFIndex mwd) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), void, calendar, setMinimumDaysInFirstWeek:mwd);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) ucal_setAttribute(calendar->_cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK, mwd);
}
Example #17
0
CFIndex CFCalendarGetMinimumDaysInFirstWeek(CFCalendarRef calendar) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFIndex, calendar, minimumDaysInFirstWeek);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    return calendar->_cal ? ucal_getAttribute(calendar->_cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK) : -1;
}
static CFRange __CFCalendarGetRangeOfUnit2(CFCalendarRef calendar, CFCalendarUnit smallerUnit, CFCalendarUnit biggerUnit, CFAbsoluteTime at) {
    CF_OBJC_FUNCDISPATCH3(CFCalendarGetTypeID(), CFRange, calendar, "_rangeOfUnit:inUnit:forAT:", smallerUnit, biggerUnit, at);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    CFRange range = {kCFNotFound, kCFNotFound};
    if (!calendar->_cal) __CFCalendarSetupCal(calendar);
    if (calendar->_cal) {
	switch (smallerUnit) {
	case kCFCalendarUnitSecond:
            switch (biggerUnit) {
            case kCFCalendarUnitMinute:
            case kCFCalendarUnitHour:
            case kCFCalendarUnitDay:
            case kCFCalendarUnitWeekday:
            case kCFCalendarUnitWeek:
            case kCFCalendarUnitMonth:
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		// goto calculate;
                range.location = 0;
                range.length = 60;
		break;
            }
	    break;
	case kCFCalendarUnitMinute:
            switch (biggerUnit) {
            case kCFCalendarUnitHour:
            case kCFCalendarUnitDay:
            case kCFCalendarUnitWeekday:
            case kCFCalendarUnitWeek:
            case kCFCalendarUnitMonth:
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		// goto calculate;
                range.location = 0;
                range.length = 60;
		break;
            }
	    break;
	case kCFCalendarUnitHour:
            switch (biggerUnit) {
            case kCFCalendarUnitDay:
            case kCFCalendarUnitWeekday:
            case kCFCalendarUnitWeek:
            case kCFCalendarUnitMonth:
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		// goto calculate;
                range.location = 0;
                range.length = 24;
		break;
            }
	    break;
	case kCFCalendarUnitDay:
            switch (biggerUnit) {
            case kCFCalendarUnitWeek:
            case kCFCalendarUnitMonth:
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		goto calculate;
		break;
            }
	    break;
	case kCFCalendarUnitWeekday:
            switch (biggerUnit) {
            case kCFCalendarUnitWeek:
            case kCFCalendarUnitMonth:
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		goto calculate;
		break;
            }
	    break;
	case kCFCalendarUnitWeekdayOrdinal:
            switch (biggerUnit) {
            case kCFCalendarUnitMonth:
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		goto calculate;
		break;
            }
	    break;
	case kCFCalendarUnitWeek:
            switch (biggerUnit) {
            case kCFCalendarUnitMonth:
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		goto calculate;
		break;
            }
	    break;
	case kCFCalendarUnitMonth:
            switch (biggerUnit) {
            case kCFCalendarUnitYear:
            case kCFCalendarUnitEra:
		goto calculate;
		break;
            }
	    break;
	case kCFCalendarUnitYear:
            switch (biggerUnit) {
            case kCFCalendarUnitEra:
		goto calculate;
		break;
            }
	    break;
	case kCFCalendarUnitEra:
	    break;
	}
    }
    return range;

    calculate:;
    ucal_clear(calendar->_cal);
    UCalendarDateFields smallField = __CFCalendarGetICUFieldCode(smallerUnit);
    UCalendarDateFields bigField = __CFCalendarGetICUFieldCode(biggerUnit);
    UCalendarDateFields yearField = __CFCalendarGetICUFieldCode(kCFCalendarUnitYear);
    UCalendarDateFields fieldToAdd = smallField;
    if (kCFCalendarUnitWeekday == smallerUnit) {
        fieldToAdd = __CFCalendarGetICUFieldCode(kCFCalendarUnitDay);
    }
    int32_t dow = -1;
    if (kCFCalendarUnitWeekdayOrdinal == smallerUnit) {
        UErrorCode status = U_ZERO_ERROR;
        UDate udate = floor((at + kCFAbsoluteTimeIntervalSince1970) * 1000.0);
        ucal_setMillis(calendar->_cal, udate, &status);
        dow = ucal_get(calendar->_cal, UCAL_DAY_OF_WEEK, &status);
        fieldToAdd = __CFCalendarGetICUFieldCode(kCFCalendarUnitWeek);
    }
    // Set calendar to first instant of big unit
    __CFCalendarSetToFirstInstant(calendar, biggerUnit, at);
    if (kCFCalendarUnitWeekdayOrdinal == smallerUnit) {
        UErrorCode status = U_ZERO_ERROR;
        // roll day forward to first 'dow'
        while (ucal_get(calendar->_cal, (kCFCalendarUnitMonth == biggerUnit) ? UCAL_WEEK_OF_MONTH : UCAL_WEEK_OF_YEAR, &status) != 1) {
	    ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, 1, &status);
        }
        while (ucal_get(calendar->_cal, UCAL_DAY_OF_WEEK, &status) != dow) {
	    ucal_add(calendar->_cal, UCAL_DAY_OF_MONTH, 1, &status);
        }
    }
    int32_t minSmallValue = INT32_MAX;
    int32_t maxSmallValue = INT32_MIN;
    UErrorCode status = U_ZERO_ERROR;
    int32_t bigValue = ucal_get(calendar->_cal, bigField, &status);
    for (;;) {
        int32_t smallValue = ucal_get(calendar->_cal, smallField, &status);
        if (smallValue < minSmallValue) minSmallValue = smallValue;
        if (smallValue > maxSmallValue) maxSmallValue = smallValue;
        ucal_add(calendar->_cal, fieldToAdd, 1, &status);
        if (bigValue != ucal_get(calendar->_cal, bigField, &status)) break;
        if (biggerUnit == kCFCalendarUnitEra && ucal_get(calendar->_cal, yearField, &status) > 10000) break;
	// we assume an answer for 10000 years can be extrapolated to 100000 years, to save time
    }
    status = U_ZERO_ERROR;
    range.location = minSmallValue;
    if (smallerUnit == kCFCalendarUnitMonth) range.location = 1;
    range.length = maxSmallValue - minSmallValue + 1;
    if (biggerUnit == kCFCalendarUnitEra && ucal_get(calendar->_cal, yearField, &status) > 10000) range.length = 100000;

    return range;
}
Example #19
0
CFStringRef CFCalendarGetIdentifier(CFCalendarRef calendar) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFStringRef, calendar, calendarIdentifier);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    return calendar->_identifier;
}
Example #20
0
CFTimeZoneRef CFCalendarCopyTimeZone(CFCalendarRef calendar) {
    CF_OBJC_FUNCDISPATCHV(CFCalendarGetTypeID(), CFTimeZoneRef, calendar_copyTimeZone);
    __CFGenericValidateType(calendar, CFCalendarGetTypeID());
    return (CFTimeZoneRef)CFRetain(calendar->_tz);
}