Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions Source/CFCalendar.c
Original file line number Diff line number Diff line change
Expand Up @@ -795,18 +795,79 @@ CFCalendarGetTimeRangeOfUnit (CFCalendarRef cal, CFCalendarUnit unit,
return true;
}

/* The ICU field that represents smallerUnit measured within biggerUnit. */
static UCalendarDateFields
CFCalendarCompoundField (CFCalendarUnit smaller, CFCalendarUnit bigger)
{
switch (smaller)
{
case kCFCalendarUnitDay:
case kCFCalendarUnitWeekday:
if (bigger == kCFCalendarUnitYear)
return UCAL_DAY_OF_YEAR;
if (bigger == kCFCalendarUnitWeek)
return UCAL_DAY_OF_WEEK;
return UCAL_DATE;
case kCFCalendarUnitMonth:
return UCAL_MONTH;
case kCFCalendarUnitWeek:
if (bigger == kCFCalendarUnitMonth)
return UCAL_WEEK_OF_MONTH;
return UCAL_WEEK_OF_YEAR;
case kCFCalendarUnitHour:
return UCAL_HOUR_OF_DAY;
case kCFCalendarUnitMinute:
return UCAL_MINUTE;
case kCFCalendarUnitSecond:
return UCAL_SECOND;
default:
return (UCalendarDateFields) -1;
}
}

CFRange
CFCalendarGetRangeOfUnit (CFCalendarRef cal, CFCalendarUnit smallerUnit,
CFCalendarUnit biggerUnit, CFAbsoluteTime at)
{
return CFRangeMake (kCFNotFound, kCFNotFound);
UCalendarDateFields field;
UErrorCode err = U_ZERO_ERROR;
int32_t min, max;

field = CFCalendarCompoundField (smallerUnit, biggerUnit);
if (field == (UCalendarDateFields) -1)
return CFRangeMake (kCFNotFound, kCFNotFound);

CFCalendarOpenUCalendar (cal);
ucal_setMillis (cal->_ucal, ABSOLUTETIME_TO_UDATE (at), &err);
min = ucal_getLimit (cal->_ucal, field, UCAL_ACTUAL_MINIMUM, &err);
max = ucal_getLimit (cal->_ucal, field, UCAL_ACTUAL_MAXIMUM, &err);
if (U_FAILURE (err))
return CFRangeMake (kCFNotFound, kCFNotFound);

/* ICU numbers months from zero. */
return CFRangeMake (field == UCAL_MONTH ? min + 1 : min, max - min + 1);
}

CFIndex
CFCalendarGetOrdinalityOfUnit (CFCalendarRef cal, CFCalendarUnit smallerUnit,
CFCalendarUnit biggerUnit, CFAbsoluteTime at)
{
return kCFNotFound;
UCalendarDateFields field;
UErrorCode err = U_ZERO_ERROR;
int32_t value;

field = CFCalendarCompoundField (smallerUnit, biggerUnit);
if (field == (UCalendarDateFields) -1)
return kCFNotFound;

CFCalendarOpenUCalendar (cal);
ucal_setMillis (cal->_ucal, ABSOLUTETIME_TO_UDATE (at), &err);
value = ucal_get (cal->_ucal, field, &err);
if (U_FAILURE (err))
return kCFNotFound;

/* ICU numbers months from zero. */
return field == UCAL_MONTH ? value + 1 : value;
}

static CFRange
Expand Down
41 changes: 41 additions & 0 deletions Tests/CFCalendar/ordinality.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "CoreFoundation/CFCalendar.h"
#include "CoreFoundation/CFTimeZone.h"
#include "../CFTesting.h"

/* CFCalendarGetOrdinalityOfUnit and CFCalendarGetRangeOfUnit. Times are
built directly as offsets from the reference date. */

int main (void)
{
double day = 86400.0;
CFTimeZoneRef gmt = CFTimeZoneCreateWithTimeIntervalFromGMT (NULL, 0.0);
CFCalendarRef cal = CFCalendarCreateWithIdentifier (NULL,
kCFGregorianCalendar);
CFRange r;

CFCalendarSetTimeZone (cal, gmt);

r = CFCalendarGetRangeOfUnit (cal, kCFCalendarUnitDay, kCFCalendarUnitMonth,
45 * day); /* 2001-02-15 */
PASS_CF (r.location == 1 && r.length == 28,
"The days of February 2001 range from 1 to 28.");

r = CFCalendarGetRangeOfUnit (cal, kCFCalendarUnitDay, kCFCalendarUnitMonth,
63 * day); /* 2001-03-05 */
PASS_CF (r.location == 1 && r.length == 31,
"The days of March 2001 range from 1 to 31.");

PASS_CF (CFCalendarGetOrdinalityOfUnit (cal, kCFCalendarUnitDay,
kCFCalendarUnitMonth, 45 * day) == 15,
"2001-02-15 is the 15th day of the month.");
PASS_CF (CFCalendarGetOrdinalityOfUnit (cal, kCFCalendarUnitDay,
kCFCalendarUnitYear, 45 * day) == 46,
"2001-02-15 is the 46th day of the year.");
PASS_CF (CFCalendarGetOrdinalityOfUnit (cal, kCFCalendarUnitMonth,
kCFCalendarUnitYear, 45 * day) == 2,
"2001-02-15 is in the 2nd month of the year.");

CFRelease (cal);
CFRelease (gmt);
return 0;
}
Loading