mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-24 01:11:01 +00:00
1068 lines
22 KiB
Objective-C
1068 lines
22 KiB
Objective-C
/** Implementation of NSDateFormatter class
|
|
Copyright (C) 1998 Free Software Foundation, Inc.
|
|
|
|
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
|
|
Created: December 1998
|
|
|
|
This file is part of the GNUstep Base Library.
|
|
|
|
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; if not, write to the Free
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110 USA.
|
|
|
|
<title>NSDateFormatter class reference</title>
|
|
$Date$ $Revision$
|
|
*/
|
|
|
|
#define GS_NSDateFormatter_IVARS \
|
|
NSUInteger _behavior; \
|
|
NSLocale *_locale; \
|
|
NSTimeZone *_tz; \
|
|
NSDateFormatterStyle _timeStyle; \
|
|
NSDateFormatterStyle _dateStyle; \
|
|
void *_formatter
|
|
|
|
#define EXPOSE_NSDateFormatter_IVARS 1
|
|
#import "common.h"
|
|
#import "Foundation/NSArray.h"
|
|
#import "Foundation/NSDate.h"
|
|
#import "Foundation/NSDictionary.h"
|
|
#import "Foundation/NSCalendar.h"
|
|
#import "Foundation/NSCalendarDate.h"
|
|
#import "Foundation/NSLocale.h"
|
|
#import "Foundation/NSTimeZone.h"
|
|
#import "Foundation/NSFormatter.h"
|
|
#import "Foundation/NSDateFormatter.h"
|
|
#import "Foundation/NSCoder.h"
|
|
|
|
#if defined(HAVE_UNICODE_UDAT_H) && defined(HAVE_UNICODE_UDATPG_H)
|
|
#define id id_ucal
|
|
#include <unicode/udat.h>
|
|
#undef id
|
|
#include <unicode/udatpg.h>
|
|
#elif defined(HAVE_ICU_H)
|
|
#include <icu.h>
|
|
#endif
|
|
|
|
|
|
|
|
// This is defined to be the same as UDAT_RELATIVE
|
|
#define FormatterDoesRelativeDateFormatting (1<<16)
|
|
#define BUFFER_SIZE 1024
|
|
|
|
@interface NSDateFormatter (PrivateMethods)
|
|
- (void) _resetUDateFormat;
|
|
- (void) _setSymbols: (NSArray *)array : (NSInteger)symbol;
|
|
- (NSArray *) _getSymbols: (NSInteger)symbol;
|
|
@end
|
|
|
|
static inline NSInteger
|
|
NSToUDateFormatStyle (NSDateFormatterStyle style)
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
NSInteger relative =
|
|
(style & FormatterDoesRelativeDateFormatting) ? UDAT_RELATIVE : 0;
|
|
switch (style)
|
|
{
|
|
case NSDateFormatterNoStyle:
|
|
return (relative | UDAT_NONE);
|
|
case NSDateFormatterShortStyle:
|
|
return (relative | UDAT_SHORT);
|
|
case NSDateFormatterMediumStyle:
|
|
return (relative | UDAT_MEDIUM);
|
|
case NSDateFormatterLongStyle:
|
|
return (relative | UDAT_LONG);
|
|
case NSDateFormatterFullStyle:
|
|
return (relative | UDAT_FULL);
|
|
}
|
|
#endif
|
|
return -1;
|
|
}
|
|
|
|
|
|
#define GSInternal NSDateFormatterInternal
|
|
#include "GSInternal.h"
|
|
GS_PRIVATE_INTERNAL(NSDateFormatter)
|
|
|
|
|
|
@implementation NSDateFormatter
|
|
|
|
static NSDateFormatterBehavior _defaultBehavior = 0;
|
|
|
|
- (id) init
|
|
{
|
|
self = [super init];
|
|
if (self == nil)
|
|
return nil;
|
|
|
|
GS_CREATE_INTERNAL(NSDateFormatter)
|
|
|
|
internal->_behavior = _defaultBehavior;
|
|
internal->_locale = RETAIN([NSLocale currentLocale]);
|
|
internal->_tz = RETAIN([NSTimeZone defaultTimeZone]);
|
|
|
|
[self _resetUDateFormat];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (BOOL) allowsNaturalLanguage
|
|
{
|
|
return _allowsNaturalLanguage;
|
|
}
|
|
|
|
- (NSAttributedString*) attributedStringForObjectValue: (id)anObject
|
|
withDefaultAttributes: (NSDictionary*)attr
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
- (id) copyWithZone: (NSZone*)zone
|
|
{
|
|
NSDateFormatter *o = (id)NSCopyObject(self, 0, zone);
|
|
|
|
IF_NO_ARC(RETAIN(o->_dateFormat);)
|
|
if (0 != internal)
|
|
{
|
|
GS_COPY_INTERNAL(o, zone)
|
|
IF_NO_ARC(RETAIN(GSIVar(o,_locale));)
|
|
#if GS_USE_ICU == 1
|
|
{
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
GSIVar(o,_formatter) = udat_clone (internal->_formatter, &err);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return o;
|
|
}
|
|
|
|
- (NSString*) dateFormat
|
|
{
|
|
return _dateFormat;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
RELEASE(_dateFormat);
|
|
if (internal != 0)
|
|
{
|
|
RELEASE(internal->_locale);
|
|
RELEASE(internal->_tz);
|
|
#if GS_USE_ICU == 1
|
|
udat_close (internal->_formatter);
|
|
#endif
|
|
GS_DESTROY_INTERNAL(NSDateFormatter)
|
|
}
|
|
[super dealloc];
|
|
}
|
|
|
|
- (NSString*) editingStringForObjectValue: (id)anObject
|
|
{
|
|
return [self stringForObjectValue: anObject];
|
|
}
|
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
|
{
|
|
[aCoder encodeValuesOfObjCTypes: "@C", &_dateFormat, &_allowsNaturalLanguage];
|
|
}
|
|
|
|
- (BOOL) getObjectValue: (id*)anObject
|
|
forString: (NSString*)string
|
|
errorDescription: (NSString**)error
|
|
{
|
|
NSCalendarDate *d;
|
|
|
|
if ([string length] == 0)
|
|
{
|
|
d = nil;
|
|
}
|
|
else
|
|
{
|
|
d = [NSCalendarDate dateWithString: string calendarFormat: _dateFormat];
|
|
}
|
|
if (d == nil)
|
|
{
|
|
if (_allowsNaturalLanguage)
|
|
{
|
|
d = [NSCalendarDate dateWithNaturalLanguageString: string];
|
|
}
|
|
if (d == nil)
|
|
{
|
|
if (error)
|
|
{
|
|
*error = @"Couldn't convert to date";
|
|
}
|
|
return NO;
|
|
}
|
|
}
|
|
if (anObject)
|
|
{
|
|
*anObject = d;
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
- (id) initWithCoder: (NSCoder*)aCoder
|
|
{
|
|
GS_CREATE_INTERNAL(NSDateFormatter)
|
|
|
|
[aCoder decodeValuesOfObjCTypes: "@C", &_dateFormat, &_allowsNaturalLanguage];
|
|
return self;
|
|
}
|
|
|
|
- (id) initWithDateFormat: (NSString *)format
|
|
allowNaturalLanguage: (BOOL)flag
|
|
{
|
|
self = [self init];
|
|
if (self == nil)
|
|
return nil;
|
|
|
|
[self setDateFormat: format];
|
|
_allowsNaturalLanguage = flag;
|
|
internal->_behavior = NSDateFormatterBehavior10_0;
|
|
return self;
|
|
}
|
|
|
|
- (BOOL) isPartialStringValid: (NSString*)partialString
|
|
newEditingString: (NSString**)newString
|
|
errorDescription: (NSString**)error
|
|
{
|
|
if (newString)
|
|
{
|
|
*newString = nil;
|
|
}
|
|
if (error)
|
|
{
|
|
*error = nil;
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
- (NSString*) stringForObjectValue: (id)anObject
|
|
{
|
|
if ([anObject isKindOfClass: [NSDate class]] == NO)
|
|
{
|
|
return nil;
|
|
}
|
|
return [anObject descriptionWithCalendarFormat: _dateFormat
|
|
timeZone: [NSTimeZone defaultTimeZone]
|
|
locale: nil];
|
|
}
|
|
|
|
|
|
|
|
+ (NSDateFormatterBehavior) defaultFormatterBehavior
|
|
{
|
|
return _defaultBehavior;
|
|
}
|
|
|
|
+ (void) setDefaultFormatterBehavior: (NSDateFormatterBehavior)behavior
|
|
{
|
|
_defaultBehavior = behavior;
|
|
}
|
|
|
|
- (NSDateFormatterBehavior) formatterBehavior
|
|
{
|
|
return internal->_behavior;
|
|
}
|
|
|
|
- (void) setFormatterBehavior: (NSDateFormatterBehavior)behavior
|
|
{
|
|
internal->_behavior = behavior;
|
|
}
|
|
|
|
- (BOOL) generatesCalendarDates
|
|
{
|
|
return NO; // FIXME
|
|
}
|
|
|
|
- (void) setGeneratesCalendarDates: (BOOL)flag
|
|
{
|
|
return; // FIXME
|
|
}
|
|
|
|
- (BOOL) isLenient
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return (BOOL)udat_isLenient (internal->_formatter);
|
|
#else
|
|
return NO;
|
|
#endif
|
|
}
|
|
|
|
- (void) setLenient: (BOOL)flag
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
udat_setLenient (internal->_formatter, flag);
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
|
|
- (NSDate *) dateFromString: (NSString *) string
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
NSDate *result = nil;
|
|
UDate date;
|
|
UChar *text;
|
|
int32_t textLength;
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
int32_t pPos = 0;
|
|
|
|
textLength = [string length];
|
|
text = malloc(sizeof(UChar) * textLength);
|
|
if (text == NULL)
|
|
return nil;
|
|
|
|
[string getCharacters: text range: NSMakeRange (0, textLength)];
|
|
|
|
date = udat_parse (internal->_formatter, text, textLength, &pPos, &err);
|
|
if (U_SUCCESS(err))
|
|
result =
|
|
[NSDate dateWithTimeIntervalSince1970: (NSTimeInterval)(date / 1000.0)];
|
|
|
|
free(text);
|
|
return result;
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (NSString *) stringFromDate: (NSDate *) date
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
NSString *result;
|
|
int32_t length;
|
|
unichar *string;
|
|
UDate udate = [date timeIntervalSince1970] * 1000.0;
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
length = udat_format (internal->_formatter, udate, NULL, 0, NULL, &err);
|
|
string = malloc(sizeof(UChar) * (length + 1));
|
|
err = U_ZERO_ERROR;
|
|
udat_format (internal->_formatter, udate, string, length, NULL, &err);
|
|
if (U_SUCCESS(err))
|
|
{
|
|
result = AUTORELEASE([[NSString allocWithZone: NSDefaultMallocZone()]
|
|
initWithBytesNoCopy: string
|
|
length: length * sizeof(UChar)
|
|
encoding: NSUnicodeStringEncoding
|
|
freeWhenDone: YES]);
|
|
return result;
|
|
}
|
|
|
|
free(string);
|
|
return nil;
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (BOOL) getObjectValue: (out id *) obj
|
|
forString: (NSString *) string
|
|
range: (inout NSRange *) range
|
|
error: (out NSError **) error
|
|
{
|
|
return NO; // FIXME
|
|
}
|
|
|
|
- (void) setDateFormat: (NSString *)string
|
|
{
|
|
ASSIGNCOPY(_dateFormat, string);
|
|
[self _resetUDateFormat];
|
|
}
|
|
|
|
- (NSDateFormatterStyle) dateStyle
|
|
{
|
|
return internal->_dateStyle;
|
|
}
|
|
|
|
- (void) setDateStyle: (NSDateFormatterStyle)style
|
|
{
|
|
internal->_dateStyle = style;
|
|
[self _resetUDateFormat];
|
|
}
|
|
|
|
- (NSDateFormatterStyle) timeStyle
|
|
{
|
|
return internal->_timeStyle;
|
|
}
|
|
|
|
- (void) setTimeStyle: (NSDateFormatterStyle)style
|
|
{
|
|
internal->_timeStyle = style;
|
|
[self _resetUDateFormat];
|
|
}
|
|
|
|
- (NSCalendar *) calendar
|
|
{
|
|
return [internal->_locale objectForKey: NSLocaleCalendar];
|
|
}
|
|
|
|
- (void) setCalendar: (NSCalendar *)calendar
|
|
{
|
|
NSMutableDictionary *dict;
|
|
NSLocale *locale;
|
|
|
|
dict = [[NSLocale componentsFromLocaleIdentifier:
|
|
[internal->_locale localeIdentifier]] mutableCopy];
|
|
[dict setValue: calendar forKey: NSLocaleCalendar];
|
|
locale = [[NSLocale alloc] initWithLocaleIdentifier:
|
|
[NSLocale localeIdentifierFromComponents: dict]];
|
|
[self setLocale: locale];
|
|
/* Don't have to use udat_setCalendar here because -setLocale: will take care
|
|
of setting the calendar when it resets the formatter. */
|
|
RELEASE(locale);
|
|
RELEASE(dict);
|
|
}
|
|
|
|
- (NSDate *) defaultDate
|
|
{
|
|
return nil; // FIXME
|
|
}
|
|
|
|
- (void) setDefaultDate: (NSDate *)date
|
|
{
|
|
return; // FIXME
|
|
}
|
|
|
|
- (NSLocale *) locale
|
|
{
|
|
return internal->_locale;
|
|
}
|
|
|
|
- (void) setLocale: (NSLocale *)locale
|
|
{
|
|
if (locale == internal->_locale)
|
|
return;
|
|
RELEASE(internal->_locale);
|
|
|
|
internal->_locale = RETAIN(locale);
|
|
[self _resetUDateFormat];
|
|
}
|
|
|
|
- (NSTimeZone *) timeZone
|
|
{
|
|
return internal->_tz;
|
|
}
|
|
|
|
- (void) setTimeZone: (NSTimeZone *)tz
|
|
{
|
|
if (tz == internal->_tz)
|
|
return;
|
|
RELEASE(internal->_tz);
|
|
|
|
internal->_tz = RETAIN(tz);
|
|
[self _resetUDateFormat];
|
|
}
|
|
|
|
- (NSDate *) twoDigitStartDate
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
return [NSDate dateWithTimeIntervalSince1970:
|
|
(udat_get2DigitYearStart (internal->_formatter, &err) / 1000.0)];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setTwoDigitStartDate: (NSDate *)date
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
udat_set2DigitYearStart (internal->_formatter,
|
|
([date timeIntervalSince1970] * 1000.0),
|
|
&err);
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
|
|
- (NSString *) AMSymbol
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
NSArray *array = [self _getSymbols: UDAT_AM_PMS];
|
|
|
|
return [array objectAtIndex: 0];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setAMSymbol: (NSString *) string
|
|
{
|
|
return;
|
|
}
|
|
|
|
- (NSString *) PMSymbol
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
NSArray *array = [self _getSymbols: UDAT_AM_PMS];
|
|
|
|
return [array objectAtIndex: 1];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setPMSymbol: (NSString *)string
|
|
{
|
|
return;
|
|
}
|
|
|
|
- (NSArray *) weekdaySymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_WEEKDAYS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setWeekdaySymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_WEEKDAYS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) shortWeekdaySymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_SHORT_WEEKDAYS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setShortWeekdaySymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_SHORT_WEEKDAYS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) monthSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_MONTHS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setMonthSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_MONTHS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) shortMonthSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_SHORT_MONTHS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setShortMonthSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_SHORT_MONTHS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) eraSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_ERAS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setEraSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_ERAS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSDate *) gregorianStartDate
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
- (void) setGregorianStartDate: (NSDate *)date
|
|
{
|
|
return;
|
|
}
|
|
|
|
- (NSArray *) longEraSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_ERA_NAMES];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setLongEraSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_ERA_NAMES];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
|
|
- (NSArray *) quarterSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_QUARTERS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setQuarterSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_QUARTERS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) shortQuarterSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_SHORT_QUARTERS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setShortQuarterSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_SHORT_QUARTERS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) standaloneQuarterSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_QUARTERS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setStandaloneQuarterSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_QUARTERS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) shortStandaloneQuarterSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_SHORT_QUARTERS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setShortStandaloneQuarterSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_SHORT_QUARTERS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) shortStandaloneMonthSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_SHORT_MONTHS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setShortStandaloneMonthSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_SHORT_MONTHS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) standaloneMonthSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_MONTHS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setStandaloneMonthSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_MONTHS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) veryShortMonthSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_NARROW_MONTHS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setVeryShortMonthSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_NARROW_MONTHS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) veryShortStandaloneMonthSymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_NARROW_MONTHS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setVeryShortStandaloneMonthSymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_NARROW_MONTHS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) shortStandaloneWeekdaySymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_SHORT_WEEKDAYS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setShortStandaloneWeekdaySymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_SHORT_WEEKDAYS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) standaloneWeekdaySymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_WEEKDAYS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setStandaloneWeekdaySymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_WEEKDAYS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) veryShortWeekdaySymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_SHORT_WEEKDAYS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setVeryShortWeekdaySymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_SHORT_WEEKDAYS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
- (NSArray *) veryShortStandaloneWeekdaySymbols
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
return [self _getSymbols: UDAT_STANDALONE_NARROW_WEEKDAYS];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (void) setVeryShortStandaloneWeekdaySymbols: (NSArray *)array
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
[self _setSymbols: array : UDAT_STANDALONE_NARROW_WEEKDAYS];
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
+ (NSString *) localizedStringFromDate: (NSDate *) date
|
|
dateStyle: (NSDateFormatterStyle) dateStyle
|
|
timeStyle: (NSDateFormatterStyle) timeStyle
|
|
{
|
|
NSString *result;
|
|
NSDateFormatter *fmt = [[self alloc] init];
|
|
|
|
[fmt setDateStyle: dateStyle];
|
|
[fmt setTimeStyle: timeStyle];
|
|
|
|
result = [fmt stringFromDate: date];
|
|
RELEASE(fmt);
|
|
|
|
return result;
|
|
}
|
|
|
|
+ (NSString *) dateFormatFromTemplate: (NSString *) aTemplate
|
|
options: (NSUInteger) opts
|
|
locale: (NSLocale *) locale
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
unichar pat[BUFFER_SIZE];
|
|
unichar skel[BUFFER_SIZE];
|
|
int32_t patLen;
|
|
int32_t skelLen;
|
|
UDateTimePatternGenerator *datpg;
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
datpg = udatpg_open ([[locale localeIdentifier] UTF8String], &err);
|
|
if (U_FAILURE(err))
|
|
return nil;
|
|
|
|
if ((patLen = [aTemplate length]) > BUFFER_SIZE)
|
|
patLen = BUFFER_SIZE;
|
|
[aTemplate getCharacters: pat range: NSMakeRange(0, patLen)];
|
|
|
|
skelLen = udatpg_getSkeleton (datpg, pat, patLen, skel, BUFFER_SIZE, &err);
|
|
if (U_FAILURE(err))
|
|
return nil;
|
|
|
|
patLen =
|
|
udatpg_getBestPattern (datpg, skel, skelLen, pat, BUFFER_SIZE, &err);
|
|
|
|
udatpg_close (datpg);
|
|
return [NSString stringWithCharacters: pat length: patLen];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
- (BOOL) doesRelativeDateFormatting
|
|
{
|
|
return (internal->_dateStyle & FormatterDoesRelativeDateFormatting) ? YES : NO;
|
|
}
|
|
|
|
- (void) setDoesRelativeDateFormatting: (BOOL)flag
|
|
{
|
|
internal->_dateStyle |= FormatterDoesRelativeDateFormatting;
|
|
}
|
|
@end
|
|
|
|
@implementation NSDateFormatter (PrivateMethods)
|
|
- (void) _resetUDateFormat
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
UChar *pat = NULL;
|
|
UChar *tzID;
|
|
int32_t patLength = 0;
|
|
int32_t tzIDLength;
|
|
UDateFormatStyle timeStyle;
|
|
UDateFormatStyle dateStyle;
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
if (internal->_formatter)
|
|
udat_close (internal->_formatter);
|
|
|
|
tzIDLength = [[internal->_tz name] length];
|
|
tzID = malloc(sizeof(UChar) * tzIDLength);
|
|
[[internal->_tz name] getCharacters: tzID];
|
|
|
|
if (self->_dateFormat)
|
|
{
|
|
patLength = [self->_dateFormat length];
|
|
pat = malloc(sizeof(UChar) * patLength);
|
|
[self->_dateFormat getCharacters: pat];
|
|
}
|
|
#if U_ICU_VERSION_MAJOR_NUM >= 50 || defined(HAVE_ICU_H)
|
|
timeStyle = pat ? UDAT_PATTERN : NSToUDateFormatStyle (internal->_timeStyle);
|
|
dateStyle = pat ? UDAT_PATTERN : NSToUDateFormatStyle (internal->_dateStyle);
|
|
#else
|
|
timeStyle = NSToUDateFormatStyle (internal->_timeStyle);
|
|
dateStyle = NSToUDateFormatStyle (internal->_dateStyle);
|
|
#endif
|
|
internal->_formatter = udat_open (timeStyle, dateStyle,
|
|
[[internal->_locale localeIdentifier] UTF8String],
|
|
tzID, tzIDLength, pat, patLength, &err);
|
|
if (U_FAILURE(err))
|
|
internal->_formatter = NULL;
|
|
if (pat)
|
|
free(pat);
|
|
free(tzID);
|
|
#else
|
|
return;
|
|
#endif
|
|
}
|
|
|
|
#if GS_USE_ICU == 1
|
|
static inline void
|
|
symbolRange(NSInteger symbol, int *from)
|
|
{
|
|
switch (symbol)
|
|
{
|
|
case UDAT_SHORT_WEEKDAYS:
|
|
case UDAT_STANDALONE_NARROW_WEEKDAYS:
|
|
case UDAT_STANDALONE_SHORT_WEEKDAYS:
|
|
case UDAT_STANDALONE_WEEKDAYS:
|
|
case UDAT_WEEKDAYS:
|
|
/* In ICU days of the week number from 1 rather than zero.
|
|
*/
|
|
*from = 1;
|
|
break;
|
|
|
|
default:
|
|
*from = 0;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
- (void) _setSymbols: (NSArray*)array : (NSInteger)symbol
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
int idx;
|
|
int count = udat_countSymbols (internal->_formatter, symbol);
|
|
|
|
symbolRange(symbol, &idx);
|
|
if ([array count] == count - idx)
|
|
{
|
|
while (idx < count)
|
|
{
|
|
int length;
|
|
UChar *value;
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
NSString *string = [array objectAtIndex: idx];
|
|
|
|
length = [string length];
|
|
value = malloc(sizeof(unichar) * length);
|
|
[string getCharacters: value range: NSMakeRange(0, length)];
|
|
udat_setSymbols(internal->_formatter, symbol, idx,
|
|
value, length, &err);
|
|
free(value);
|
|
++idx;
|
|
}
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
- (NSArray *) _getSymbols: (NSInteger)symbol
|
|
{
|
|
#if GS_USE_ICU == 1
|
|
NSMutableArray *mArray;
|
|
int idx;
|
|
int count;
|
|
|
|
count = udat_countSymbols(internal->_formatter, symbol);
|
|
symbolRange(symbol, &idx);
|
|
mArray = [NSMutableArray arrayWithCapacity: count - idx];
|
|
while (idx < count)
|
|
{
|
|
int length;
|
|
unichar *value;
|
|
NSString *str;
|
|
NSZone *z = [self zone];
|
|
UErrorCode err = U_ZERO_ERROR;
|
|
|
|
length
|
|
= udat_getSymbols(internal->_formatter, symbol, idx, NULL, 0, &err);
|
|
value = NSZoneMalloc(z, sizeof(unichar) * (length + 1));
|
|
err = U_ZERO_ERROR;
|
|
udat_getSymbols(internal->_formatter, symbol, idx, value, length, &err);
|
|
if (U_SUCCESS(err))
|
|
{
|
|
str = [[NSString allocWithZone: z]
|
|
initWithBytesNoCopy: value
|
|
length: length * sizeof(unichar)
|
|
encoding: NSUnicodeStringEncoding
|
|
freeWhenDone: YES];
|
|
[mArray addObject: str];
|
|
RELEASE(str);
|
|
}
|
|
else
|
|
{
|
|
NSZoneFree (z, value);
|
|
}
|
|
|
|
++idx;
|
|
}
|
|
|
|
return [NSArray arrayWithArray: mArray];
|
|
#else
|
|
return nil;
|
|
#endif
|
|
}
|
|
@end
|
|
|