@@ -114,6 +114,7 @@ - (NSString *) _localeIdentifier;
114114- (void ) _setLocaleIdentifier : (NSString *)identifier ;
115115@end
116116
117+ static NSCalendar *currentCalendar = nil ;
117118static NSCalendar *autoupdatingCalendar = nil ;
118119static NSRecursiveLock *classLock = nil ;
119120
@@ -123,6 +124,52 @@ - (void) _setLocaleIdentifier: (NSString*)identifier;
123124
124125@implementation NSCalendar (PrivateMethods)
125126
127+ - (BOOL ) _needsRefreshForLocale : (NSString *)locale
128+ calendar : (NSString *)calendar
129+ timeZone : (NSString *)timeZone
130+ {
131+ BOOL needsToRefresh;
132+
133+ [_lock lock ];
134+
135+ needsToRefresh = [locale isEqual: my->localeID] == NO
136+ || [calendar isEqual: my->identifier] == NO
137+ || [timeZone isEqual: [my->tz name ]] == NO ;
138+
139+ [_lock unlock ];
140+
141+ return needsToRefresh;
142+ }
143+
144+ - (BOOL ) _needsRefreshForDefaultsChangeNotification : (NSNotification *)n
145+ {
146+ NSUserDefaults *defs = [NSUserDefaults standardUserDefaults ];
147+ NSString *locale = [defs stringForKey: @" Locale" ];
148+ NSString *calendar = [defs stringForKey: @" Calendar" ];
149+ NSString *tz = [defs stringForKey: @" Local Time Zone" ];
150+ BOOL needsToRefresh = [self _needsRefreshForLocale: locale calendar: calendar timeZone: tz];
151+
152+ return needsToRefresh;
153+ }
154+
155+ + (void ) _refreshCurrentCalendarFromDefaultsDidChange : (NSNotification *)n
156+ {
157+ [classLock lock ];
158+
159+ if (currentCalendar != nil )
160+ {
161+ BOOL needToRefreshCurrentCalendar = [currentCalendar _needsRefreshForDefaultsChangeNotification: n];
162+
163+ if (needToRefreshCurrentCalendar)
164+ {
165+ RELEASE (currentCalendar);
166+ currentCalendar = nil ;
167+ }
168+ }
169+
170+ [classLock unlock ];
171+ }
172+
126173#if GS_USE_ICU == 1
127174- (void *) _locked_openCalendarFor : (NSTimeZone *)timeZone
128175{
@@ -132,7 +179,6 @@ - (void *) _locked_openCalendarFor: (NSTimeZone *)timeZone
132179 const char *cLocaleId;
133180 UErrorCode err = U_ZERO_ERROR;
134181 UCalendarType type;
135- void *cal;
136182
137183 cLocaleId = [my->localeID UTF8String ];
138184 tzName = [timeZone name ];
@@ -260,26 +306,25 @@ - (void) _setLocaleIdentifier: (NSString *)identifier
260306
261307- (void ) _defaultsDidChange : (NSNotification *)n
262308{
263- NSUserDefaults *defs;
264- NSString *locale;
265- NSString *calendar;
266- NSString *tz;
267-
268- defs = [NSUserDefaults standardUserDefaults ];
269- locale = [defs stringForKey: @" Locale" ];
270- calendar = [defs stringForKey: @" Calendar" ];
271- tz = [defs stringForKey: @" Local Time Zone" ];
309+ BOOL needsToRefresh;
310+ NSUserDefaults *defs = [NSUserDefaults standardUserDefaults ];
311+ NSString *locale = [defs stringForKey: @" Locale" ];
312+ NSString *calendar = [defs stringForKey: @" Calendar" ];
313+ NSString *tz = [defs stringForKey: @" Local Time Zone" ];
272314
273315 [classLock lock ];
274316 [_lock lock ];
275- if ([locale isEqual: my->localeID] == NO ||
276- [calendar isEqual: my->identifier] == NO ||
277- [tz isEqual: [my->tz name ]] == NO ) {
317+
318+ needsToRefresh = [self _needsRefreshForLocale: locale calendar: calendar timeZone: tz];
319+
320+ if (needsToRefresh)
321+ {
278322#if GS_USE_ICU == 1
279- if (my->cal != NULL ) {
323+ if (my->cal != NULL )
324+ {
280325 ucal_close (my->cal );
281326 my->cal = NULL ;
282- }
327+ }
283328#endif
284329
285330 ASSIGN (my->localeID , locale);
@@ -289,6 +334,7 @@ - (void) _defaultsDidChange: (NSNotification*)n
289334
290335 [self _locked_resetCalendar ];
291336 }
337+
292338 [_lock unlock ];
293339 [classLock unlock ];
294340}
@@ -298,21 +344,36 @@ @implementation NSCalendar
298344
299345+ (void ) initialize
300346{
301- if (self == [NSCalendar class ]) {
347+ if (self == [NSCalendar class ])
348+ {
302349 classLock = [NSRecursiveLock new ];
303- }
350+
351+ [[NSNotificationCenter defaultCenter ] addObserver: self
352+ selector: @selector (_refreshCurrentCalendarFromDefaultsDidChange: )
353+ name: NSUserDefaultsDidChangeNotification
354+ object: nil ];
355+ }
304356}
305357
306358+ (id ) currentCalendar
307359{
308360 NSCalendar *result;
309- NSString *identifier;
310361
311- // This identifier may be nil
312- identifier = [[NSLocale currentLocale ] objectForKey: NSLocaleCalendarIdentifier];
313- result = [[NSCalendar alloc ] initWithCalendarIdentifier: identifier];
362+ [classLock lock ];
363+
364+ if (currentCalendar == nil )
365+ {
366+ // This identifier may be nil
367+ NSString *identifier = [[NSLocale currentLocale ] objectForKey: NSLocaleCalendarIdentifier];
368+
369+ currentCalendar = [[NSCalendar alloc ] initWithCalendarIdentifier: identifier];
370+ }
314371
315- return AUTORELEASE (result);
372+ result = currentCalendar;
373+
374+ [classLock unlock ];
375+
376+ return result;
316377}
317378
318379+ (id ) autoupdatingCurrentCalendar
@@ -827,6 +888,10 @@ - (NSDate *)dateBySettingUnit:(NSCalendarUnit)unit value:(NSInteger)value ofDate
827888{
828889 void *cal;
829890 UErrorCode err = U_ZERO_ERROR;
891+ BOOL ok;
892+ UCalendarDateFields ucalField;
893+ NSTimeInterval epochTime;
894+ NSTimeInterval newEpochTime;
830895
831896 [_lock lock ];
832897 cal = [self _locked_cloneCalendar: &err];
@@ -840,20 +905,19 @@ - (NSDate *)dateBySettingUnit:(NSCalendarUnit)unit value:(NSInteger)value ofDate
840905 ucal_clear (cal);
841906
842907 // Convert to ICU-equivalent calendar unit
843- BOOL ok;
844- UCalendarDateFields ucalField = NSCalendarUnitToUCalendarDateField(unit, &ok);
908+ ucalField = NSCalendarUnitToUCalendarDateField(unit, &ok);
845909 NSAssert (ok, @" GNUStep does not implement the given date field." );
846910
847911 // Set the ICU calendar to this date
848- NSTimeInterval epochTime = [date timeIntervalSince1970 ] * SECOND_TO_MILLI;
912+ epochTime = [date timeIntervalSince1970 ] * SECOND_TO_MILLI;
849913 ucal_setMillis (cal, epochTime, &err);
850914 NSAssert (!U_FAILURE(err), ([NSString stringWithFormat: @" Couldn't setMillis to calendar: %s " , u_errorName (err)]));
851915
852916 // Set the field on the ICU calendar
853917 ucal_set (cal, ucalField, value);
854918
855919 // Get the date back from the ICU calendar
856- NSTimeInterval newEpochTime = ucal_getMillis (cal, &err);
920+ newEpochTime = ucal_getMillis (cal, &err);
857921 ucal_close (cal);
858922
859923 NSAssert (!U_FAILURE(err), ([NSString stringWithFormat: @" Couldn't getMillis from calendar: %s " , u_errorName (err)]));
0 commit comments