FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FILE_SECBOOT ( PERMITTED );
+#include <assert.h>
#include <time.h>
/** @file
* @ret time Seconds since the Epoch
*/
time_t mktime ( struct tm *tm ) {
+ int tm_year = tm->tm_year;
+ int tm_mon = tm->tm_mon;
+ int tm_mday = tm->tm_mday;
+ int tm_hour = tm->tm_hour;
+ int tm_min = tm->tm_min;
+ int tm_sec = tm->tm_sec;
+ int tm_yday;
+ int tm_wday;
int days_since_epoch;
int seconds_since_day;
time_t seconds;
+ /* Normalize month for use as an array index */
+ tm_year += ( tm_mon / 12 );
+ tm_mon = ( tm_mon % 12 );
+ if ( tm_mon < 0 ) {
+ tm_year--;
+ tm_mon += 12;
+ }
+ assert ( tm_mon >= 0 );
+ assert ( tm_mon < 12 );
+
/* Calculate day of year */
- tm->tm_yday = ( ( tm->tm_mday - 1 ) +
- days_to_month_start[ tm->tm_mon ] );
- if ( ( tm->tm_mon >= 2 ) && is_leap_year ( tm->tm_year ) )
- tm->tm_yday++;
+ tm_yday = ( ( tm_mday - 1 ) + days_to_month_start[tm_mon] );
+ if ( ( tm_mon >= 2 ) && is_leap_year ( tm_year ) )
+ tm_yday++;
+ tm->tm_yday = tm_yday;
/* Calculate day of week */
- tm->tm_wday = day_of_week ( tm->tm_year, tm->tm_mon, tm->tm_mday );
+ tm_wday = day_of_week ( tm_year, tm_mon, tm_mday );
+ tm->tm_wday = tm_wday;
/* Calculate seconds since the Epoch */
- days_since_epoch = ( tm->tm_yday + ( 365 * tm->tm_year ) - 25567 +
- leap_years_to_end ( tm->tm_year - 1 ) );
+ days_since_epoch = ( tm_yday + ( 365 * tm_year ) - 25567 +
+ leap_years_to_end ( tm_year - 1 ) );
seconds_since_day =
- ( ( ( ( tm->tm_hour * 60 ) + tm->tm_min ) * 60 ) + tm->tm_sec );
- seconds = ( ( ( ( time_t ) days_since_epoch ) * ( ( time_t ) 86400 ) ) +
- seconds_since_day );
+ ( ( ( ( tm_hour * 60 ) + tm_min ) * 60 ) + tm_sec );
+ seconds = ( ( ( ( time_t ) days_since_epoch ) * ( ( time_t ) 86400 ) )
+ + seconds_since_day );
DBGC ( &weekdays, "TIME %04d-%02d-%02d %02d:%02d:%02d => %lld (%s, "
"day %d)\n", ( tm->tm_year + 1900 ), ( tm->tm_mon + 1 ),
MKTIME_TEST ( mktime_30, 49, 7, 18, 16, 10, 271, 6, 319, 0, 6370596469ULL );
MKTIME_TEST ( mktime_31, 31, 55, 2, 25, 5, 141, 2, 175, 0, 2255741731ULL );
+/* Out-of-range month values */
+MKTIME_TEST ( mktime_32, 32, 55, 2, 25, 17, 140, 2, 175, 0, 2255741732ULL );
+MKTIME_TEST ( mktime_33, 33, 55, 2, 25, 65, 136, 2, 175, 0, 2255741733ULL );
+MKTIME_TEST ( mktime_34, 34, 55, 2, 25, -7, 142, 2, 175, 0, 2255741734ULL );
+MKTIME_TEST ( mktime_35, 35, 55, 2, 25, -55, 146, 2, 175, 0, 2255741735ULL );
+
/**
* Perform date and time self-tests
*
mktime_ok ( &mktime_29 );
mktime_ok ( &mktime_30 );
mktime_ok ( &mktime_31 );
+ mktime_ok ( &mktime_32 );
+ mktime_ok ( &mktime_33 );
+ mktime_ok ( &mktime_34 );
+ mktime_ok ( &mktime_35 );
}
/** Date and time self-test */