2023-12-23 01:44:50 +00:00
|
|
|
/** NSCalendar.m
|
2010-12-15 00:04:51 +00:00
|
|
|
|
|
|
|
Copyright (C) 2010 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Written by: Stefan Bidigaray
|
|
|
|
Date: December, 2010
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with this library; see the file COPYING.LIB.
|
|
|
|
If not, see <http://www.gnu.org/licenses/> or write to the
|
|
|
|
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import "common.h"
|
|
|
|
#import "Foundation/NSCalendar.h"
|
2011-01-02 03:47:29 +00:00
|
|
|
#import "Foundation/NSCoder.h"
|
2010-12-15 00:04:51 +00:00
|
|
|
#import "Foundation/NSDate.h"
|
2010-12-16 02:57:31 +00:00
|
|
|
#import "Foundation/NSDictionary.h"
|
2013-03-26 09:27:49 +00:00
|
|
|
#import "Foundation/NSException.h"
|
2010-12-15 00:04:51 +00:00
|
|
|
#import "Foundation/NSLocale.h"
|
2024-05-30 10:06:23 +00:00
|
|
|
#import "Foundation/NSLock.h"
|
2011-01-29 18:49:21 +00:00
|
|
|
#import "Foundation/NSNotification.h"
|
2010-12-15 00:04:51 +00:00
|
|
|
#import "Foundation/NSString.h"
|
|
|
|
#import "Foundation/NSTimeZone.h"
|
2011-01-29 18:49:21 +00:00
|
|
|
#import "Foundation/NSUserDefaults.h"
|
2010-12-15 00:04:51 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_UNICODE_UCAL_H)
|
2011-06-11 10:44:38 +00:00
|
|
|
#define id ucal_id
|
2010-12-15 00:04:51 +00:00
|
|
|
#include <unicode/ucal.h>
|
2016-02-29 10:05:36 +00:00
|
|
|
#include <unicode/uvernum.h>
|
2011-06-11 10:44:38 +00:00
|
|
|
#undef id
|
2021-07-16 12:31:38 +00:00
|
|
|
#elif defined(HAVE_ICU_H)
|
|
|
|
#include <icu.h>
|
2010-12-15 00:04:51 +00:00
|
|
|
#endif
|
|
|
|
|
2010-12-17 02:15:55 +00:00
|
|
|
|
|
|
|
#if GS_USE_ICU == 1
|
2020-05-12 12:35:18 +00:00
|
|
|
static UCalendarDateFields _NSCalendarUnitToDateField(NSCalendarUnit unit)
|
2010-12-17 02:15:55 +00:00
|
|
|
{
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitEra)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_ERA;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitYear)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_YEAR;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitMonth)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_MONTH;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitDay)
|
2010-12-31 22:22:10 +00:00
|
|
|
return UCAL_DAY_OF_MONTH;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitHour)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_HOUR_OF_DAY;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitMinute)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_MINUTE;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitSecond)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_SECOND;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitWeekOfYear)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_WEEK_OF_YEAR;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitWeekday)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_DAY_OF_WEEK;
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unit & NSCalendarUnitWeekdayOrdinal)
|
2010-12-17 02:15:55 +00:00
|
|
|
return UCAL_DAY_OF_WEEK_IN_MONTH;
|
2020-05-12 12:35:18 +00:00
|
|
|
return (UCalendarDateFields)-1;
|
2010-12-17 02:15:55 +00:00
|
|
|
}
|
|
|
|
#endif /* GS_USE_ICU */
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
typedef struct {
|
|
|
|
NSString *identifier;
|
|
|
|
NSString *localeID;
|
2020-04-26 19:13:22 +00:00
|
|
|
NSTimeZone *tz;
|
2013-03-26 09:27:49 +00:00
|
|
|
void *cal;
|
2013-04-08 16:21:57 +00:00
|
|
|
NSInteger firstWeekday;
|
|
|
|
NSInteger minimumDaysInFirstWeek;
|
2020-04-26 19:13:22 +00:00
|
|
|
} Calendar;
|
2013-03-26 09:27:49 +00:00
|
|
|
#define my ((Calendar*)_NSCalendarInternal)
|
|
|
|
|
2010-12-16 02:57:31 +00:00
|
|
|
@interface NSCalendar (PrivateMethods)
|
2020-04-26 19:13:22 +00:00
|
|
|
- (void *) _openCalendarFor: (NSTimeZone *)timeZone;
|
2011-01-28 00:23:57 +00:00
|
|
|
- (void) _resetCalendar;
|
2011-01-28 00:49:16 +00:00
|
|
|
- (void *) _UCalendar;
|
2013-03-26 09:27:49 +00:00
|
|
|
- (NSString *) _localeIDWithLocale: (NSLocale*)locale;
|
2020-04-26 19:13:22 +00:00
|
|
|
- (NSString *) _localeIdentifier;
|
2013-03-26 09:27:49 +00:00
|
|
|
- (void) _setLocaleIdentifier: (NSString*)identifier;
|
2010-12-16 02:57:31 +00:00
|
|
|
@end
|
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
static NSCalendar *autoupdatingCalendar = nil;
|
|
|
|
static NSRecursiveLock *classLock = nil;
|
|
|
|
|
2010-12-16 02:57:31 +00:00
|
|
|
#define TZ_NAME_LENGTH 1024
|
2020-04-26 19:13:22 +00:00
|
|
|
#define SECOND_TO_MILLI 1000.0
|
|
|
|
#define MILLI_TO_NANO 1000000
|
2010-12-16 02:57:31 +00:00
|
|
|
|
|
|
|
@implementation NSCalendar (PrivateMethods)
|
2020-04-25 22:32:49 +00:00
|
|
|
|
2010-12-16 10:09:43 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2020-04-25 22:32:49 +00:00
|
|
|
- (void *) _openCalendarFor: (NSTimeZone *)timeZone
|
|
|
|
{
|
2011-01-28 00:23:57 +00:00
|
|
|
NSString *tzName;
|
|
|
|
NSUInteger tzLen;
|
|
|
|
unichar cTzId[TZ_NAME_LENGTH];
|
|
|
|
const char *cLocaleId;
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
2020-04-25 22:32:49 +00:00
|
|
|
UCalendarType type;
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
cLocaleId = [my->localeID UTF8String];
|
2020-04-25 22:32:49 +00:00
|
|
|
tzName = [timeZone name];
|
2011-01-28 00:23:57 +00:00
|
|
|
tzLen = [tzName length];
|
|
|
|
if (tzLen > TZ_NAME_LENGTH)
|
2020-04-25 22:32:49 +00:00
|
|
|
{
|
|
|
|
tzLen = TZ_NAME_LENGTH;
|
|
|
|
}
|
2011-01-28 00:23:57 +00:00
|
|
|
[tzName getCharacters: cTzId range: NSMakeRange(0, tzLen)];
|
2010-12-17 11:45:17 +00:00
|
|
|
|
2020-04-25 22:32:49 +00:00
|
|
|
if ([NSGregorianCalendar isEqualToString: my->identifier])
|
|
|
|
{
|
|
|
|
type = UCAL_GREGORIAN;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-12-17 11:45:17 +00:00
|
|
|
#ifndef UCAL_DEFAULT
|
|
|
|
/*
|
|
|
|
* Older versions of ICU used UCAL_TRADITIONAL rather than UCAL_DEFAULT
|
|
|
|
* so if one is not available we use the other.
|
2020-04-26 19:13:22 +00:00
|
|
|
*/
|
|
|
|
type = UCAL_TRADITIONAL;
|
|
|
|
#else
|
2020-04-25 22:32:49 +00:00
|
|
|
type = UCAL_DEFAULT;
|
2020-04-26 19:13:22 +00:00
|
|
|
#endif
|
|
|
|
// 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:.
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
return ucal_open((const UChar *)cTzId, tzLen, cLocaleId, type, &err);
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
- (void) _resetCalendar
|
|
|
|
{
|
|
|
|
#if GS_USE_ICU == 1
|
|
|
|
if (my->cal != NULL)
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_close(my->cal);
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
my->cal = [self _openCalendarFor: my->tz];
|
2013-03-26 09:27:49 +00:00
|
|
|
|
|
|
|
if (NSNotFound == my->firstWeekday)
|
|
|
|
{
|
|
|
|
my->firstWeekday
|
|
|
|
= ucal_getAttribute(my->cal, UCAL_FIRST_DAY_OF_WEEK);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ucal_setAttribute(my->cal, UCAL_FIRST_DAY_OF_WEEK,
|
2013-04-08 16:21:57 +00:00
|
|
|
(int32_t)my->firstWeekday);
|
2013-03-26 09:27:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NSNotFound == my->minimumDaysInFirstWeek)
|
|
|
|
{
|
|
|
|
my->minimumDaysInFirstWeek
|
|
|
|
= ucal_getAttribute(my->cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ucal_setAttribute(my->cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,
|
2013-04-08 16:21:57 +00:00
|
|
|
(int32_t)my->minimumDaysInFirstWeek);
|
2013-03-26 09:27:49 +00:00
|
|
|
}
|
2010-12-16 02:57:31 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-01-28 00:49:16 +00:00
|
|
|
- (void *) _UCalendar
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->cal;
|
2011-01-28 00:49:16 +00:00
|
|
|
}
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
- (NSString*) _localeIDWithLocale: (NSLocale *)locale
|
2010-12-16 02:57:31 +00:00
|
|
|
{
|
|
|
|
NSString *result;
|
|
|
|
NSString *localeId;
|
|
|
|
NSMutableDictionary *tmpDict;
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2010-12-16 02:57:31 +00:00
|
|
|
localeId = [locale localeIdentifier];
|
2020-04-26 19:13:22 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-12-16 02:57:31 +00:00
|
|
|
return result;
|
|
|
|
}
|
2011-01-02 03:47:29 +00:00
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
- (NSString*) _localeIdentifier
|
2011-01-02 03:47:29 +00:00
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->localeID;
|
2011-01-02 03:47:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) _setLocaleIdentifier: (NSString *) identifier
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
if ([identifier isEqualToString: my->localeID])
|
2020-04-25 22:32:49 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
return;
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
|
|
|
ASSIGN(my->localeID, identifier);
|
|
|
|
[self _resetCalendar];
|
2011-01-29 18:49:21 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
- (void) _defaultsDidChange: (NSNotification*)n
|
2011-01-29 18:49:21 +00:00
|
|
|
{
|
|
|
|
NSUserDefaults *defs;
|
|
|
|
NSString *locale;
|
|
|
|
NSString *calendar;
|
|
|
|
NSString *tz;
|
|
|
|
|
|
|
|
defs = [NSUserDefaults standardUserDefaults];
|
|
|
|
locale = [defs stringForKey: @"Locale"];
|
|
|
|
calendar = [defs stringForKey: @"Calendar"];
|
|
|
|
tz = [defs stringForKey: @"Local Time Zone"];
|
2020-04-26 19:13:22 +00:00
|
|
|
|
|
|
|
[classLock lock];
|
|
|
|
if ([locale isEqual: my->localeID] == NO
|
|
|
|
|| [calendar isEqual: my->identifier] == NO
|
|
|
|
|| [tz isEqual: [my->tz name]] == NO)
|
|
|
|
{
|
2011-01-29 18:49:21 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_close(my->cal);
|
2011-01-29 18:49:21 +00:00
|
|
|
#endif
|
2020-04-26 19:13:22 +00:00
|
|
|
|
|
|
|
ASSIGN(my->localeID, locale);
|
|
|
|
ASSIGN(my->identifier, calendar);
|
|
|
|
RELEASE(my->tz);
|
|
|
|
my->tz = [[NSTimeZone alloc] initWithName: tz];
|
|
|
|
|
|
|
|
[self _resetCalendar];
|
|
|
|
}
|
|
|
|
[classLock unlock];
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSCalendar
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
if (self == [NSCalendar class])
|
|
|
|
{
|
|
|
|
classLock = [NSRecursiveLock new];
|
2011-01-29 18:49:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
+ (id) currentCalendar
|
|
|
|
{
|
2011-01-29 18:49:21 +00:00
|
|
|
NSCalendar *result;
|
2020-04-26 19:13:22 +00:00
|
|
|
NSString *identifier;
|
|
|
|
|
|
|
|
// This identifier may be nil
|
|
|
|
identifier = [[NSLocale currentLocale] objectForKey: NSLocaleCalendarIdentifier];
|
|
|
|
result = [[NSCalendar alloc] initWithCalendarIdentifier: identifier];
|
|
|
|
|
2011-01-01 22:20:16 +00:00
|
|
|
return AUTORELEASE(result);
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
+ (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
|
2013-03-26 09:27:49 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
return AUTORELEASE([[self alloc] initWithCalendarIdentifier: identifier]);
|
2013-03-26 09:27:49 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 22:32:49 +00:00
|
|
|
- (id) init
|
2018-04-30 17:01:51 +00:00
|
|
|
{
|
2020-04-25 22:32:49 +00:00
|
|
|
return [self initWithCalendarIdentifier: nil];
|
2018-04-30 17:01:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
- (id) initWithCalendarIdentifier: (NSString *) identifier
|
2010-12-15 00:04:51 +00:00
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
NSAssert(0 == _NSCalendarInternal, NSInvalidArgumentException);
|
2020-04-26 19:13:22 +00:00
|
|
|
_NSCalendarInternal = NSZoneCalloc([self zone], sizeof(Calendar), 1);
|
2013-03-26 09:27:49 +00:00
|
|
|
|
|
|
|
my->firstWeekday = NSNotFound;
|
|
|
|
my->minimumDaysInFirstWeek = NSNotFound;
|
2020-04-26 19:13:22 +00:00
|
|
|
ASSIGN(my->identifier, identifier);
|
|
|
|
ASSIGN(my->tz, [NSTimeZone defaultTimeZone]);
|
|
|
|
[self setLocale: [NSLocale currentLocale]];
|
|
|
|
|
2010-12-16 02:57:31 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
if (0 != _NSCalendarInternal)
|
|
|
|
{
|
2011-01-28 00:23:57 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2013-03-26 09:27:49 +00:00
|
|
|
ucal_close (my->cal);
|
2011-01-28 00:23:57 +00:00
|
|
|
#endif
|
2013-03-26 09:27:49 +00:00
|
|
|
RELEASE(my->identifier);
|
|
|
|
RELEASE(my->localeID);
|
|
|
|
RELEASE(my->tz);
|
|
|
|
NSZoneFree([self zone], _NSCalendarInternal);
|
|
|
|
}
|
2010-12-16 02:57:31 +00:00
|
|
|
[super dealloc];
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) calendarIdentifier
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->identifier;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2022-04-05 03:57:10 +00:00
|
|
|
- (NSInteger) component: (NSCalendarUnit)unit
|
|
|
|
fromDate: (NSDate *)date
|
|
|
|
{
|
|
|
|
NSDateComponents *comps = [self components: unit
|
|
|
|
fromDate: date];
|
|
|
|
NSInteger val = 0;
|
|
|
|
|
|
|
|
switch (unit)
|
|
|
|
{
|
|
|
|
case NSCalendarUnitEra:
|
|
|
|
val = [comps era];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitYear:
|
|
|
|
val = [comps year];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitMonth:
|
|
|
|
val = [comps month];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitDay:
|
|
|
|
val = [comps day];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitHour:
|
|
|
|
val = [comps hour];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitMinute:
|
|
|
|
val = [comps minute];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitSecond:
|
|
|
|
val = [comps second];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitWeekday:
|
|
|
|
val = [comps weekday];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitWeekdayOrdinal:
|
|
|
|
val = [comps weekdayOrdinal];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitQuarter:
|
|
|
|
val = [comps quarter];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitWeekOfMonth:
|
|
|
|
val = [comps weekOfMonth];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitWeekOfYear:
|
|
|
|
val = [comps weekOfYear];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitYearForWeekOfYear:
|
|
|
|
val = [comps yearForWeekOfYear];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitNanosecond:
|
|
|
|
val = [comps nanosecond];
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitCalendar:
|
|
|
|
case NSCalendarUnitTimeZone:
|
|
|
|
// in these cases do nothing since they are undefined.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
2010-12-15 00:04:51 +00:00
|
|
|
|
|
|
|
- (NSDateComponents *) components: (NSUInteger) unitFlags
|
|
|
|
fromDate: (NSDate *) date
|
|
|
|
{
|
2011-01-23 17:10:21 +00:00
|
|
|
#if GS_USE_ICU == 1
|
|
|
|
NSDateComponents *comps;
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
UDate udate;
|
2020-04-26 19:13:22 +00:00
|
|
|
|
|
|
|
udate = (UDate)floor([date timeIntervalSince1970] * SECOND_TO_MILLI);
|
|
|
|
ucal_setMillis(my->cal, udate, &err);
|
2011-01-23 17:10:21 +00:00
|
|
|
if (U_FAILURE(err))
|
2020-04-25 22:32:49 +00:00
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-23 17:10:21 +00:00
|
|
|
comps = [[NSDateComponents alloc] init];
|
2020-04-25 22:32:49 +00:00
|
|
|
if (unitFlags & NSCalendarUnitEra)
|
|
|
|
{
|
|
|
|
[comps setEra: ucal_get(my->cal, UCAL_ERA, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitYear)
|
|
|
|
{
|
|
|
|
[comps setYear: ucal_get(my->cal, UCAL_YEAR, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitMonth)
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
[comps setMonth: ucal_get(my->cal, UCAL_MONTH, &err) + 1];
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitDay)
|
|
|
|
{
|
|
|
|
[comps setDay: ucal_get(my->cal, UCAL_DAY_OF_MONTH, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitHour)
|
|
|
|
{
|
|
|
|
[comps setHour: ucal_get(my->cal, UCAL_HOUR_OF_DAY, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitMinute)
|
|
|
|
{
|
|
|
|
[comps setMinute: ucal_get(my->cal, UCAL_MINUTE, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitSecond)
|
|
|
|
{
|
|
|
|
[comps setSecond: ucal_get(my->cal, UCAL_SECOND, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & (NSWeekCalendarUnit | NSCalendarUnitWeekOfYear))
|
|
|
|
{
|
|
|
|
[comps setWeek: ucal_get(my->cal, UCAL_WEEK_OF_YEAR, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitWeekday)
|
|
|
|
{
|
|
|
|
[comps setWeekday: ucal_get(my->cal, UCAL_DAY_OF_WEEK, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitWeekdayOrdinal)
|
|
|
|
{
|
|
|
|
[comps setWeekdayOrdinal:
|
|
|
|
ucal_get(my->cal, UCAL_DAY_OF_WEEK_IN_MONTH, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitQuarter)
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
[comps setQuarter: (ucal_get(my->cal, UCAL_MONTH, &err) + 3) / 3];
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitWeekOfMonth)
|
|
|
|
{
|
|
|
|
[comps setWeekOfMonth: ucal_get(my->cal, UCAL_WEEK_OF_MONTH, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitYearForWeekOfYear)
|
|
|
|
{
|
|
|
|
[comps setYearForWeekOfYear: ucal_get(my->cal, UCAL_YEAR_WOY, &err)];
|
|
|
|
}
|
|
|
|
if (unitFlags & NSCalendarUnitNanosecond)
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
[comps setNanosecond: ucal_get(my->cal, UCAL_MILLISECOND, &err) * MILLI_TO_NANO];
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-23 17:10:21 +00:00
|
|
|
return AUTORELEASE(comps);
|
|
|
|
#else
|
2010-12-15 00:04:51 +00:00
|
|
|
return nil;
|
2011-01-23 17:10:21 +00:00
|
|
|
#endif
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2015-11-30 10:06:04 +00:00
|
|
|
/*
|
|
|
|
* Convenience macro for field extraction.
|
2016-02-20 17:25:53 +00:00
|
|
|
* TODO: We need to implement NSWrapCalendarComponents,
|
|
|
|
* but it is unclear how that actually works.
|
2015-11-30 10:06:04 +00:00
|
|
|
*/
|
2016-02-20 17:25:53 +00:00
|
|
|
#define COMPONENT_DIFF( \
|
|
|
|
cal, units, components, toDate, nsunit, setSel, uunit, err) \
|
|
|
|
do \
|
2015-11-30 10:06:04 +00:00
|
|
|
{ \
|
2016-03-04 14:58:01 +00:00
|
|
|
if (nsunit == (units & nsunit)) \
|
2016-02-20 17:25:53 +00:00
|
|
|
{ \
|
|
|
|
int32_t uunit ## Diff \
|
|
|
|
= ucal_getFieldDifference(cal, toDate, uunit, &err); \
|
|
|
|
if (U_FAILURE(err)) \
|
|
|
|
{ \
|
|
|
|
RELEASE(components); \
|
|
|
|
return nil; \
|
|
|
|
} \
|
|
|
|
[components setSel uunit ## Diff]; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2015-11-30 10:06:04 +00:00
|
|
|
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
- (NSDateComponents *) components: (NSUInteger) unitFlags
|
|
|
|
fromDate: (NSDate *) startingDate
|
|
|
|
toDate: (NSDate *) resultDate
|
|
|
|
options: (NSUInteger) opts
|
|
|
|
{
|
2016-02-29 10:05:36 +00:00
|
|
|
#if GS_USE_ICU == 1 && (U_ICU_VERSION_MAJOR_NUM > 4 \
|
2022-02-18 16:00:14 +00:00
|
|
|
|| (U_ICU_VERSION_MAJOR_NUM == 4 && U_ICU_VERSION_MINOR_NUM >= 8) \
|
|
|
|
|| defined(HAVE_ICU_H))
|
2016-02-29 10:05:36 +00:00
|
|
|
|
2015-11-30 10:06:04 +00:00
|
|
|
NSDateComponents *comps = nil;
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
2020-04-26 19:13:22 +00:00
|
|
|
UDate udateFrom = (UDate)floor([startingDate timeIntervalSince1970] * SECOND_TO_MILLI);
|
|
|
|
UDate udateTo = (UDate)floor([resultDate timeIntervalSince1970] * SECOND_TO_MILLI);
|
2016-02-29 10:05:36 +00:00
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_setMillis(my->cal, udateFrom, &err);
|
2015-11-30 10:06:04 +00:00
|
|
|
if (U_FAILURE(err))
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
comps = [[NSDateComponents alloc] init];
|
|
|
|
/*
|
2016-02-20 17:25:53 +00:00
|
|
|
* Since the ICU field difference function automatically advances
|
|
|
|
* the calendar as appropriate, we need to process the units from
|
|
|
|
* the largest to the smallest.
|
2015-11-30 10:06:04 +00:00
|
|
|
*/
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitEra, setEra:, UCAL_ERA, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitYear, setYear:, UCAL_YEAR, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitMonth, setMonth:, UCAL_MONTH, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitWeekOfYear, setWeek:, UCAL_WEEK_OF_YEAR, err);
|
|
|
|
if (!(unitFlags & NSCalendarUnitWeekOfYear))
|
2015-11-30 10:06:04 +00:00
|
|
|
{
|
|
|
|
/* We must avoid setting the same unit twice (it would be zero because
|
|
|
|
* of the automatic advancement.
|
|
|
|
*/
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
|
|
|
NSWeekCalendarUnit, setWeek:, UCAL_WEEK_OF_YEAR, err);
|
2015-11-30 10:06:04 +00:00
|
|
|
}
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitWeekOfMonth, setWeekOfMonth:, UCAL_WEEK_OF_MONTH, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitDay, setDay:, UCAL_DAY_OF_MONTH, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitWeekdayOrdinal, setWeekdayOrdinal:,
|
2016-02-20 17:25:53 +00:00
|
|
|
UCAL_DAY_OF_WEEK_IN_MONTH, err);
|
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitWeekday, setWeekday:, UCAL_DAY_OF_WEEK, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitHour, setHour:, UCAL_HOUR_OF_DAY, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitMinute, setMinute:, UCAL_MINUTE, err);
|
2016-02-20 17:25:53 +00:00
|
|
|
COMPONENT_DIFF(my->cal, unitFlags, comps, udateTo,
|
2020-04-25 22:32:49 +00:00
|
|
|
NSCalendarUnitSecond, setSecond:, UCAL_SECOND, err);
|
2015-11-30 10:06:04 +00:00
|
|
|
if (unitFlags & NSCalendarUnitNanosecond)
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
int32_t ms;
|
2016-02-20 17:25:53 +00:00
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
ms = ucal_getFieldDifference(my->cal, udateTo, UCAL_MILLISECOND, &err);
|
2015-11-30 10:06:04 +00:00
|
|
|
if (U_FAILURE(err))
|
|
|
|
{
|
|
|
|
RELEASE(comps);
|
|
|
|
return nil;
|
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
[comps setNanosecond: ms * MILLI_TO_NANO];
|
2015-11-30 10:06:04 +00:00
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2015-11-30 10:06:04 +00:00
|
|
|
return AUTORELEASE(comps);
|
|
|
|
|
|
|
|
#else
|
2010-12-15 00:04:51 +00:00
|
|
|
return nil;
|
2015-11-30 10:06:04 +00:00
|
|
|
#endif
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
#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; \
|
|
|
|
}
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
- (NSDate *) dateByAddingComponents: (NSDateComponents *) comps
|
|
|
|
toDate: (NSDate *) date
|
|
|
|
options: (NSUInteger) opts
|
|
|
|
{
|
2010-12-31 22:22:10 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2016-03-04 14:58:01 +00:00
|
|
|
NSInteger amount;
|
2010-12-31 22:22:10 +00:00
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
UDate udate;
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-28 00:23:57 +00:00
|
|
|
[self _resetCalendar];
|
2020-04-26 19:13:22 +00:00
|
|
|
udate = (UDate)([date timeIntervalSince1970] * SECOND_TO_MILLI);
|
|
|
|
ucal_setMillis(my->cal, udate, &err);
|
|
|
|
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps era]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_ERA, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps year]) != NSDateComponentUndefined)
|
2013-01-24 09:15:53 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_YEAR, (int32_t)amount);
|
2013-01-24 09:15:53 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps month]) != NSDateComponentUndefined)
|
2013-01-24 09:15:53 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_MONTH, (int32_t)amount);
|
2013-01-24 09:15:53 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps day]) != NSDateComponentUndefined)
|
2013-01-24 09:15:53 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_DAY_OF_MONTH, (int32_t)amount);
|
2013-01-24 09:15:53 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps hour]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_HOUR_OF_DAY, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps minute]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_MINUTE, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps second]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_SECOND, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps week]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_WEEK_OF_YEAR, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps weekday]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_DAY_OF_WEEK, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps weekOfMonth]) != NSDateComponentUndefined)
|
2013-03-20 17:37:16 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_WEEK_OF_MONTH, (int32_t)amount);
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps yearForWeekOfYear]) != NSDateComponentUndefined)
|
2013-03-20 17:37:16 +00:00
|
|
|
{
|
2016-03-04 14:58:01 +00:00
|
|
|
_ADD_COMPONENT(UCAL_YEAR_WOY, (int32_t)amount);
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
if ((amount = [comps nanosecond]) != NSDateComponentUndefined)
|
|
|
|
{
|
|
|
|
_ADD_COMPONENT(UCAL_MILLISECOND, (int32_t)(amount / MILLI_TO_NANO));
|
|
|
|
}
|
|
|
|
|
|
|
|
udate = ucal_getMillis(my->cal, &err);
|
2010-12-31 22:22:10 +00:00
|
|
|
if (U_FAILURE(err))
|
2020-04-26 19:13:22 +00:00
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [NSDate dateWithTimeIntervalSince1970: (udate / SECOND_TO_MILLI)];
|
2010-12-31 22:22:10 +00:00
|
|
|
#else
|
2010-12-15 00:04:51 +00:00
|
|
|
return nil;
|
2010-12-31 22:22:10 +00:00
|
|
|
#endif
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-26 19:13:22 +00:00
|
|
|
#undef _ADD_COMPONENT
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
- (NSDate *) dateFromComponents: (NSDateComponents *) comps
|
|
|
|
{
|
2010-12-31 22:22:10 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2016-03-04 14:58:01 +00:00
|
|
|
NSInteger amount;
|
2010-12-31 22:22:10 +00:00
|
|
|
UDate udate;
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
2020-04-26 19:13:22 +00:00
|
|
|
void *cal;
|
|
|
|
NSTimeZone *timeZone;
|
|
|
|
|
|
|
|
timeZone = [comps timeZone];
|
|
|
|
if (timeZone == nil)
|
|
|
|
{
|
|
|
|
timeZone = [self timeZone];
|
|
|
|
}
|
|
|
|
cal = [self _openCalendarFor: timeZone];
|
|
|
|
if (!cal)
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
ucal_clear(cal);
|
|
|
|
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps era]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set(cal, UCAL_ERA, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps year]) != NSDateComponentUndefined)
|
2013-01-24 09:15:53 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_YEAR, (int32_t)amount);
|
2013-01-24 09:15:53 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps month]) != NSDateComponentUndefined)
|
2013-01-24 09:15:53 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_MONTH, amount - 1);
|
2013-01-24 09:15:53 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps day]) != NSDateComponentUndefined)
|
2013-01-24 09:15:53 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_DAY_OF_MONTH, (int32_t)amount);
|
2013-01-24 09:15:53 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps hour]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_HOUR_OF_DAY, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps minute]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_MINUTE, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps second]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_SECOND, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps week]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_WEEK_OF_YEAR, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps weekday]) != NSDateComponentUndefined)
|
2010-12-31 22:22:10 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_DAY_OF_WEEK, (int32_t)amount);
|
2010-12-31 22:22:10 +00:00
|
|
|
}
|
2020-04-25 22:32:49 +00:00
|
|
|
if ((amount = [comps weekdayOrdinal]) != NSDateComponentUndefined)
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_DAY_OF_WEEK_IN_MONTH, (int32_t)amount);
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps weekOfMonth]) != NSDateComponentUndefined)
|
2013-03-20 17:37:16 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_WEEK_OF_MONTH, (int32_t)amount);
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
2016-03-04 14:58:01 +00:00
|
|
|
if ((amount = [comps yearForWeekOfYear]) != NSDateComponentUndefined)
|
2013-03-20 17:37:16 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_YEAR_WOY, (int32_t)amount);
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
2020-04-25 22:32:49 +00:00
|
|
|
if ((amount = [comps nanosecond]) != NSDateComponentUndefined)
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_set (cal, UCAL_MILLISECOND, (int32_t)(amount / MILLI_TO_NANO));
|
2020-04-25 22:32:49 +00:00
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
|
|
|
udate = ucal_getMillis(cal, &err);
|
|
|
|
ucal_close(cal);
|
2010-12-31 22:22:10 +00:00
|
|
|
if (U_FAILURE(err))
|
2020-04-26 19:13:22 +00:00
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [NSDate dateWithTimeIntervalSince1970: (udate / SECOND_TO_MILLI)];
|
2010-12-31 22:22:10 +00:00
|
|
|
#else
|
2010-12-15 00:04:51 +00:00
|
|
|
return nil;
|
2010-12-31 22:22:10 +00:00
|
|
|
#endif
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSLocale *) locale
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return AUTORELEASE([[NSLocale alloc] initWithLocaleIdentifier: my->localeID]);
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
- (void) setLocale: (NSLocale *) locale
|
2010-12-15 00:04:51 +00:00
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
// 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.
|
2013-03-26 09:27:49 +00:00
|
|
|
[self _setLocaleIdentifier: [self _localeIDWithLocale: locale]];
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSUInteger) firstWeekday
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->firstWeekday;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
- (void) setFirstWeekday: (NSUInteger)weekday
|
2010-12-15 00:04:51 +00:00
|
|
|
{
|
2013-04-08 16:21:57 +00:00
|
|
|
my->firstWeekday = weekday;
|
2010-12-16 10:09:43 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_setAttribute(my->cal, UCAL_FIRST_DAY_OF_WEEK, my->firstWeekday);
|
2011-01-01 22:20:16 +00:00
|
|
|
#endif
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2010-12-16 02:57:31 +00:00
|
|
|
- (NSUInteger) minimumDaysInFirstWeek
|
2010-12-15 00:04:51 +00:00
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->minimumDaysInFirstWeek;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
- (void) setMinimumDaysInFirstWeek: (NSUInteger)mdw
|
2010-12-15 00:04:51 +00:00
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->minimumDaysInFirstWeek = (int32_t)mdw;
|
2010-12-16 10:09:43 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2020-04-26 19:13:22 +00:00
|
|
|
ucal_setAttribute(my->cal, UCAL_MINIMAL_DAYS_IN_FIRST_WEEK,
|
2013-03-26 09:27:49 +00:00
|
|
|
my->minimumDaysInFirstWeek);
|
2011-01-01 22:20:16 +00:00
|
|
|
#endif
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSTimeZone *) timeZone
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->tz;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setTimeZone: (NSTimeZone *) tz
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
if ([tz isEqual: my->tz])
|
2020-04-25 22:32:49 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2020-04-25 22:32:49 +00:00
|
|
|
ASSIGN(my->tz, tz);
|
2011-01-28 00:23:57 +00:00
|
|
|
[self _resetCalendar];
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) maximumRangeOfUnit: (NSCalendarUnit) unit
|
|
|
|
{
|
2020-04-25 22:32:49 +00:00
|
|
|
NSRange result = NSMakeRange (0, 0);
|
2010-12-17 02:15:55 +00:00
|
|
|
#if GS_USE_ICU == 1
|
|
|
|
UCalendarDateFields dateField;
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-28 00:23:57 +00:00
|
|
|
[self _resetCalendar];
|
2020-04-26 19:13:22 +00:00
|
|
|
dateField = _NSCalendarUnitToDateField(unit);
|
2020-05-12 12:35:18 +00:00
|
|
|
if (dateField != (UCalendarDateFields)-1)
|
2020-04-25 22:32:49 +00:00
|
|
|
{
|
|
|
|
// We really don't care if there are any errors...
|
|
|
|
result.location =
|
2020-04-26 19:13:22 +00:00
|
|
|
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_MINIMUM, &err);
|
2020-04-25 22:32:49 +00:00
|
|
|
result.length =
|
2020-04-26 19:13:22 +00:00
|
|
|
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_MAXIMUM, &err)
|
2020-04-25 22:32:49 +00:00
|
|
|
- result.location + 1;
|
|
|
|
// ICU's month is 0-based, while NSCalendar is 1-based
|
|
|
|
if (dateField == UCAL_MONTH)
|
|
|
|
{
|
|
|
|
result.location += 1;
|
|
|
|
}
|
|
|
|
}
|
2010-12-17 02:15:55 +00:00
|
|
|
#endif
|
2020-04-25 22:32:49 +00:00
|
|
|
|
|
|
|
return result;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) minimumRangeofUnit: (NSCalendarUnit) unit
|
|
|
|
{
|
2020-04-25 22:32:49 +00:00
|
|
|
NSRange result = NSMakeRange (0, 0);
|
2010-12-17 02:15:55 +00:00
|
|
|
#if GS_USE_ICU == 1
|
|
|
|
UCalendarDateFields dateField;
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-28 00:23:57 +00:00
|
|
|
[self _resetCalendar];
|
2020-04-26 19:13:22 +00:00
|
|
|
dateField = _NSCalendarUnitToDateField(unit);
|
2020-05-12 12:35:18 +00:00
|
|
|
if (dateField != (UCalendarDateFields)-1)
|
2020-04-25 22:32:49 +00:00
|
|
|
{
|
|
|
|
// We really don't care if there are any errors...
|
|
|
|
result.location =
|
2020-04-26 19:13:22 +00:00
|
|
|
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_GREATEST_MINIMUM, &err);
|
2020-04-25 22:32:49 +00:00
|
|
|
result.length =
|
2020-04-26 19:13:22 +00:00
|
|
|
(NSUInteger)ucal_getLimit(my->cal, dateField, UCAL_LEAST_MAXIMUM, &err)
|
2020-04-25 22:32:49 +00:00
|
|
|
- result.location + 1;
|
|
|
|
// ICU's month is 0-based, while NSCalendar is 1-based
|
|
|
|
if (dateField == UCAL_MONTH)
|
|
|
|
{
|
|
|
|
result.location += 1;
|
|
|
|
}
|
|
|
|
}
|
2010-12-17 02:15:55 +00:00
|
|
|
#endif
|
2020-04-25 22:32:49 +00:00
|
|
|
return result;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSUInteger) ordinalityOfUnit: (NSCalendarUnit) smaller
|
|
|
|
inUnit: (NSCalendarUnit) larger
|
|
|
|
forDate: (NSDate *) date
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRange) rangeOfUnit: (NSCalendarUnit) smaller
|
|
|
|
inUnit: (NSCalendarUnit) larger
|
|
|
|
forDate: (NSDate *) date
|
|
|
|
{
|
|
|
|
return NSMakeRange (0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL) rangeOfUnit: (NSCalendarUnit) unit
|
|
|
|
startDate: (NSDate **) datep
|
|
|
|
interval: (NSTimeInterval *)tip
|
2010-12-31 22:22:10 +00:00
|
|
|
forDate: (NSDate *)date
|
2010-12-15 00:04:51 +00:00
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
2011-01-02 03:47:29 +00:00
|
|
|
|
|
|
|
- (BOOL) isEqual: (id) obj
|
|
|
|
{
|
2011-01-28 00:49:16 +00:00
|
|
|
#if GS_USE_ICU == 1
|
2020-04-26 19:13:22 +00:00
|
|
|
return (BOOL)ucal_equivalentTo(my->cal, [obj _UCalendar]);
|
2011-01-28 00:49:16 +00:00
|
|
|
#else
|
2011-01-02 03:47:29 +00:00
|
|
|
if ([obj isKindOfClass: [self class]])
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
if (![my->identifier isEqual: [obj calendarIdentifier]])
|
2011-01-02 03:47:29 +00:00
|
|
|
return NO;
|
2013-03-26 09:27:49 +00:00
|
|
|
if (![my->localeID isEqual: [obj localeIdentifier]])
|
2011-01-02 03:47:29 +00:00
|
|
|
return NO;
|
2013-03-26 09:27:49 +00:00
|
|
|
if (![my->tz isEqual: [obj timeZone]])
|
2011-01-02 03:47:29 +00:00
|
|
|
return NO;
|
2020-04-26 19:13:22 +00:00
|
|
|
if (my->firstWeekday != [obj firstWeekday])
|
|
|
|
return NO;
|
|
|
|
if (my->minimumDaysInFirstWeek != [obj minimumDaysInFirstWeek])
|
|
|
|
return NO;
|
2011-01-02 03:47:29 +00:00
|
|
|
return YES;
|
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-02 03:47:29 +00:00
|
|
|
return NO;
|
2011-01-28 00:49:16 +00:00
|
|
|
#endif
|
2011-01-02 03:47:29 +00:00
|
|
|
}
|
|
|
|
|
2022-04-04 23:26:22 +00:00
|
|
|
|
|
|
|
- (void) getEra: (NSInteger *)eraValuePointer
|
|
|
|
year: (NSInteger *)yearValuePointer
|
|
|
|
month: (NSInteger *)monthValuePointer
|
|
|
|
day: (NSInteger *)dayValuePointer
|
|
|
|
fromDate: (NSDate *)date
|
|
|
|
{
|
|
|
|
#if GS_USE_ICU == 1
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
UDate udate;
|
|
|
|
[self _resetCalendar];
|
|
|
|
ucal_clear (my->cal);
|
|
|
|
|
|
|
|
udate = (UDate)floor([date timeIntervalSince1970] * 1000.0);
|
|
|
|
ucal_setMillis (my->cal, udate, &err);
|
|
|
|
if (U_FAILURE(err))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (eraValuePointer != NULL)
|
|
|
|
*eraValuePointer = ucal_get(my->cal, UCAL_ERA, &err);
|
|
|
|
if (yearValuePointer != NULL)
|
|
|
|
*yearValuePointer = ucal_get(my->cal, UCAL_YEAR, &err);
|
|
|
|
if (monthValuePointer != NULL)
|
|
|
|
*monthValuePointer = ucal_get(my->cal, UCAL_MONTH, &err) + 1;
|
|
|
|
if (dayValuePointer != NULL)
|
|
|
|
*dayValuePointer = ucal_get(my->cal, UCAL_DAY_OF_MONTH, &err);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) getHour: (NSInteger *)hourValuePointer
|
|
|
|
minute: (NSInteger *)minuteValuePointer
|
|
|
|
second: (NSInteger *)secondValuePointer
|
|
|
|
nanosecond: (NSInteger *)nanosecondValuePointer
|
|
|
|
fromDate: (NSDate *)date
|
|
|
|
{
|
|
|
|
#if GS_USE_ICU == 1
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
UDate udate;
|
|
|
|
[self _resetCalendar];
|
|
|
|
ucal_clear (my->cal);
|
|
|
|
|
|
|
|
udate = (UDate)floor([date timeIntervalSince1970] * 1000.0);
|
|
|
|
ucal_setMillis (my->cal, udate, &err);
|
|
|
|
if (U_FAILURE(err))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (hourValuePointer != NULL)
|
|
|
|
*hourValuePointer = ucal_get(my->cal, UCAL_HOUR_OF_DAY, &err);
|
|
|
|
if (minuteValuePointer != NULL)
|
|
|
|
*minuteValuePointer = ucal_get(my->cal, UCAL_MINUTE, &err);
|
|
|
|
if (secondValuePointer != NULL)
|
|
|
|
*secondValuePointer = ucal_get(my->cal, UCAL_SECOND, &err);
|
|
|
|
if (nanosecondValuePointer != NULL)
|
|
|
|
*nanosecondValuePointer = ucal_get(my->cal, UCAL_MILLISECOND, &err) * 1000;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) getEra: (NSInteger *)eraValuePointer
|
|
|
|
yearForWeekOfYear: (NSInteger *)yearValuePointer
|
|
|
|
weekOfYear: (NSInteger *)weekValuePointer
|
|
|
|
weekday: (NSInteger *)weekdayValuePointer
|
|
|
|
fromDate: (NSDate *)date
|
|
|
|
{
|
|
|
|
#if GS_USE_ICU == 1
|
|
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
UDate udate;
|
|
|
|
[self _resetCalendar];
|
|
|
|
ucal_clear (my->cal);
|
|
|
|
|
|
|
|
udate = (UDate)floor([date timeIntervalSince1970] * 1000.0);
|
|
|
|
ucal_setMillis (my->cal, udate, &err);
|
|
|
|
if (U_FAILURE(err))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (eraValuePointer != NULL)
|
|
|
|
*eraValuePointer = ucal_get(my->cal, UCAL_ERA, &err);
|
|
|
|
if (yearValuePointer != NULL)
|
|
|
|
*yearValuePointer = ucal_get(my->cal, UCAL_YEAR_WOY, &err);
|
|
|
|
if (weekValuePointer != NULL)
|
|
|
|
*weekValuePointer = ucal_get(my->cal, UCAL_WEEK_OF_YEAR, &err);
|
|
|
|
if (weekdayValuePointer != NULL)
|
|
|
|
*weekdayValuePointer = ucal_get(my->cal, UCAL_DAY_OF_WEEK, &err);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-01-02 03:47:29 +00:00
|
|
|
- (void) encodeWithCoder: (NSCoder*)encoder
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
[encoder encodeObject: my->identifier];
|
|
|
|
[encoder encodeObject: my->localeID];
|
|
|
|
[encoder encodeObject: my->tz];
|
2011-01-02 03:47:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id) initWithCoder: (NSCoder*)decoder
|
|
|
|
{
|
|
|
|
NSString *s = [decoder decodeObject];
|
|
|
|
|
|
|
|
[self initWithCalendarIdentifier: s];
|
|
|
|
[self _setLocaleIdentifier: [decoder decodeObject]];
|
|
|
|
[self setTimeZone: [decoder decodeObject]];
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-02 03:47:29 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) copyWithZone: (NSZone*)zone
|
|
|
|
{
|
|
|
|
NSCalendar *result;
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-02 03:47:29 +00:00
|
|
|
if (NSShouldRetainWithZone(self, zone))
|
2013-03-26 09:27:49 +00:00
|
|
|
{
|
|
|
|
return RETAIN(self);
|
|
|
|
}
|
2011-01-02 03:47:29 +00:00
|
|
|
else
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
result = [[[self class] allocWithZone: zone]
|
|
|
|
initWithCalendarIdentifier: my->identifier];
|
|
|
|
[result _setLocaleIdentifier: my->localeID];
|
|
|
|
[result setTimeZone: my->tz];
|
2011-01-02 03:47:29 +00:00
|
|
|
}
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2011-01-02 03:47:29 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
@end
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
#undef my
|
2010-12-15 00:04:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
@implementation NSDateComponents
|
|
|
|
|
2013-03-20 17:37:16 +00:00
|
|
|
typedef struct {
|
|
|
|
NSInteger era;
|
|
|
|
NSInteger year;
|
|
|
|
NSInteger month;
|
|
|
|
NSInteger day;
|
|
|
|
NSInteger hour;
|
|
|
|
NSInteger minute;
|
|
|
|
NSInteger second;
|
|
|
|
NSInteger week;
|
|
|
|
NSInteger weekday;
|
|
|
|
NSInteger weekdayOrdinal;
|
|
|
|
NSInteger quarter;
|
|
|
|
NSInteger weekOfMonth;
|
|
|
|
NSInteger yearForWeekOfYear;
|
2020-04-25 20:19:20 +00:00
|
|
|
BOOL leapMonth;
|
|
|
|
NSInteger nanosecond;
|
2013-03-20 17:37:16 +00:00
|
|
|
NSCalendar *cal;
|
|
|
|
NSTimeZone *tz;
|
|
|
|
} DateComp;
|
|
|
|
|
2013-03-26 09:27:49 +00:00
|
|
|
#define my ((DateComp*)_NSDateComponentsInternal)
|
2013-03-20 17:37:16 +00:00
|
|
|
|
|
|
|
- (void) dealloc
|
|
|
|
{
|
|
|
|
if (0 != _NSDateComponentsInternal)
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
RELEASE(my->cal);
|
|
|
|
RELEASE(my->tz);
|
|
|
|
NSZoneFree([self zone], _NSDateComponentsInternal);
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
- (id) init
|
|
|
|
{
|
2013-03-20 17:37:16 +00:00
|
|
|
if (nil != (self = [super init]))
|
|
|
|
{
|
2020-04-26 19:13:22 +00:00
|
|
|
_NSDateComponentsInternal =
|
2016-03-25 11:15:28 +00:00
|
|
|
NSZoneCalloc([self zone], sizeof(DateComp), 1);
|
2013-03-26 09:27:49 +00:00
|
|
|
|
2016-03-04 14:58:01 +00:00
|
|
|
my->era = NSDateComponentUndefined;
|
|
|
|
my->year = NSDateComponentUndefined;
|
|
|
|
my->month = NSDateComponentUndefined;
|
|
|
|
my->day = NSDateComponentUndefined;
|
|
|
|
my->hour = NSDateComponentUndefined;
|
|
|
|
my->minute = NSDateComponentUndefined;
|
|
|
|
my->second = NSDateComponentUndefined;
|
|
|
|
my->week = NSDateComponentUndefined;
|
|
|
|
my->weekday = NSDateComponentUndefined;
|
|
|
|
my->weekdayOrdinal = NSDateComponentUndefined;
|
|
|
|
my->quarter = NSDateComponentUndefined;
|
|
|
|
my->weekOfMonth = NSDateComponentUndefined;
|
|
|
|
my->yearForWeekOfYear = NSDateComponentUndefined;
|
2020-04-25 20:19:20 +00:00
|
|
|
my->leapMonth = NO;
|
|
|
|
my->nanosecond = NSDateComponentUndefined;
|
2013-03-26 09:27:49 +00:00
|
|
|
my->cal = NULL;
|
|
|
|
my->tz = NULL;
|
2020-04-26 19:13:22 +00:00
|
|
|
}
|
2010-12-15 00:04:51 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) day
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->day;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) era
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->era;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) hour
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->hour;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) minute
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->minute;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) month
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->month;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) quarter
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->quarter;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) second
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->second;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 20:19:20 +00:00
|
|
|
- (NSInteger) nanosecond
|
|
|
|
{
|
|
|
|
return my->nanosecond;
|
|
|
|
}
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
- (NSInteger) week
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->week;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) weekday
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->weekday;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) weekdayOrdinal
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->weekdayOrdinal;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) year
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->year;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2013-03-20 17:37:16 +00:00
|
|
|
- (NSInteger) weekOfMonth
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->weekOfMonth;
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) weekOfYear
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->week;
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger) yearForWeekOfYear
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->yearForWeekOfYear;
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 20:19:20 +00:00
|
|
|
- (BOOL) leapMonth
|
|
|
|
{
|
|
|
|
return my->leapMonth;
|
|
|
|
}
|
|
|
|
|
2010-12-31 18:13:39 +00:00
|
|
|
- (NSCalendar *) calendar
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->cal;
|
2010-12-31 18:13:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSTimeZone *) timeZone
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
return my->tz;
|
2010-12-31 18:13:39 +00:00
|
|
|
}
|
|
|
|
|
2013-03-20 17:37:16 +00:00
|
|
|
- (NSDate *) date
|
|
|
|
{
|
|
|
|
NSCalendar* cal = [self calendar];
|
|
|
|
|
|
|
|
return [cal dateFromComponents: self];
|
|
|
|
}
|
2010-12-15 00:04:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
- (void) setDay: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->day = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setEra: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->era = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setHour: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->hour = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setMinute: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->minute = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setMonth: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->month = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setQuarter: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->quarter = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setSecond: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->second = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 20:19:20 +00:00
|
|
|
- (void) setNanosecond: (NSInteger) v
|
|
|
|
{
|
|
|
|
my->nanosecond = v;
|
|
|
|
}
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
- (void) setWeek: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->week = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setWeekday: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->weekday = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setWeekdayOrdinal: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->weekdayOrdinal = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setYear: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->year = v;
|
2010-12-15 00:04:51 +00:00
|
|
|
}
|
|
|
|
|
2013-03-20 17:37:16 +00:00
|
|
|
- (void) setWeekOfYear: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->week = v;
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setWeekOfMonth: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->weekOfMonth = v;
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setYearForWeekOfYear: (NSInteger) v
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
my->yearForWeekOfYear = v;
|
2013-03-20 17:37:16 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 20:19:20 +00:00
|
|
|
- (void) setLeapMonth: (BOOL) v
|
|
|
|
{
|
|
|
|
my->leapMonth = v;
|
|
|
|
}
|
|
|
|
|
2010-12-31 18:13:39 +00:00
|
|
|
- (void) setCalendar: (NSCalendar *) cal
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
ASSIGN(my->cal, cal);
|
2010-12-31 18:13:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setTimeZone: (NSTimeZone *) tz
|
|
|
|
{
|
2013-03-26 09:27:49 +00:00
|
|
|
ASSIGN(my->tz, tz);
|
2010-12-31 18:13:39 +00:00
|
|
|
}
|
|
|
|
|
2020-04-25 20:19:20 +00:00
|
|
|
- (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;
|
2020-04-26 19:13:22 +00:00
|
|
|
case NSWeekCalendarUnit: return my->week;
|
2020-04-25 20:19:20 +00:00
|
|
|
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;
|
2020-04-26 19:13:22 +00:00
|
|
|
case NSWeekCalendarUnit:
|
|
|
|
my->week = value;
|
|
|
|
break;
|
2020-04-25 20:19:20 +00:00
|
|
|
case NSCalendarUnitYearForWeekOfYear:
|
|
|
|
my->yearForWeekOfYear = value;
|
|
|
|
break;
|
|
|
|
case NSCalendarUnitNanosecond:
|
|
|
|
my->nanosecond = value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-22 18:10:33 +00:00
|
|
|
- (id) copyWithZone: (NSZone*)zone
|
|
|
|
{
|
|
|
|
if (NSShouldRetainWithZone(self, zone))
|
2013-03-26 09:27:49 +00:00
|
|
|
{
|
|
|
|
return RETAIN(self);
|
|
|
|
}
|
2010-12-22 18:10:33 +00:00
|
|
|
else
|
2013-03-20 17:37:16 +00:00
|
|
|
{
|
|
|
|
NSDateComponents *c = [[NSDateComponents allocWithZone: zone] init];
|
2020-04-26 19:13:22 +00:00
|
|
|
|
2013-03-20 17:37:16 +00:00
|
|
|
memcpy(c->_NSDateComponentsInternal, _NSDateComponentsInternal,
|
|
|
|
sizeof(DateComp));
|
2013-03-20 17:47:55 +00:00
|
|
|
/* We gave objects to the copy, so we need to retain them too.
|
|
|
|
*/
|
2013-03-26 09:27:49 +00:00
|
|
|
RETAIN(my->cal);
|
|
|
|
RETAIN(my->tz);
|
2013-03-20 17:37:16 +00:00
|
|
|
return c;
|
|
|
|
}
|
2010-12-22 18:10:33 +00:00
|
|
|
}
|
|
|
|
|
2010-12-15 00:04:51 +00:00
|
|
|
@end
|