* Source/NSTimeZone.m

Implement nextDaylightSavingTimeTransitionAfterDate:


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@36709 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
lubosd 2013-06-08 19:02:10 +00:00
parent 35c7d70e34
commit eacd4a4a48
3 changed files with 78 additions and 0 deletions

View file

@ -1,3 +1,8 @@
2013-06-08 Lubos Dolezel <lubos@dolezel.info>
* Source/NSTimeZone.m
Implement nextDaylightSavingTimeTransitionAfterDate:
2013-06-06 Sebastian Reitenbach <sebastia@l00-bugdead-prods.de>
* Source/Additions/Unicode.m

View file

@ -166,6 +166,7 @@ NSString * const NSSystemTimeZoneDidChangeNotification
#endif
#define BUFFER_SIZE 512
#define WEEK_MILLISECONDS (7.0*24.0*60.0*60.0*1000.0)
#if GS_USE_ICU == 1
static inline int
@ -2231,7 +2232,73 @@ localZoneString, [zone name], sign, s/3600, (s/60)%60);
- (NSDate *) nextDaylightSavingTimeTransitionAfterDate: (NSDate *)aDate
{
#if GS_USE_ICU == 1
/* ICU doesn't provide transition information per se.
* The canonical method of retrieving this piece of information is to
* use binary search.
*/
int32_t originalOffset, currentOffset;
UCalendar *cal;
UErrorCode err = U_ZERO_ERROR;
UDate currentTime;
int i;
NSDate* result = nil;
cal = ICUCalendarSetup (self, nil);
if (cal == NULL)
return nil;
currentTime = [aDate timeIntervalSince1970] * 1000.0;
ucal_setMillis (cal, currentTime, &err);
originalOffset = ucal_get (cal, UCAL_DST_OFFSET, &err);
if (U_FAILURE(err))
return nil;
/* First try to find the next transition by adding a week at a time */
/* Avoid ending in an infinite loop in case there is no transition at all */
for (i = 0; i < 53; i++)
{
/* Add a single week */
currentTime += WEEK_MILLISECONDS;
ucal_setMillis (cal, currentTime, &err);
if (U_FAILURE(err))
break;
currentOffset = ucal_get (cal, UCAL_DST_OFFSET, &err);
if (U_FAILURE(err))
break;
if (currentOffset != originalOffset)
{
double interval = WEEK_MILLISECONDS / 2.0;
/* Now use bisection to determine the exact moment */
while (interval >= 1.0)
{
ucal_setMillis (cal, currentTime - interval, &err);
currentOffset = ucal_get (cal, UCAL_DST_OFFSET, &err);
if (currentOffset != originalOffset)
currentTime -= interval; /* it is in the lower half */
interval /= 2.0;
}
result =
[NSDate dateWithTimeIntervalSince1970: floor(currentTime/1000.0)];
}
}
ucal_close (cal);
return result;
#else
return nil; // FIXME;
#endif
}
- (NSTimeInterval) daylightSavingTimeOffset

View file

@ -50,6 +50,12 @@ int main()
&& [current isDaylightSavingTime] == NO,
"can set default time zone");
current = [NSTimeZone timeZoneWithName: @"Europe/Brussels"];
date = [current nextDaylightSavingTimeTransitionAfterDate:
[NSDate dateWithString: @"2013-06-08 20:00:00 +0200"]];
PASS_EQUAL(date, [NSDate dateWithString: @"2013-10-27 03:00:00 +0200"],
"can calculate next DST transition");
START_SET("NSLocale")
if (!NSLOCALE_SUPPORTED)
SKIP("NSLocale not supported\nThe ICU library was not available when GNUstep-base was built")