mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 08:21:25 +00:00
Merge branch 'master' of github.com:gnustep/libs-base into NSSecureCoding_branch
This commit is contained in:
commit
76fac00cd2
10 changed files with 598 additions and 335 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -26,6 +26,9 @@ Tests/base/coding/ulong-8.type
|
|||
*.orig
|
||||
*.swp
|
||||
|
||||
# MacOS Desktop Services Store
|
||||
.DS_Store
|
||||
|
||||
# Created by https://www.gitignore.io/api/xcode
|
||||
# Edit at https://www.gitignore.io/?templates=xcode
|
||||
|
||||
|
|
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2020-04-26 Fred Kiefer <fredkiefer@gmx.de>
|
||||
|
||||
* Source/NSLocale.m: Respect NSLocaleCalendarIdentifier if
|
||||
NSLocaleCalendar isn't set.
|
||||
* Headers/Foundation/NSCalendar.h,
|
||||
* Source/NSCalendar.m: Add newer features for NSDateComponents and
|
||||
started to clean up NSCalendar implementation.
|
||||
* Tests/base/NSCalendar/features-10-7.m: Add test for different
|
||||
time zone.
|
||||
|
||||
2020-04-21 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSNotification.m:
|
||||
|
|
|
@ -129,7 +129,7 @@ enum
|
|||
NSCalendarUnitWeekOfMonth = (1UL << 12),
|
||||
NSCalendarUnitWeekOfYear = (1UL << 13),
|
||||
NSCalendarUnitYearForWeekOfYear = (1UL << 14),
|
||||
NSCalendarUnitNanosecond = (1 << 15), // FIXME: unimplemented
|
||||
NSCalendarUnitNanosecond = (1 << 15),
|
||||
NSCalendarUnitCalendar = (1 << 20), // FIXME: unimplemented
|
||||
NSCalendarUnitTimeZone = (1 << 21) // FIXME: unimplemented
|
||||
#endif
|
||||
|
@ -227,6 +227,7 @@ enum
|
|||
* yearForWeekOfYear is 2013, since it's already week 1 in 2013.
|
||||
*/
|
||||
- (NSInteger) yearForWeekOfYear;
|
||||
- (NSInteger) nanosecond;
|
||||
|
||||
/** Sets the number of the week in this month. */
|
||||
- (void) setWeekOfMonth: (NSInteger) v;
|
||||
|
@ -241,8 +242,22 @@ enum
|
|||
* See the explanation at <code>-yearForWeekOfYear</code>.
|
||||
*/
|
||||
- (void) setYearForWeekOfYear: (NSInteger) v;
|
||||
- (void) setNanosecond: (NSInteger) v;
|
||||
|
||||
#endif
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_8, GS_API_LATEST)
|
||||
- (BOOL) leapMonth;
|
||||
- (void) setLeapMonth: (BOOL) v;
|
||||
#endif
|
||||
|
||||
#if OS_API_VERSION(MAC_OS_X_VERSION_10_9, GS_API_LATEST)
|
||||
- (BOOL) isValidDate;
|
||||
- (BOOL) isValidDateInCalendar: (NSCalendar *) calendar;
|
||||
- (NSInteger) valueForComponent: (NSCalendarUnit) unit;
|
||||
- (void) setValue: (NSInteger) value
|
||||
forComponent: (NSCalendarUnit) unit;
|
||||
#endif
|
||||
@end
|
||||
|
||||
|
||||
|
|
|
@ -46,31 +46,26 @@
|
|||
#if GS_USE_ICU == 1
|
||||
static UCalendarDateFields _NSCalendarUnitToDateField (NSCalendarUnit unit)
|
||||
{
|
||||
// I'm just going to go in the order they appear in Apple's documentation
|
||||
if (unit & NSEraCalendarUnit)
|
||||
if (unit & NSCalendarUnitEra)
|
||||
return UCAL_ERA;
|
||||
if (unit & NSYearCalendarUnit)
|
||||
if (unit & NSCalendarUnitYear)
|
||||
return UCAL_YEAR;
|
||||
if (unit & NSMonthCalendarUnit)
|
||||
if (unit & NSCalendarUnitMonth)
|
||||
return UCAL_MONTH;
|
||||
if (unit & NSDayCalendarUnit)
|
||||
if (unit & NSCalendarUnitDay)
|
||||
return UCAL_DAY_OF_MONTH;
|
||||
if (unit & NSHourCalendarUnit)
|
||||
if (unit & NSCalendarUnitHour)
|
||||
return UCAL_HOUR_OF_DAY;
|
||||
if (unit & NSMinuteCalendarUnit)
|
||||
if (unit & NSCalendarUnitMinute)
|
||||
return UCAL_MINUTE;
|
||||
if (unit & NSSecondCalendarUnit)
|
||||
if (unit & NSCalendarUnitSecond)
|
||||
return UCAL_SECOND;
|
||||
if (unit & NSWeekCalendarUnit)
|
||||
if (unit & NSCalendarUnitWeekOfYear)
|
||||
return UCAL_WEEK_OF_YEAR;
|
||||
if (unit & NSWeekdayCalendarUnit)
|
||||
if (unit & NSCalendarUnitWeekday)
|
||||
return UCAL_DAY_OF_WEEK;
|
||||
if (unit & NSWeekdayOrdinalCalendarUnit)
|
||||
// FIXME: Is this right???
|
||||
if (unit & NSCalendarUnitWeekdayOrdinal)
|
||||
return UCAL_DAY_OF_WEEK_IN_MONTH;
|
||||
// ICU doesn't include a quarter DateField...
|
||||
if (unit & NSQuarterCalendarUnit)
|
||||
return (UCAL_MONTH + 2) / 3;
|
||||
return -1;
|
||||
}
|
||||
#endif /* GS_USE_ICU */
|
||||
|
@ -84,47 +79,76 @@ typedef struct {
|
|||
NSInteger minimumDaysInFirstWeek;
|
||||
} Calendar;
|
||||
#define my ((Calendar*)_NSCalendarInternal)
|
||||
#define aac ((Calendar*)(autoupdatingCalendar->_NSCalendarInternal))
|
||||
|
||||
@interface NSCalendar (PrivateMethods)
|
||||
- (void *) _openCalendarFor: (NSTimeZone *)timeZone;
|
||||
- (void) _resetCalendar;
|
||||
- (void *) _UCalendar;
|
||||
- (NSString *) _localeIDWithLocale: (NSLocale*)locale;
|
||||
- (NSString *) _localeIDentifier;
|
||||
- (NSString *) _localeIdentifier;
|
||||
- (void) _setLocaleIdentifier: (NSString*)identifier;
|
||||
@end
|
||||
|
||||
static NSCalendar *autoupdatingCalendar = nil;
|
||||
static NSRecursiveLock *classLock = nil;
|
||||
|
||||
#define TZ_NAME_LENGTH 1024
|
||||
#define SECOND_TO_MILLI 1000.0
|
||||
#define MILLI_TO_NANO 1000000
|
||||
|
||||
@implementation NSCalendar (PrivateMethods)
|
||||
- (void) _resetCalendar
|
||||
{
|
||||
|
||||
#if GS_USE_ICU == 1
|
||||
- (void *) _openCalendarFor: (NSTimeZone *)timeZone
|
||||
{
|
||||
NSString *tzName;
|
||||
NSUInteger tzLen;
|
||||
unichar cTzId[TZ_NAME_LENGTH];
|
||||
const char *cLocaleId;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
if (my->cal != NULL)
|
||||
ucal_close (my->cal);
|
||||
UCalendarType type;
|
||||
|
||||
cLocaleId = [my->localeID UTF8String];
|
||||
tzName = [my->tz name];
|
||||
tzName = [timeZone name];
|
||||
tzLen = [tzName length];
|
||||
if (tzLen > TZ_NAME_LENGTH)
|
||||
{
|
||||
tzLen = TZ_NAME_LENGTH;
|
||||
}
|
||||
[tzName getCharacters: cTzId range: NSMakeRange(0, tzLen)];
|
||||
|
||||
if ([NSGregorianCalendar isEqualToString: my->identifier])
|
||||
{
|
||||
type = UCAL_GREGORIAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef UCAL_DEFAULT
|
||||
/*
|
||||
* Older versions of ICU used UCAL_TRADITIONAL rather than UCAL_DEFAULT
|
||||
* so if one is not available we use the other.
|
||||
*/
|
||||
#define UCAL_DEFAULT UCAL_TRADITIONAL
|
||||
type = UCAL_TRADITIONAL;
|
||||
#else
|
||||
type = UCAL_DEFAULT;
|
||||
#endif
|
||||
my->cal =
|
||||
ucal_open ((const UChar *)cTzId, tzLen, cLocaleId, UCAL_DEFAULT, &err);
|
||||
// We do not need to call uloc_setKeywordValue() here to set the calendar on the locale
|
||||
// as the calendar is already encoded in the locale id by _localeIDWithLocale:.
|
||||
}
|
||||
|
||||
return ucal_open((const UChar *)cTzId, tzLen, cLocaleId, type, &err);
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void) _resetCalendar
|
||||
{
|
||||
#if GS_USE_ICU == 1
|
||||
if (my->cal != NULL)
|
||||
{
|
||||
ucal_close(my->cal);
|
||||
}
|
||||
|
||||
my->cal = [self _openCalendarFor: my->tz];
|
||||
|
||||
if (NSNotFound == my->firstWeekday)
|
||||
{
|
||||
|
@ -147,7 +171,6 @@ typedef struct {
|
|||
ucal_setAttribute(my->cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,
|
||||
(int32_t)my->minimumDaysInFirstWeek);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -163,16 +186,24 @@ typedef struct {
|
|||
NSMutableDictionary *tmpDict;
|
||||
|
||||
localeId = [locale localeIdentifier];
|
||||
if (my->identifier)
|
||||
{
|
||||
tmpDict = [[NSLocale componentsFromLocaleIdentifier: localeId]
|
||||
mutableCopyWithZone: NULL];
|
||||
[tmpDict removeObjectForKey: NSLocaleCalendar];
|
||||
[tmpDict setObject: my->identifier forKey: NSLocaleCalendarIdentifier];
|
||||
result = [NSLocale localeIdentifierFromComponents: tmpDict];
|
||||
RELEASE(tmpDict);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = localeId;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*) _localeIDentifier
|
||||
- (NSString*) _localeIdentifier
|
||||
{
|
||||
return my->localeID;
|
||||
}
|
||||
|
@ -180,26 +211,15 @@ typedef struct {
|
|||
- (void) _setLocaleIdentifier: (NSString *) identifier
|
||||
{
|
||||
if ([identifier isEqualToString: my->localeID])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RELEASE(my->localeID);
|
||||
my->localeID = RETAIN(identifier);
|
||||
ASSIGN(my->localeID, identifier);
|
||||
[self _resetCalendar];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSCalendar
|
||||
|
||||
static NSCalendar *autoupdatingCalendar = nil;
|
||||
static NSRecursiveLock *classLock = nil;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSLocale class])
|
||||
classLock = [NSRecursiveLock new];
|
||||
}
|
||||
|
||||
+ (void) defaultsDidChange: (NSNotification*)n
|
||||
- (void) _defaultsDidChange: (NSNotification*)n
|
||||
{
|
||||
NSUserDefaults *defs;
|
||||
NSString *locale;
|
||||
|
@ -211,105 +231,87 @@ static NSRecursiveLock *classLock = nil;
|
|||
calendar = [defs stringForKey: @"Calendar"];
|
||||
tz = [defs stringForKey: @"Local Time Zone"];
|
||||
|
||||
if ([locale isEqual: aac->localeID] == NO
|
||||
|| [calendar isEqual: aac->identifier] == NO
|
||||
|| [tz isEqual: [(aac->tz) name]] == NO)
|
||||
{
|
||||
[classLock lock];
|
||||
RELEASE(aac->localeID);
|
||||
RELEASE(aac->identifier);
|
||||
RELEASE(aac->tz);
|
||||
if ([locale isEqual: my->localeID] == NO
|
||||
|| [calendar isEqual: my->identifier] == NO
|
||||
|| [tz isEqual: [my->tz name]] == NO)
|
||||
{
|
||||
#if GS_USE_ICU == 1
|
||||
ucal_close(aac->cal);
|
||||
ucal_close(my->cal);
|
||||
#endif
|
||||
|
||||
aac->localeID = RETAIN(locale);
|
||||
aac->identifier = RETAIN(calendar);
|
||||
aac->tz = [[NSTimeZone alloc] initWithName: tz];
|
||||
ASSIGN(my->localeID, locale);
|
||||
ASSIGN(my->identifier, calendar);
|
||||
RELEASE(my->tz);
|
||||
my->tz = [[NSTimeZone alloc] initWithName: tz];
|
||||
|
||||
[autoupdatingCalendar _resetCalendar];
|
||||
[self _resetCalendar];
|
||||
}
|
||||
[classLock unlock];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSCalendar
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if (self == [NSCalendar class])
|
||||
{
|
||||
classLock = [NSRecursiveLock new];
|
||||
}
|
||||
}
|
||||
|
||||
+ (id) currentCalendar
|
||||
{
|
||||
NSCalendar *result;
|
||||
NSLocale *locale;
|
||||
NSCalendar *cal;
|
||||
NSString *identifier;
|
||||
|
||||
locale = [NSLocale currentLocale];
|
||||
cal = [locale objectForKey: NSLocaleCalendar];
|
||||
result =
|
||||
[[NSCalendar alloc] initWithCalendarIdentifier: [cal calendarIdentifier]];
|
||||
// This identifier may be nil
|
||||
identifier = [[NSLocale currentLocale] objectForKey: NSLocaleCalendarIdentifier];
|
||||
result = [[NSCalendar alloc] initWithCalendarIdentifier: identifier];
|
||||
|
||||
return AUTORELEASE(result);
|
||||
}
|
||||
|
||||
+ (id) autoupdatingCurrentCalendar
|
||||
{
|
||||
[classLock lock];
|
||||
if (nil == autoupdatingCalendar)
|
||||
{
|
||||
autoupdatingCalendar = [[self currentCalendar] copy];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: autoupdatingCalendar
|
||||
selector: @selector(_defaultsDidChange:)
|
||||
name: NSUserDefaultsDidChangeNotification
|
||||
object: nil];
|
||||
}
|
||||
|
||||
[classLock unlock];
|
||||
return autoupdatingCalendar;
|
||||
}
|
||||
|
||||
|
||||
+ (id) calendarWithIdentifier: (NSString *) identifier
|
||||
{
|
||||
return AUTORELEASE([[self alloc] initWithCalendarIdentifier: identifier]);
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
self = [self initWithCalendarIdentifier: nil];
|
||||
return self;
|
||||
return [self initWithCalendarIdentifier: nil];
|
||||
}
|
||||
|
||||
+ (id) calendarWithIdentifier: (NSString *) string
|
||||
{
|
||||
return [[[self alloc] initWithCalendarIdentifier: string] autorelease];
|
||||
}
|
||||
|
||||
- (id) initWithCalendarIdentifier: (NSString *) string
|
||||
- (id) initWithCalendarIdentifier: (NSString *) identifier
|
||||
{
|
||||
NSAssert(0 == _NSCalendarInternal, NSInvalidArgumentException);
|
||||
_NSCalendarInternal =
|
||||
NSZoneCalloc([self zone], sizeof(Calendar), 1);
|
||||
_NSCalendarInternal = NSZoneCalloc([self zone], sizeof(Calendar), 1);
|
||||
|
||||
my->firstWeekday = NSNotFound;
|
||||
my->minimumDaysInFirstWeek = NSNotFound;
|
||||
ASSIGN(my->identifier, identifier);
|
||||
ASSIGN(my->tz, [NSTimeZone defaultTimeZone]);
|
||||
[self setLocale: [NSLocale currentLocale]];
|
||||
|
||||
if ([string isEqualToString: NSGregorianCalendar])
|
||||
my->identifier = NSGregorianCalendar;
|
||||
else if ([string isEqualToString: NSBuddhistCalendar])
|
||||
my->identifier = NSBuddhistCalendar;
|
||||
else if ([string isEqualToString: NSChineseCalendar])
|
||||
my->identifier = NSChineseCalendar;
|
||||
else if ([string isEqualToString: NSHebrewCalendar])
|
||||
my->identifier = NSHebrewCalendar;
|
||||
else if ([string isEqualToString: NSIslamicCalendar])
|
||||
my->identifier = NSIslamicCalendar;
|
||||
else if ([string isEqualToString: NSIslamicCivilCalendar])
|
||||
my->identifier = NSIslamicCivilCalendar;
|
||||
else if ([string isEqualToString: NSJapaneseCalendar])
|
||||
my->identifier = NSJapaneseCalendar;
|
||||
else if ([string isEqualToString: NSRepublicOfChinaCalendar])
|
||||
my->identifier = NSRepublicOfChinaCalendar;
|
||||
else if ([string isEqualToString: NSPersianCalendar])
|
||||
my->identifier = NSPersianCalendar;
|
||||
else if ([string isEqualToString: NSIndianCalendar])
|
||||
my->identifier = NSIndianCalendar;
|
||||
else if ([string isEqualToString: NSISO8601Calendar])
|
||||
my->identifier = NSISO8601Calendar;
|
||||
else if ([string isEqualToString: NSCalendarIdentifierCoptic])
|
||||
my->identifier = NSGregorianCalendar; // TODO: unimplemented
|
||||
else if ([string isEqualToString: NSCalendarIdentifierEthiopicAmeteMihret])
|
||||
my->identifier = NSGregorianCalendar; // TODO: unimplemented
|
||||
else if ([string isEqualToString: NSCalendarIdentifierEthiopicAmeteAlem])
|
||||
my->identifier = NSGregorianCalendar; // TODO: unimplemented
|
||||
else if ([string isEqualToString: NSCalendarIdentifierIslamicTabular])
|
||||
my->identifier = NSGregorianCalendar; // TODO: unimplemented
|
||||
else if ([string isEqualToString: NSCalendarIdentifierIslamicUmmAlQura])
|
||||
my->identifier = NSGregorianCalendar; // TODO: unimplemented
|
||||
else
|
||||
{
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
// It's much easier to keep a copy of the NSLocale's string representation
|
||||
// than to have to build it everytime we have to open a UCalendar.
|
||||
my->localeID = RETAIN([self _localeIDWithLocale: [NSLocale currentLocale]]);
|
||||
my->tz = RETAIN([NSTimeZone defaultTimeZone]);
|
||||
|
||||
[self _resetCalendar];
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -342,37 +344,71 @@ static NSRecursiveLock *classLock = nil;
|
|||
UErrorCode err = U_ZERO_ERROR;
|
||||
UDate udate;
|
||||
|
||||
udate = (UDate)floor([date timeIntervalSince1970] * 1000.0);
|
||||
ucal_setMillis (my->cal, udate, &err);
|
||||
udate = (UDate)floor([date timeIntervalSince1970] * SECOND_TO_MILLI);
|
||||
ucal_setMillis(my->cal, udate, &err);
|
||||
if (U_FAILURE(err))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
comps = [[NSDateComponents alloc] init];
|
||||
if (unitFlags & NSEraCalendarUnit)
|
||||
if (unitFlags & NSCalendarUnitEra)
|
||||
{
|
||||
[comps setEra: ucal_get(my->cal, UCAL_ERA, &err)];
|
||||
if (unitFlags & NSYearCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitYear)
|
||||
{
|
||||
[comps setYear: ucal_get(my->cal, UCAL_YEAR, &err)];
|
||||
if (unitFlags & NSMonthCalendarUnit)
|
||||
[comps setMonth: ucal_get(my->cal, UCAL_MONTH, &err)+1];
|
||||
if (unitFlags & NSDayCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitMonth)
|
||||
{
|
||||
[comps setMonth: ucal_get(my->cal, UCAL_MONTH, &err) + 1];
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitDay)
|
||||
{
|
||||
[comps setDay: ucal_get(my->cal, UCAL_DAY_OF_MONTH, &err)];
|
||||
if (unitFlags & NSHourCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitHour)
|
||||
{
|
||||
[comps setHour: ucal_get(my->cal, UCAL_HOUR_OF_DAY, &err)];
|
||||
if (unitFlags & NSMinuteCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitMinute)
|
||||
{
|
||||
[comps setMinute: ucal_get(my->cal, UCAL_MINUTE, &err)];
|
||||
if (unitFlags & NSSecondCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitSecond)
|
||||
{
|
||||
[comps setSecond: ucal_get(my->cal, UCAL_SECOND, &err)];
|
||||
if (unitFlags & (NSWeekCalendarUnit|NSWeekOfYearCalendarUnit))
|
||||
}
|
||||
if (unitFlags & (NSWeekCalendarUnit | NSCalendarUnitWeekOfYear))
|
||||
{
|
||||
[comps setWeek: ucal_get(my->cal, UCAL_WEEK_OF_YEAR, &err)];
|
||||
if (unitFlags & NSWeekdayCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitWeekday)
|
||||
{
|
||||
[comps setWeekday: ucal_get(my->cal, UCAL_DAY_OF_WEEK, &err)];
|
||||
if (unitFlags & NSWeekdayOrdinalCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitWeekdayOrdinal)
|
||||
{
|
||||
[comps setWeekdayOrdinal:
|
||||
ucal_get(my->cal, UCAL_DAY_OF_WEEK_IN_MONTH, &err)];
|
||||
if (unitFlags & NSWeekOfMonthCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitQuarter)
|
||||
{
|
||||
[comps setQuarter: (ucal_get(my->cal, UCAL_MONTH, &err) + 3) / 3];
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitWeekOfMonth)
|
||||
{
|
||||
[comps setWeekOfMonth: ucal_get(my->cal, UCAL_WEEK_OF_MONTH, &err)];
|
||||
if (unitFlags & NSYearForWeekOfYearCalendarUnit)
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitYearForWeekOfYear)
|
||||
{
|
||||
[comps setYearForWeekOfYear: ucal_get(my->cal, UCAL_YEAR_WOY, &err)];
|
||||
}
|
||||
if (unitFlags & NSCalendarUnitNanosecond)
|
||||
{
|
||||
[comps setNanosecond: ucal_get(my->cal, UCAL_MILLISECOND, &err) * MILLI_TO_NANO];
|
||||
}
|
||||
|
||||
return AUTORELEASE(comps);
|
||||
#else
|
||||
|
@ -413,10 +449,10 @@ do \
|
|||
|
||||
NSDateComponents *comps = nil;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
UDate udateFrom = (UDate)floor([startingDate timeIntervalSince1970] * 1000.0);
|
||||
UDate udateTo = (UDate)floor([resultDate timeIntervalSince1970] * 1000.0);
|
||||
UDate udateFrom = (UDate)floor([startingDate timeIntervalSince1970] * SECOND_TO_MILLI);
|
||||
UDate udateTo = (UDate)floor([resultDate timeIntervalSince1970] * SECOND_TO_MILLI);
|
||||
|
||||
ucal_setMillis (my->cal, udateFrom, &err);
|
||||
ucal_setMillis(my->cal, udateFrom, &err);
|
||||
if (U_FAILURE(err))
|
||||
{
|
||||
return nil;
|
||||
|
@ -428,14 +464,14 @@ do \
|
|||
* the largest to the smallest.
|
||||
*/
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSEraCalendarUnit, setEra:, UCAL_ERA, err);
|
||||
NSCalendarUnitEra, setEra:, UCAL_ERA, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSYearCalendarUnit, setYear:, UCAL_YEAR, err);
|
||||
NSCalendarUnitYear, setYear:, UCAL_YEAR, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSMonthCalendarUnit, setMonth:, UCAL_MONTH, err);
|
||||
NSCalendarUnitMonth, setMonth:, UCAL_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSWeekOfYearCalendarUnit, setWeek:, UCAL_WEEK_OF_YEAR, err);
|
||||
if (!(unitFlags & NSWeekOfYearCalendarUnit))
|
||||
NSCalendarUnitWeekOfYear, setWeek:, UCAL_WEEK_OF_YEAR, err);
|
||||
if (!(unitFlags & NSCalendarUnitWeekOfYear))
|
||||
{
|
||||
/* We must avoid setting the same unit twice (it would be zero because
|
||||
* of the automatic advancement.
|
||||
|
@ -444,35 +480,33 @@ do \
|
|||
NSWeekCalendarUnit, setWeek:, UCAL_WEEK_OF_YEAR, err);
|
||||
}
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSWeekOfMonthCalendarUnit, setWeekOfMonth:, UCAL_WEEK_OF_MONTH, err);
|
||||
NSCalendarUnitWeekOfMonth, setWeekOfMonth:, UCAL_WEEK_OF_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSDayCalendarUnit, setDay:, UCAL_DAY_OF_MONTH, err);
|
||||
NSCalendarUnitDay, setDay:, UCAL_DAY_OF_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSWeekdayOrdinalCalendarUnit, setWeekdayOrdinal:,
|
||||
NSCalendarUnitWeekdayOrdinal, setWeekdayOrdinal:,
|
||||
UCAL_DAY_OF_WEEK_IN_MONTH, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSWeekdayCalendarUnit, setWeekday:, UCAL_DAY_OF_WEEK, err);
|
||||
NSCalendarUnitWeekday, setWeekday:, UCAL_DAY_OF_WEEK, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSHourCalendarUnit, setHour:, UCAL_HOUR_OF_DAY, err);
|
||||
NSCalendarUnitHour, setHour:, UCAL_HOUR_OF_DAY, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSMinuteCalendarUnit, setMinute:, UCAL_MINUTE, err);
|
||||
NSCalendarUnitMinute, setMinute:, UCAL_MINUTE, err);
|
||||
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
||||
NSSecondCalendarUnit, setSecond:, UCAL_SECOND, err);
|
||||
# if 0
|
||||
NSCalendarUnitSecond, setSecond:, UCAL_SECOND, err);
|
||||
if (unitFlags & NSCalendarUnitNanosecond)
|
||||
{
|
||||
int32_t ns;
|
||||
int32_t ms;
|
||||
|
||||
ns = ucal_getFieldDifference(my->cal, udateTo, UCAL_MILLISECOND, &err)
|
||||
* 1000000;
|
||||
ms = ucal_getFieldDifference(my->cal, udateTo, UCAL_MILLISECOND, &err);
|
||||
if (U_FAILURE(err))
|
||||
{
|
||||
RELEASE(comps);
|
||||
return nil;
|
||||
}
|
||||
[comps setNanosecond: ns];
|
||||
[comps setNanosecond: ms * MILLI_TO_NANO];
|
||||
}
|
||||
# endif
|
||||
|
||||
return AUTORELEASE(comps);
|
||||
|
||||
#else
|
||||
|
@ -480,6 +514,18 @@ do \
|
|||
#endif
|
||||
}
|
||||
|
||||
#undef COMPONENT_DIFF
|
||||
|
||||
#define _ADD_COMPONENT(c, n) \
|
||||
if (opts & NSWrapCalendarComponents) \
|
||||
ucal_roll(my->cal, c, n, &err); \
|
||||
else \
|
||||
ucal_add(my->cal, c, n, &err); \
|
||||
if (U_FAILURE(err)) \
|
||||
{ \
|
||||
return nil; \
|
||||
}
|
||||
|
||||
- (NSDate *) dateByAddingComponents: (NSDateComponents *) comps
|
||||
toDate: (NSDate *) date
|
||||
options: (NSUInteger) opts
|
||||
|
@ -490,14 +536,9 @@ do \
|
|||
UDate udate;
|
||||
|
||||
[self _resetCalendar];
|
||||
udate = (UDate)([date timeIntervalSince1970] * 1000.0);
|
||||
ucal_setMillis (my->cal, udate, &err);
|
||||
udate = (UDate)([date timeIntervalSince1970] * SECOND_TO_MILLI);
|
||||
ucal_setMillis(my->cal, udate, &err);
|
||||
|
||||
#define _ADD_COMPONENT(c, n) \
|
||||
if (opts & NSWrapCalendarComponents) \
|
||||
ucal_roll (my->cal, c, n, &err); \
|
||||
else \
|
||||
ucal_add (my->cal, c, n, &err);
|
||||
if ((amount = [comps era]) != NSDateComponentUndefined)
|
||||
{
|
||||
_ADD_COMPONENT(UCAL_ERA, (int32_t)amount);
|
||||
|
@ -542,78 +583,107 @@ do \
|
|||
{
|
||||
_ADD_COMPONENT(UCAL_YEAR_WOY, (int32_t)amount);
|
||||
}
|
||||
#undef _ADD_COMPONENT
|
||||
if ((amount = [comps nanosecond]) != NSDateComponentUndefined)
|
||||
{
|
||||
_ADD_COMPONENT(UCAL_MILLISECOND, (int32_t)(amount / MILLI_TO_NANO));
|
||||
}
|
||||
|
||||
udate = ucal_getMillis (my->cal, &err);
|
||||
udate = ucal_getMillis(my->cal, &err);
|
||||
if (U_FAILURE(err))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [NSDate dateWithTimeIntervalSince1970: (udate / 1000.0)];
|
||||
return [NSDate dateWithTimeIntervalSince1970: (udate / SECOND_TO_MILLI)];
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef _ADD_COMPONENT
|
||||
|
||||
- (NSDate *) dateFromComponents: (NSDateComponents *) comps
|
||||
{
|
||||
#if GS_USE_ICU == 1
|
||||
NSInteger amount;
|
||||
UDate udate;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
void *cal;
|
||||
NSTimeZone *timeZone;
|
||||
|
||||
[self _resetCalendar];
|
||||
ucal_clear (my->cal);
|
||||
timeZone = [comps timeZone];
|
||||
if (timeZone == nil)
|
||||
{
|
||||
timeZone = [self timeZone];
|
||||
}
|
||||
cal = [self _openCalendarFor: timeZone];
|
||||
if (!cal)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
ucal_clear(cal);
|
||||
|
||||
if ((amount = [comps era]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_ERA, (int32_t)amount);
|
||||
ucal_set(cal, UCAL_ERA, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps year]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_YEAR, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_YEAR, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps month]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_MONTH, amount-1);
|
||||
ucal_set (cal, UCAL_MONTH, amount - 1);
|
||||
}
|
||||
if ((amount = [comps day]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_DAY_OF_MONTH, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_DAY_OF_MONTH, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps hour]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_HOUR_OF_DAY, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_HOUR_OF_DAY, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps minute]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_MINUTE, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_MINUTE, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps second]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_SECOND, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_SECOND, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps week]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_WEEK_OF_YEAR, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_WEEK_OF_YEAR, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps weekday]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_DAY_OF_WEEK, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_DAY_OF_WEEK, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps weekdayOrdinal]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (cal, UCAL_DAY_OF_WEEK_IN_MONTH, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps weekOfMonth]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_WEEK_OF_MONTH, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_WEEK_OF_MONTH, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps yearForWeekOfYear]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (my->cal, UCAL_YEAR_WOY, (int32_t)amount);
|
||||
ucal_set (cal, UCAL_YEAR_WOY, (int32_t)amount);
|
||||
}
|
||||
if ((amount = [comps nanosecond]) != NSDateComponentUndefined)
|
||||
{
|
||||
ucal_set (cal, UCAL_MILLISECOND, (int32_t)(amount / MILLI_TO_NANO));
|
||||
}
|
||||
|
||||
udate = ucal_getMillis (my->cal, &err);
|
||||
udate = ucal_getMillis(cal, &err);
|
||||
ucal_close(cal);
|
||||
if (U_FAILURE(err))
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [NSDate dateWithTimeIntervalSince1970: (udate / 1000.0)];
|
||||
return [NSDate dateWithTimeIntervalSince1970: (udate / SECOND_TO_MILLI)];
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
|
@ -626,6 +696,8 @@ do \
|
|||
|
||||
- (void) setLocale: (NSLocale *) locale
|
||||
{
|
||||
// It's much easier to keep a copy of the NSLocale's string representation
|
||||
// than to have to build it everytime we have to open a UCalendar.
|
||||
[self _setLocaleIdentifier: [self _localeIDWithLocale: locale]];
|
||||
}
|
||||
|
||||
|
@ -638,7 +710,7 @@ do \
|
|||
{
|
||||
my->firstWeekday = weekday;
|
||||
#if GS_USE_ICU == 1
|
||||
ucal_setAttribute (my->cal, UCAL_FIRST_DAY_OF_WEEK, my->firstWeekday);
|
||||
ucal_setAttribute(my->cal, UCAL_FIRST_DAY_OF_WEEK, my->firstWeekday);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -651,7 +723,7 @@ do \
|
|||
{
|
||||
my->minimumDaysInFirstWeek = (int32_t)mdw;
|
||||
#if GS_USE_ICU == 1
|
||||
ucal_setAttribute (my->cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,
|
||||
ucal_setAttribute(my->cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,
|
||||
my->minimumDaysInFirstWeek);
|
||||
#endif
|
||||
}
|
||||
|
@ -664,62 +736,67 @@ do \
|
|||
- (void) setTimeZone: (NSTimeZone *) tz
|
||||
{
|
||||
if ([tz isEqual: my->tz])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RELEASE(my->tz);
|
||||
my->tz = RETAIN(tz);
|
||||
ASSIGN(my->tz, tz);
|
||||
[self _resetCalendar];
|
||||
}
|
||||
|
||||
|
||||
- (NSRange) maximumRangeOfUnit: (NSCalendarUnit) unit
|
||||
{
|
||||
NSRange result = NSMakeRange (0, 0);
|
||||
#if GS_USE_ICU == 1
|
||||
UCalendarDateFields dateField;
|
||||
NSRange result;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
[self _resetCalendar];
|
||||
dateField = _NSCalendarUnitToDateField (unit);
|
||||
dateField = _NSCalendarUnitToDateField(unit);
|
||||
if (dateField != -1)
|
||||
{
|
||||
// We really don't care if there are any errors...
|
||||
result.location =
|
||||
(NSUInteger)ucal_getLimit (my->cal, dateField, UCAL_MINIMUM, &err);
|
||||
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_MINIMUM, &err);
|
||||
result.length =
|
||||
(NSUInteger)ucal_getLimit (my->cal, dateField, UCAL_MAXIMUM, &err)
|
||||
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_MAXIMUM, &err)
|
||||
- result.location + 1;
|
||||
// ICU's month is 0-based, while NSCalendar is 1-based
|
||||
if (dateField == UCAL_MONTH)
|
||||
{
|
||||
result.location += 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
#else
|
||||
return NSMakeRange (0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (NSRange) minimumRangeofUnit: (NSCalendarUnit) unit
|
||||
{
|
||||
NSRange result = NSMakeRange (0, 0);
|
||||
#if GS_USE_ICU == 1
|
||||
UCalendarDateFields dateField;
|
||||
NSRange result;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
|
||||
[self _resetCalendar];
|
||||
dateField = _NSCalendarUnitToDateField (unit);
|
||||
dateField = _NSCalendarUnitToDateField(unit);
|
||||
if (dateField != -1)
|
||||
{
|
||||
// We really don't care if there are any errors...
|
||||
result.location =
|
||||
(NSUInteger)ucal_getLimit (my->cal, dateField, UCAL_GREATEST_MINIMUM, &err);
|
||||
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_GREATEST_MINIMUM, &err);
|
||||
result.length =
|
||||
(NSUInteger)ucal_getLimit (my->cal, dateField, UCAL_LEAST_MAXIMUM, &err)
|
||||
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_LEAST_MAXIMUM, &err)
|
||||
- result.location + 1;
|
||||
// ICU's month is 0-based, while NSCalendar is 1-based
|
||||
if (dateField == UCAL_MONTH)
|
||||
{
|
||||
result.location += 1;
|
||||
|
||||
return result;
|
||||
#else
|
||||
return NSMakeRange (0, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSUInteger) ordinalityOfUnit: (NSCalendarUnit) smaller
|
||||
|
@ -736,27 +813,6 @@ do \
|
|||
return NSMakeRange (0, 0);
|
||||
}
|
||||
|
||||
+ (id) autoupdatingCurrentCalendar
|
||||
{
|
||||
NSCalendar *result;
|
||||
|
||||
[classLock lock];
|
||||
if (nil == autoupdatingCalendar)
|
||||
{
|
||||
autoupdatingCalendar = [[self currentCalendar] copy];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver: self
|
||||
selector: @selector(defaultsDidChange:)
|
||||
name: NSUserDefaultsDidChangeNotification
|
||||
object: nil];
|
||||
}
|
||||
|
||||
result = RETAIN(autoupdatingCalendar);
|
||||
[classLock unlock];
|
||||
return AUTORELEASE(result);
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) rangeOfUnit: (NSCalendarUnit) unit
|
||||
startDate: (NSDate **) datep
|
||||
interval: (NSTimeInterval *)tip
|
||||
|
@ -768,7 +824,7 @@ do \
|
|||
- (BOOL) isEqual: (id) obj
|
||||
{
|
||||
#if GS_USE_ICU == 1
|
||||
return (BOOL)ucal_equivalentTo (my->cal, [obj _UCalendar]);
|
||||
return (BOOL)ucal_equivalentTo(my->cal, [obj _UCalendar]);
|
||||
#else
|
||||
if ([obj isKindOfClass: [self class]])
|
||||
{
|
||||
|
@ -778,6 +834,10 @@ do \
|
|||
return NO;
|
||||
if (![my->tz isEqual: [obj timeZone]])
|
||||
return NO;
|
||||
if (my->firstWeekday != [obj firstWeekday])
|
||||
return NO;
|
||||
if (my->minimumDaysInFirstWeek != [obj minimumDaysInFirstWeek])
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -843,6 +903,8 @@ typedef struct {
|
|||
NSInteger quarter;
|
||||
NSInteger weekOfMonth;
|
||||
NSInteger yearForWeekOfYear;
|
||||
BOOL leapMonth;
|
||||
NSInteger nanosecond;
|
||||
NSCalendar *cal;
|
||||
NSTimeZone *tz;
|
||||
} DateComp;
|
||||
|
@ -880,6 +942,8 @@ typedef struct {
|
|||
my->quarter = NSDateComponentUndefined;
|
||||
my->weekOfMonth = NSDateComponentUndefined;
|
||||
my->yearForWeekOfYear = NSDateComponentUndefined;
|
||||
my->leapMonth = NO;
|
||||
my->nanosecond = NSDateComponentUndefined;
|
||||
my->cal = NULL;
|
||||
my->tz = NULL;
|
||||
}
|
||||
|
@ -921,6 +985,11 @@ typedef struct {
|
|||
return my->second;
|
||||
}
|
||||
|
||||
- (NSInteger) nanosecond
|
||||
{
|
||||
return my->nanosecond;
|
||||
}
|
||||
|
||||
- (NSInteger) week
|
||||
{
|
||||
return my->week;
|
||||
|
@ -956,6 +1025,11 @@ typedef struct {
|
|||
return my->yearForWeekOfYear;
|
||||
}
|
||||
|
||||
- (BOOL) leapMonth
|
||||
{
|
||||
return my->leapMonth;
|
||||
}
|
||||
|
||||
- (NSCalendar *) calendar
|
||||
{
|
||||
return my->cal;
|
||||
|
@ -969,10 +1043,6 @@ typedef struct {
|
|||
- (NSDate *) date
|
||||
{
|
||||
NSCalendar* cal = [self calendar];
|
||||
NSTimeZone* zone = [self timeZone];
|
||||
|
||||
if (zone != NULL)
|
||||
[cal setTimeZone: zone];
|
||||
|
||||
return [cal dateFromComponents: self];
|
||||
}
|
||||
|
@ -1013,6 +1083,11 @@ typedef struct {
|
|||
my->second = v;
|
||||
}
|
||||
|
||||
- (void) setNanosecond: (NSInteger) v
|
||||
{
|
||||
my->nanosecond = v;
|
||||
}
|
||||
|
||||
- (void) setWeek: (NSInteger) v
|
||||
{
|
||||
my->week = v;
|
||||
|
@ -1048,6 +1123,11 @@ typedef struct {
|
|||
my->yearForWeekOfYear = v;
|
||||
}
|
||||
|
||||
- (void) setLeapMonth: (BOOL) v
|
||||
{
|
||||
my->leapMonth = v;
|
||||
}
|
||||
|
||||
- (void) setCalendar: (NSCalendar *) cal
|
||||
{
|
||||
ASSIGN(my->cal, cal);
|
||||
|
@ -1058,6 +1138,98 @@ typedef struct {
|
|||
ASSIGN(my->tz, tz);
|
||||
}
|
||||
|
||||
- (BOOL) isValidDate
|
||||
{
|
||||
if (my->cal == nil)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
return [self isValidDateInCalendar: my->cal];
|
||||
}
|
||||
|
||||
- (BOOL) isValidDateInCalendar: (NSCalendar *) calendar
|
||||
{
|
||||
return [calendar dateFromComponents: self] != nil;
|
||||
}
|
||||
|
||||
- (NSInteger) valueForComponent: (NSCalendarUnit) unit
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case NSCalendarUnitEra: return my->era;
|
||||
case NSCalendarUnitYear: return my->year;
|
||||
case NSCalendarUnitMonth: return my->month;
|
||||
case NSCalendarUnitDay: return my->day;
|
||||
case NSCalendarUnitHour: return my->hour;
|
||||
case NSCalendarUnitMinute: return my->minute;
|
||||
case NSCalendarUnitSecond: return my->second;
|
||||
case NSCalendarUnitWeekday: return my->weekday;
|
||||
case NSCalendarUnitWeekdayOrdinal: return my->weekdayOrdinal;
|
||||
case NSCalendarUnitQuarter: return my->quarter;
|
||||
case NSCalendarUnitWeekOfMonth: return my->weekOfMonth;
|
||||
case NSCalendarUnitWeekOfYear: return my->week;
|
||||
case NSWeekCalendarUnit: return my->week;
|
||||
case NSCalendarUnitYearForWeekOfYear: return my->yearForWeekOfYear;
|
||||
case NSCalendarUnitNanosecond: return my->nanosecond;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setValue: (NSInteger) value
|
||||
forComponent: (NSCalendarUnit) unit
|
||||
{
|
||||
switch (unit)
|
||||
{
|
||||
case NSCalendarUnitEra:
|
||||
my->era = value;
|
||||
break;
|
||||
case NSCalendarUnitYear:
|
||||
my->year = value;
|
||||
break;
|
||||
case NSCalendarUnitMonth:
|
||||
my->month = value;
|
||||
break;
|
||||
case NSCalendarUnitDay:
|
||||
my->day = value;
|
||||
break;
|
||||
case NSCalendarUnitHour:
|
||||
my->hour = value;
|
||||
break;
|
||||
case NSCalendarUnitMinute:
|
||||
my->minute = value;
|
||||
break;
|
||||
case NSCalendarUnitSecond:
|
||||
my->second = value;
|
||||
break;
|
||||
case NSCalendarUnitWeekday:
|
||||
my->weekday = value;
|
||||
break;
|
||||
case NSCalendarUnitWeekdayOrdinal:
|
||||
my->weekdayOrdinal = value;
|
||||
break;
|
||||
case NSCalendarUnitQuarter:
|
||||
my->quarter = value;
|
||||
break;
|
||||
case NSCalendarUnitWeekOfMonth:
|
||||
my->weekOfMonth = value;
|
||||
break;
|
||||
case NSCalendarUnitWeekOfYear:
|
||||
my->week = value;
|
||||
break;
|
||||
case NSWeekCalendarUnit:
|
||||
my->week = value;
|
||||
break;
|
||||
case NSCalendarUnitYearForWeekOfYear:
|
||||
my->yearForWeekOfYear = value;
|
||||
break;
|
||||
case NSCalendarUnitNanosecond:
|
||||
my->nanosecond = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
{
|
||||
if (NSShouldRetainWithZone(self, zone))
|
||||
|
|
|
@ -468,10 +468,15 @@ parseNumber(ParserState *state)
|
|||
{\
|
||||
bufferSize *= 2;\
|
||||
if (number == numberBuffer)\
|
||||
{\
|
||||
number = malloc(bufferSize);\
|
||||
memcpy(number, numberBuffer, sizeof(numberBuffer));\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
number = realloc(number, bufferSize);\
|
||||
}\
|
||||
}\
|
||||
number[parsedSize++] = (char)x; } while (0)
|
||||
// JSON numbers must start with a - or a digit
|
||||
if (!(c == '-' || isdigit(c)))
|
||||
|
|
|
@ -627,6 +627,11 @@ static NSRecursiveLock *classLock = nil;
|
|||
[[dict objectForKey: NSLocaleCollationIdentifier] UTF8String];
|
||||
const char *currency = [[dict objectForKey: NSLocaleCurrencyCode] UTF8String];
|
||||
|
||||
if (!calendar)
|
||||
{
|
||||
calendar = [[dict objectForKey: NSLocaleCalendarIdentifier] UTF8String];
|
||||
}
|
||||
|
||||
// A locale cannot be constructed without a language.
|
||||
if (language == NULL)
|
||||
return nil;
|
||||
|
|
|
@ -1901,7 +1901,8 @@ GSICUCollatorOpen(NSStringCompareOptions mask, NSLocale *locale)
|
|||
}
|
||||
}
|
||||
|
||||
- (NSString *) stringByAddingPercentEncodingWithAllowedCharacters: (NSCharacterSet *)aSet
|
||||
- (NSString *) stringByAddingPercentEncodingWithAllowedCharacters:
|
||||
(NSCharacterSet *)aSet
|
||||
{
|
||||
NSData *data = [self dataUsingEncoding: NSUTF8StringEncoding];
|
||||
NSString *s = nil;
|
||||
|
@ -1921,7 +1922,10 @@ GSICUCollatorOpen(NSStringCompareOptions mask, NSLocale *locale)
|
|||
unsigned int hi;
|
||||
unsigned int lo;
|
||||
|
||||
if([aSet characterIsMember: c]) // if the character is in the allowed set, put it in
|
||||
/* If the character is in the allowed set *and* is in the
|
||||
* 7-bit ASCII range, it can be added unchanged.
|
||||
*/
|
||||
if (c < 128 && [aSet characterIsMember: c])
|
||||
{
|
||||
dst[dpos++] = c;
|
||||
}
|
||||
|
@ -1936,7 +1940,7 @@ GSICUCollatorOpen(NSStringCompareOptions mask, NSLocale *locale)
|
|||
}
|
||||
s = [[NSString alloc] initWithBytes: dst
|
||||
length: dpos
|
||||
encoding: NSUTF8StringEncoding];
|
||||
encoding: NSASCIIStringEncoding];
|
||||
NSZoneFree(NSDefaultMallocZone(), dst);
|
||||
IF_NO_GC([s autorelease];)
|
||||
}
|
||||
|
@ -1963,7 +1967,7 @@ GSICUCollatorOpen(NSStringCompareOptions mask, NSLocale *locale)
|
|||
uint8_t hi = s[index+1];
|
||||
uint8_t lo = s[index+2];
|
||||
|
||||
if (isdigit(hi) && isxdigit(lo))
|
||||
if (isxdigit(hi) && isxdigit(lo))
|
||||
{
|
||||
index += 2;
|
||||
if (hi <= '9')
|
||||
|
|
|
@ -51,6 +51,9 @@ TOP_DIR := $(shell dirname $(CURDIR))
|
|||
all::
|
||||
@(echo If you want to run the gnustep-base testsuite, please type \'${MAKE} check\')
|
||||
|
||||
# To run tests for a separate group please, use 'make check testobj=NSString'
|
||||
# or 'make check testobj=NSDate/general.m' to run an individual test file
|
||||
#
|
||||
#
|
||||
# 'make check' runs the testsuite (Objective-C tests only)
|
||||
#
|
||||
|
@ -72,9 +75,9 @@ check::
|
|||
export LD_LIBRARY_PATH;\
|
||||
export PATH;\
|
||||
if [ "$(debug)" = "yes" ]; then \
|
||||
gnustep-tests --debug base;\
|
||||
gnustep-tests --debug 'base/$(testobj)';\
|
||||
else \
|
||||
gnustep-tests base;\
|
||||
gnustep-tests 'base/$(testobj)';\
|
||||
fi; \
|
||||
)
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ int main()
|
|||
NSCalendar *cal;
|
||||
NSDate *date;
|
||||
NSDate *date2;
|
||||
NSDate *date3;
|
||||
NSDate *date4;
|
||||
|
||||
START_SET("NSCalendar 10.7 features")
|
||||
if (!NSCALENDAR_SUPPORTED)
|
||||
|
@ -49,6 +51,12 @@ int main()
|
|||
|
||||
PASS_EQUAL(date, date2, "-[NSDateComponents date] returns the correct date");
|
||||
|
||||
date3 = [NSDate dateWithString: @"2012-12-31 13:57:00 +0200"];
|
||||
[comps setTimeZone: [NSTimeZone timeZoneForSecondsFromGMT: 7200]];
|
||||
date4 = [cal dateFromComponents: comps];
|
||||
|
||||
PASS_EQUAL(date3, date4, "-[NSCalendar dateFromComponents:] respects the time zone");
|
||||
|
||||
RELEASE(comps);
|
||||
RELEASE(cal);
|
||||
|
||||
|
|
|
@ -3,55 +3,93 @@
|
|||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSCharacterSet.h>
|
||||
|
||||
BOOL testUrlCharacterSetEncoding(
|
||||
NSString* decodedString,
|
||||
NSString* encodedString,
|
||||
NSCharacterSet* allowedCharacterSet)
|
||||
{
|
||||
NSString *testString
|
||||
= [decodedString stringByAddingPercentEncodingWithAllowedCharacters:
|
||||
allowedCharacterSet];
|
||||
// NSLog(@"String by adding percent, done. test=%@ decoded=%@", testString, decodedString);
|
||||
return [encodedString isEqualToString: testString];
|
||||
void testEncodeDecode(NSString* encoded, NSString* decoded, NSCharacterSet* charset, NSString* description){
|
||||
|
||||
NSString* encodeTest = [decoded stringByAddingPercentEncodingWithAllowedCharacters:charset];
|
||||
NSString* decodeTest = [encoded stringByRemovingPercentEncoding];
|
||||
|
||||
const char* encodeMsg = [[NSString stringWithFormat:@"Percent-Encode: %@", description] UTF8String];
|
||||
const char* decodeMsg = [[NSString stringWithFormat:@"Percent-Decode: %@", description] UTF8String];
|
||||
|
||||
PASS_EQUAL(encodeTest, encoded, "%s", encodeMsg);
|
||||
PASS_EQUAL(decodeTest, decoded, "%s", decodeMsg);
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
|
||||
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
NSString *urlDecodedString = @"Only alphabetic characters should be allowed and not encoded. !@#$%^&*()_+-=";
|
||||
NSString *urlEncodedString =
|
||||
@"Only%20alphabetic%20characters%20should%20be%20allowed%20and%20not%20encoded%2E%20%21%40%23%24%25%5E%26%2A%28%29%5F%2B%2D%3D";
|
||||
NSCharacterSet *allowedCharacterSet = [NSCharacterSet alphanumericCharacterSet];
|
||||
PASS(testUrlCharacterSetEncoding(urlDecodedString, urlEncodedString, allowedCharacterSet), "alphanumericCharacterSet");
|
||||
NSString *urlEncodedString = @"Only%20alphabetic%20characters%20should%20be%20allowed%20and%20not%20encoded%2E%20%21%40%23%24%25%5E%26%2A%28%29%5F%2B%2D%3D";
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [NSCharacterSet alphanumericCharacterSet],
|
||||
@"Skip alphanumericCharacterSet 01");
|
||||
|
||||
|
||||
urlDecodedString = @"https://www.microsoft.com/en-us/!@#$%^&*()_";
|
||||
urlEncodedString = @"https://www.microsoft.com/en-us/!@%23$%25%5E&*()_";
|
||||
allowedCharacterSet = [NSCharacterSet URLFragmentAllowedCharacterSet];
|
||||
PASS(testUrlCharacterSetEncoding(urlDecodedString, urlEncodedString, allowedCharacterSet), "fragmentCharacterSet");
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [NSCharacterSet URLFragmentAllowedCharacterSet],
|
||||
@"Skip URLFragmentAllowedCharacterSet 02");
|
||||
|
||||
|
||||
urlDecodedString = @"All alphabetic characters should be encoded. Symbols should not be: !@#$%^&*()_+-=";
|
||||
urlEncodedString = @"%41%6C%6C %61%6C%70%68%61%62%65%74%69%63 %63%68%61%72%61%63%74%65%72%73 %73%68%6F%75%6C%64 %62%65 "
|
||||
@"%65%6E%63%6F%64%65%64. %53%79%6D%62%6F%6C%73 %73%68%6F%75%6C%64 %6E%6F%74 %62%65: !@#$%^&*()_+-=";
|
||||
allowedCharacterSet = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
|
||||
PASS(testUrlCharacterSetEncoding(urlDecodedString, urlEncodedString, allowedCharacterSet), "inverted");
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [[NSCharacterSet alphanumericCharacterSet] invertedSet],
|
||||
@"Skip not alphanumericCharacterSet 03");
|
||||
|
||||
|
||||
urlDecodedString = @"Here are some Emojis: \U0001F601 \U0001F602 \U0001F638 Emojis done."; // Multibyte encoded characters
|
||||
urlEncodedString = @"Here%20are%20some%20Emojis:%20%F0%9F%98%81%20%F0%9F%98%82%20%F0%9F%98%B8%20Emojis%20done.";
|
||||
allowedCharacterSet = [NSCharacterSet URLFragmentAllowedCharacterSet];
|
||||
PASS(testUrlCharacterSetEncoding(urlDecodedString, urlEncodedString, allowedCharacterSet), "fragmentCharacterSet emojis");
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [NSCharacterSet URLFragmentAllowedCharacterSet],
|
||||
@"Skip URLFragmentAllowedCharacterSet 04");
|
||||
|
||||
|
||||
urlDecodedString = @"\1";
|
||||
urlEncodedString = @"%01";
|
||||
allowedCharacterSet = [NSCharacterSet alphanumericCharacterSet];
|
||||
PASS(testUrlCharacterSetEncoding(urlDecodedString, urlEncodedString, allowedCharacterSet), "alphanumericCharacterSet");
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [NSCharacterSet alphanumericCharacterSet],
|
||||
@"Skip URLFragmentAllowedCharacterSet 05");
|
||||
|
||||
|
||||
urlDecodedString = @"£";
|
||||
urlEncodedString = @"%C2%A3";
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [NSCharacterSet alphanumericCharacterSet],
|
||||
@"Two-byte character 06");
|
||||
|
||||
|
||||
urlDecodedString = @"€";
|
||||
urlEncodedString = @"%E2%82%AC";
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [NSCharacterSet alphanumericCharacterSet],
|
||||
@"Three-byte character 07");
|
||||
|
||||
|
||||
urlDecodedString = @"𐍈";
|
||||
urlEncodedString = @"%F0%90%8D%88";
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [NSCharacterSet alphanumericCharacterSet],
|
||||
@"Four-byte character 08");
|
||||
|
||||
|
||||
//check full string encoding and decoding
|
||||
urlDecodedString = @"0123456789 AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz _-~`!#$%&'()*+,/:;=?@[]™…©®£ƒ‰¥§";
|
||||
urlEncodedString = @"%30%31%32%33%34%35%36%37%38%39%20%41%61%42%62%43%63%44%64%45%65%46%66%47%67%48%68%49%69%4A%6A%4B%6B%4C%6C%4D%6D%4E%6E%4F%6F%50%70%51%71%52%72%53%73%54%74%55%75%56%76%57%77%58%78%59%79%5A%7A%20%5F%2D%7E%60%21%23%24%25%26%27%28%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D%E2%84%A2%E2%80%A6%C2%A9%C2%AE%C2%A3%C6%92%E2%80%B0%C2%A5%C2%A7";
|
||||
testEncodeDecode(urlEncodedString, urlDecodedString, [[NSCharacterSet characterSetWithCharactersInString:urlDecodedString] invertedSet],
|
||||
@"All characters in string 09");
|
||||
|
||||
|
||||
//check decoding of string with an unencoded part at the beginning
|
||||
NSString* asIsString = @"0123456789 AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz _-~`!#$&'()*+,/:;=?@[]™…©®£ƒ‰¥§";
|
||||
urlDecodedString = [asIsString stringByAppendingString:urlDecodedString];
|
||||
urlEncodedString = [asIsString stringByAppendingString:urlEncodedString];
|
||||
PASS_EQUAL([urlEncodedString stringByRemovingPercentEncoding], urlDecodedString, "Percent-encoded string decoding 10");
|
||||
|
||||
|
||||
//check decoding of string with the encoded part in the middle
|
||||
urlDecodedString = [urlDecodedString stringByAppendingString:asIsString];
|
||||
urlEncodedString = [urlEncodedString stringByAppendingString:asIsString];
|
||||
PASS_EQUAL([urlEncodedString stringByRemovingPercentEncoding], urlDecodedString, "Percent-encoded string decoding 11");
|
||||
|
||||
|
||||
urlDecodedString = @"All alphabetic characters should be encoded. Symbols should not be: !@#$%^&*()_+-=";
|
||||
urlEncodedString = @"%41%6C%6C %61%6C%70%68%61%62%65%74%69%63 %63%68%61%72%61%63%74%65%72%73 %73%68%6F%75%6C%64 %62%65 "
|
||||
@"%65%6E%63%6F%64%65%64. %53%79%6D%62%6F%6C%73 %73%68%6F%75%6C%64 %6E%6F%74 %62%65: !@#$%^&*()_+-=";
|
||||
NSString *result = [urlEncodedString stringByRemovingPercentEncoding];
|
||||
PASS([urlDecodedString isEqualToString: result], "stringByRemovingPercentEncoding");
|
||||
// NSLog(@"Result = \"%@\",\ndecodedString = \"%@\",\nencodedString = \"%@\"", result, urlDecodedString, urlEncodedString);
|
||||
[pool drain];
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue