Index: src/OFDate.h ================================================================== --- src/OFDate.h +++ src/OFDate.h @@ -64,6 +64,51 @@ * \param usec The microsecond part of the time * \return An initialized OFDate with the specified date and time */ - initWithTimeIntervalSince1970: (time_t)sec microseconds: (suseconds_t)usec; + +/** + * \return The seconds of the date + */ +- (int)seconds; + +/** + * \return The microseconds of the date + */ +- (suseconds_t)microseconds; + +/** + * \return The minutes of the date + */ +- (int)minutes; + +/** + * \return The hours of the date + */ +- (int)hours; + +/** + * \return The day of the month of the date + */ +- (int)dayOfMonth; + +/** + * \return The month of the year of the date + */ +- (int)monthOfYear; + +/** + * \return The year of the date + */ +- (int)year; + +/** + * \return The day of the week of the date + */ +- (int)dayOfWeek; + +/** + * \return The day of the year of the date + */ +- (int)dayOfYear; @end Index: src/OFDate.m ================================================================== --- src/OFDate.m +++ src/OFDate.m @@ -22,10 +22,44 @@ #if !defined(HAVE_GMTIME_R) && defined(OF_THREADS) # import "OFThread.h" static OFMutex *mutex; #endif + +#ifdef HAVE_GMTIME_R +# define GMTIME_RET(field) \ + struct tm tm; \ + \ + if (gmtime_r(&sec, &tm) == NULL) \ + @throw [OFOutOfRangeException newWithClass: isa]; \ + \ + return tm.field; +#else +# ifdef OF_THREADS +# define GMTIME_RET(field) \ + struct tm *tm; \ + \ + [mutex lock]; \ + \ + @try { \ + if ((tm = gmtime(&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; +# endif +#endif @implementation OFDate #if !defined(HAVE_GMTIME_R) && defined(OF_THREADS) + (void)initialize { @@ -149,6 +183,51 @@ if (usec == 0) return [OFString stringWithFormat: @"%sZ", str]; return [OFString stringWithFormat: @"%s.%06dZ", str, usec]; } + +- (int)seconds +{ + GMTIME_RET(tm_sec) +} + +- (suseconds_t)microseconds +{ + return usec; +} + +- (int)minutes +{ + GMTIME_RET(tm_min) +} + +- (int)hours +{ + GMTIME_RET(tm_hour) +} + +- (int)dayOfMonth +{ + GMTIME_RET(tm_mday) +} + +- (int)monthOfYear +{ + GMTIME_RET(tm_mon + 1) +} + +- (int)year +{ + GMTIME_RET(tm_year + 1900) +} + +- (int)dayOfWeek +{ + GMTIME_RET(tm_wday) +} + +- (int)dayOfYear +{ + GMTIME_RET(tm_yday + 1) +} @end Index: tests/OFDateTests.m ================================================================== --- tests/OFDateTests.m +++ tests/OFDateTests.m @@ -41,8 +41,27 @@ ![d1 isEqual: [OFDate dateWithTimeIntervalSince1970: 0 microseconds: 1]]) TEST(@"-[compare:]", [d1 compare: d2] == OF_ORDERED_ASCENDING) + TEST(@"-[seconds]", [d1 seconds] == 0 && [d2 seconds] == 5) + + TEST(@"-[microseconds]", + [d1 microseconds] == 0 && [d2 microseconds] == 1) + + TEST(@"-[minutes]", [d1 minutes] == 0 && [d2 minutes] == 0) + + TEST(@"-[hours]", [d1 hours] == 0 && [d2 hours] == 1) + + TEST(@"-[dayOfMonth]", [d1 dayOfMonth] == 1 && [d2 dayOfMonth] == 2) + + TEST(@"-[monthOfYear]", [d1 monthOfYear] == 1 && [d2 monthOfYear] == 1) + + TEST(@"-[year]", [d1 year] == 1970 && [d2 year] == 1970) + + TEST(@"-[dayOfWeek]", [d1 dayOfWeek] == 4 && [d2 dayOfWeek] == 5) + + TEST(@"-[dayOfYear]", [d1 dayOfYear] == 1 && [d2 dayOfYear] == 2) + [pool drain]; } @end