/*============================================================================= * time2.c *----------------------------------------------------------------------------*/ #include "compiler.h" #include #include #if TEST #include #endif typedef long long int drt_i64_t; typedef drt_i64_t drt_time_t; struct drt_tm { int tm_vers; int tm_year; int tm_mon; int tm_mday; int tm_hour; int tm_min; int tm_sec; long int tm_usec; int tm_wday; int tm_yday; int tm_dst; }; const drt_time_t DRT_TIME_UNKNOWN = 0; const drt_time_t DRT_TIME_NEVER = 0; #define TICKS_PER_SEC 10000000 /* 10e6 */ #define TIME_ZYEAR 2001 /* AD2001-01-01 */ #define SECS_PER_DAY 86400 /* 60*60*24 */ #define SECS_PER_YEAR 31556952 /* 365.2425 days, 365+05:49:12 */ #define DAYS_PER_400YR 146097 /* 365.2425*400, 97 leap days */ static const int days_per_mon[] = { /* 0 Jan */ 0, /* 0 */ /* 1 Feb */ 31, /* 31 */ /* 2 Mar */ 31+28, /* 59 */ /* 3 Apr */ 31+28+31, /* 90 */ /* 4 May */ 31+28+31+30, /* 120 */ /* 5 Jun */ 31+28+31+30+31, /* 151 */ /* 6 Jul */ 31+28+31+30+31+30, /* 181 */ /* 7 Aug */ 31+28+31+30+31+30+31, /* 212 */ /* 8 Sep */ 31+28+31+30+31+30+31+31, /* 243 */ /* 9 Oct */ 31+28+31+30+31+30+31+31+30, /* 273 */ /* 10 Nov */ 31+28+31+30+31+30+31+31+30+31, /* 304 */ /* 11 Dec */ 31+28+31+30+31+30+31+31+30+31+30, /* 334 */ /* 12 - */ 31+28+31+30+31+30+31+31+30+31+30+31+1,/* 366 */ }; /*----------------------------------------------------------------------------- * drt_time_gmtime() * Convert time value 't' into its broken-down form, placing the results * into struct 'th'. * * Returns * True if successful, otherwise false on error. *----------------------------------------------------------------------------*/ bool drt_time_gmtime(struct drt_tm *th, drt_time_t t) { long int t2; long int y; int d; int yd; int leapday; /* Check args */ if (th == null) return (false); /* Reset some struct members */ memset(th, 0, sizeof(*th)); th->tm_dst = -1; /* Check for special cases */ if (t == DRT_TIME_UNKNOWN) { /* Time value is 'unknown' */ th->tm_year = INT_MIN; return (true); } if (t == DRT_TIME_NEVER) { /* Time value is 'never' */ th->tm_year = INT_MAX; return (true); } /* Convert time 't' into a broken-down time */ /* Determine the microseconds */ th->tm_usec = t%TICKS_PER_SEC; t /= TICKS_PER_SEC; /* Seconds since ZD (exact) */ /* Determine the day of the week */ t2 = t/SECS_PER_DAY; /* Days since ZD (exact) */ th->tm_wday = (t2+1)%7; /* Determine the year */ y = t/SECS_PER_YEAR; t2 = t%SECS_PER_YEAR; /* Seconds since Jan-01 */ th->tm_year = y + TIME_ZYEAR; /* Years since ZD */ /* Determine the day of the year */ yd = t2/SECS_PER_DAY; t2 %= SECS_PER_DAY; /* Seconds since midnight */ th->tm_yday = yd; /* Determine the time (HH:MM:SS) */ th->tm_hour = t2/3600; t2 %= 3600; th->tm_min = t2/60; t2 %= 60; th->tm_sec = t2; /* Determine leap days for the year */ leapday = 0; if (yd >= days_per_mon[2] and y%4 == 0 and y%100 != 0 and y%400 == 0) leapday = 1; /* Determine the month */ d = yd/31; /* First guess */ if (yd+leapday >= days_per_mon[d+1]) d++; th->tm_mon = d; /* Determine the day of the month */ th->tm_mday = yd+leapday - days_per_mon[d] + 1; return (true); } /*===========================================================================*/ #if TEST == 1 static int leapday = 0; int main(void) { int yd; for (yd = 0; yd <= 365; yd++) { int d; int j; #if 0 if (yd%20 == 0) printf("\n%3d. ", yd); #else printf("\n%3d. ", yd); #endif /* Guess the month */ d = yd/31; /* First guess */ if (yd+leapday >= days_per_mon[d+1]) d++; printf("%2d", d); #if 1 j = yd - days_per_mon[d]; j = yd+leapday - days_per_mon[d] + 1; printf(j <= 1 ? " >" : " "); printf("%2d/%02d", d+1, j); #endif /* Check out guess */ if (yd < days_per_mon[d]) printf("<"); else if (d > 0 and yd < days_per_mon[d-1]) printf("*"); else if (yd > days_per_mon[d+1]) printf("."); else printf(" "); } printf("\n"); return (0); } #endif /* TEST */ /*===========================================================================*/ #if TEST == 2 static const char wday[][3+1] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "-7-", "-8-", "-9-" }; int main(void) { drt_time_t t; drt_time_t t1 = 0; drt_time_t inc; int i; inc = 100000000; inc *= 10000; t = 1; for (i = 0; i < 30; i++) { struct drt_tm tm; drt_time_gmtime(&tm, t); printf("%20lld: %04d-%02d-%02d(%03d) %02d:%02d:%02d.%07d %d:%s\n", t, tm.tm_year, tm.tm_mon+1, tm.tm_mday, tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_wday, wday[tm.tm_wday] ); if (tm.tm_year < 2100) t1 = t; t += t*2/3 + inc; } printf("\n"); t = t1; inc = TICKS_PER_SEC; for (i = 0; i < 30; i++) { struct drt_tm tm; drt_time_gmtime(&tm, t); printf("%20lld: %04d-%02d-%02d(%03d) %02d:%02d:%02d.%07d %d:%s\n", t, tm.tm_year, tm.tm_mon+1, tm.tm_mday, tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, tm.tm_wday, wday[tm.tm_wday] ); if (i == 3) inc *= 3600; if (i == 7) inc *= 24; if (i == 11) inc *= 30; if (i == 15) inc = (drt_time_t)TICKS_PER_SEC * SECS_PER_YEAR; if (i == 19) inc *= 100; if (i == 23) inc *= 10; t += inc; } printf("\n"); return (0); } #endif /* TEST */ /* End time2.c */