@@ -18,11 +18,12 @@ #import "OFDate.h" #import "OFString.h" #import "OFAutoreleasePool.h" #import "OFExceptions.h" -#if !defined(HAVE_GMTIME_R) && defined(OF_THREADS) +#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \ + defined(OF_THREADS) # import "OFThread.h" static OFMutex *mutex; #endif @@ -31,10 +32,17 @@ struct tm tm; \ \ if (gmtime_r(&sec, &tm) == NULL) \ @throw [OFOutOfRangeException newWithClass: isa]; \ \ + return tm.field; +# define LOCALTIME_RET(field) \ + struct tm tm; \ + \ + if (localtime_r(&sec, &tm) == NULL) \ + @throw [OFOutOfRangeException newWithClass: isa]; \ + \ return tm.field; #else # ifdef OF_THREADS # define GMTIME_RET(field) \ struct tm *tm; \ @@ -47,23 +55,44 @@ \ return tm->field; \ } @finally { \ [mutex unlock]; \ } +# define LOCALTIME_RET(field) \ + struct tm *tm; \ + \ + [mutex lock]; \ + \ + @try { \ + if ((tm = localtime(&sec)) == NULL) \ + @throw [OFOutOfRangeException newWithClass: isa]; \ + \ + return tm->field; \ + } @finally { \ + [mutex unlock]; \ + } # else # define GMTIME_RET(field) \ struct tm *tm; \ \ if ((tm = gmtime(&sec)) == NULL) \ @throw [OFOutOfRangeException newWithClass: isa]; \ \ return tm->field; +# define LOCALTIME_RET(field) \ + struct tm *tm; \ + \ + if ((tm = localtime(&sec)) == NULL) \ + @throw [OFOutOfRangeException newWithClass: isa]; \ + \ + return tm->field; # endif #endif @implementation OFDate -#if !defined(HAVE_GMTIME_R) && defined(OF_THREADS) +#if (!defined(HAVE_GMTIME_R) || !defined(HAVE_LOCALTIME_R)) && \ + defined(OF_THREADS) + (void)initialize { if (self == [OFDate class]) mutex = [[OFMutex alloc] init]; } @@ -154,11 +183,11 @@ - (OFString*)description { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFString *tmp, *ret; - tmp = [self stringWithFormat: @"%Y-%m-%dT%H:%M:%S"]; + tmp = [self dateStringWithFormat: @"%Y-%m-%dT%H:%M:%S"]; if (usec == 0) ret = [OFString stringWithFormat: @"%sZ", [tmp cString]]; else ret = [OFString stringWithFormat: @"%s.%06dZ", [tmp cString], @@ -168,39 +197,54 @@ [pool release]; return [ret autorelease]; } -- (int)seconds +- (suseconds_t)microsecond +{ + return usec; +} + +- (int)second { GMTIME_RET(tm_sec) } -- (suseconds_t)microseconds -{ - return usec; -} - -- (int)minutes +- (int)minute { GMTIME_RET(tm_min) } -- (int)hours +- (int)hour { GMTIME_RET(tm_hour) } + +- (int)localHour +{ + LOCALTIME_RET(tm_hour) +} - (int)dayOfMonth { GMTIME_RET(tm_mday) } + +- (int)localDayOfMonth +{ + LOCALTIME_RET(tm_mday) +} - (int)monthOfYear { GMTIME_RET(tm_mon + 1) } + +- (int)localMonthOfYear +{ + LOCALTIME_RET(tm_mon + 1) +} - (int)year { GMTIME_RET(tm_year + 1900) } @@ -207,17 +251,27 @@ - (int)dayOfWeek { GMTIME_RET(tm_wday) } + +- (int)localDayOfWeek +{ + LOCALTIME_RET(tm_wday) +} - (int)dayOfYear { GMTIME_RET(tm_yday + 1) } -- (OFString*)stringWithFormat: (OFString*)fmt +- (int)localDayOfYear +{ + LOCALTIME_RET(tm_yday + 1) +} + +- (OFString*)dateStringWithFormat: (OFString*)fmt { struct tm tm; char *buf; #ifdef HAVE_GMTIME_R @@ -232,10 +286,49 @@ struct tm *tmp; if ((tmp = gmtime(&sec)) == NULL) @throw [OFOutOfRangeException newWithClass: isa]; + tm = *tmp; +# ifdef OF_THREADS + } @finally { + [mutex unlock]; + } +# endif +#endif + + buf = [self allocMemoryWithSize: of_pagesize]; + + @try { + if (!strftime(buf, of_pagesize, [fmt cString], &tm)) + @throw [OFOutOfRangeException newWithClass: isa]; + + return [OFString stringWithCString: buf]; + } @finally { + [self freeMemory: buf]; + } +} + +- (OFString*)localDateStringWithFormat: (OFString*)fmt +{ + struct tm tm; + char *buf; + +#ifdef HAVE_LOCALTIME_R + if (localtime_r(&sec, &tm) == NULL) + @throw [OFOutOfRangeException newWithClass: isa]; +#else +# ifdef OF_THREADS + [mutex lock]; + + @try { +# endif + struct tm *tmp; + + if ((tmp = localtime(&sec)) == NULL) + @throw [OFOutOfRangeException newWithClass: isa]; + tm = *tmp; # ifdef OF_THREADS } @finally { [mutex unlock]; }