/*============================================================================= * drt/sys/htime.c * /*============================================================================= * drt/sys/htime.c * DRT primitive date and time functions. * * History * 0.01, 1999-02-27, David R Tribble. * First cut. * * 0.02, 1999-03-19, David R Tribble. * Converted from C++ to C. * * Copyright ©1999, by David R. Tribble, all rights reserved. * See "drt/sys/copyr.txt" for more information. *----------------------------------------------------------------------------*/ /* Identification */ static const char id[] = "@(#)drt/sys/htime.c 0.02"; /* System includes */ #include #define drt_std_assert_h 1 #include #define drt_std_time_h 1 /* Special includes */ #include "kdefs.h" /* System-specific includes */ #if DRT_OS_UNIX #ifndef drt_std_sys_time_h #include #define drt_std_sys_time_h 1 #endif #elif DRT_OS_WIN32 #ifndef drt_std_windows_h #define WIN32_LEAN_AND_MEAN 1 #include #define drt_std_windows_h 1 #endif #else #error Undefined DRT_OS_XXX #endif /* Local includes */ #include "kdebug.h" #include "ktimec.h" #include "ktime.h" /*----------------------------------------------------------------------------- * Public functions *----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * drt_time_now() * Determine the current date and time, and set 'th' to this value. * * Returns * True if successful, otherwise false. *----------------------------------------------------------------------------*/ bool drt_time_now(drt_time_t *th) { #if DRT_TIME_VS/100 != 1 #error DRT_TIME_VS has changed #endif #if DEBUG >= 2 drt_trace dbg = { s_grp, "now" }; #endif /* Check args */ if (th == null) return (false); #if DRT_OS_UNIX /*------------------------------------------------------------------------- * The BSD gettimeofday() function fills a 'timeval' structure with the * current time_t value (which is the number of seconds since * AD1970-01-01 00:00:00 Z) and a microsecond count. These time values are * directly convertible into drt_time_t epoch tick counts. * * If the gettimeofday() function is not available, we can use the POSIX.4 * clock_gettime() function instead. *------------------------------------------------------------------------*/ { /* Retrieve the current (system) date */ struct timeval tv; drt_int64_t x; /* Get the current system time (secs & usecs) */ #if DRT_USE_POSIX_GETTIMEOFDAY clock_gettimeofday(&tv, null); #else gettimeofday(&tv, null); #endif #if TEST printf("systemtime=<%9ld.%06ld>\n", (long)tv.tv_sec, (long)tv.tv_usec); printf("AD1970= %+20lld\n", (drt_int64_t)DRT_TIME_AD1970); #endif /* Convert to drt_time_t form */ x = DRT_TIME_AD1970; x += tv.tv_sec * (drt_int64_t)TICKS_PER_SEC; x += tv.tv_usec * (drt_int64_t)(TICKS_PER_SEC/1000000); *th = x; return (true); } #elif DRT_OS_WIN32 /*------------------------------------------------------------------------- * The Microsoft Win32 API can return the current system time in "file * timestamp" format, which is a 64-bit value representing the number of * 100-nanosecond ticks since AD1601-01-01 00:00:00 Z. This time value is * directly convertible into a drt_time_t epoch tick count. *------------------------------------------------------------------------*/ { /* Retrieve the current (system) date */ FILETIME ft; drt_int64_t x; /* Get the current system time */ GetSystemTimeAsFileTime(&ft); /* Not GetSystemTime(&st) */ #if TEST printf("systemtime=<%08lX,%08lX>\n", (long)ft.dwHighDateTime, (long)ft.dwLowDateTime); printf("AD1601= %+020I64d\n", (drt_int64_t)DRT_TIME_AD1601); #endif /* Convert to drt_time_t form */ x = ((drt_int64_t)ft.dwHighDateTime << 32) + ft.dwLowDateTime; x *= TICKS_PER_SEC/10000000; x += DRT_TIME_AD1601; *th = x; #if TEST printf("offset= %+020I64d\n", x-DRT_TIME_AD1601); printf("result= %+020I64d\n", (drt_int64_t)*th); #endif return (true); } #elif DRT_OS_POSIX /*------------------------------------------------------------------------- * The POSIX time() function returns the number of seconds since * AD1970-01-01 00:00:00 Z. This time value is directly convertible into * a drt_time_t epoch tick count. *------------------------------------------------------------------------*/ { /* Retrieve the current (system) date */ time_t t; drt_int64_t x; /* Get the current system time (secs & usecs) */ time(&t); #if TEST printf("systemtime=<%9ld>\n", (long)t); printf("AD1970= %+20lld\n", (drt_int64_t)DRT_TIME_AD1970); #endif /* Convert to drt_time_t form */ x = t * (drt_int64_t)TICKS_PER_SEC; x += DRT_TIME_AD1970; *th = x; return (true); } #elif DRT_OS_ISO /*------------------------------------------------------------------------- * If all else fails, we can use the ISO/IEC C/C++ time() function to get * the current system time. * * Unfortunately, the only thing we know (portably) about the value is that * the time_t type is arithmetic. This isn't much help for converting the * value into drt_time_t epoch tick counts. * * We can, however, convert the time_t value into a broken-down 'tm' * structure, then convert that into a 'drt_tm' structure, and then finally * convert that into a drt_time_t value. What a pain. *------------------------------------------------------------------------*/ { /* Retrieve the current (system) date */ time_t t; struct tm st; struct drt_tm dt; /* Get the current system time (secs & usecs) */ time(&t); /* Convert to broken-down (expanded) form */ st = *gmtime(&t); /* Note: Not thread-safe! */ /* Convert broken-down form into our broken-down form */ #if DRT_TM_VS != 101 #error DRT_TM_VS has changed #endif dt.tm_vers = DRT_TM_VS; dt.tm_year = st.tm_year+1900; dt.tm_mon = st.tm_mon; dt.tm_mday = st.tm_mday; dt.tm_hour = st.tm_hour; dt.tm_min = st.tm_min; dt.tm_sec = st.tm_sec; dt.tm_nsec = 0; dt.tm_yday = 0; dt.tm_wday = 0; /* Finally, convert our broken-down form into a time value */ return (drt_time_make(&th, &dt)); } #else #error Unknown O/S, DRT_OS_XXX not set return (false); #endif } /*============================================================================= * Test code *----------------------------------------------------------------------------*/ #if TEST static const char wday[][3+1] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "-7-", "-8-", "-9-" }; /*----------------------------------------------------------------------------- * main() * Test driver. *----------------------------------------------------------------------------*/ int main(int argc, const char *const *argv) { drt_time_t t; time_t rt; int i; printf("Get the current date and time...\n"); time(&rt); drt_time_now(&t); /* Print the time in decimal form */ { int d[20/3+1]; drt_time_t v = t; if (v < 0) { printf("-"); v = -v; } else printf("+"); for (i = 0; i < 20/3+1; i++) { d[i] = v % 1000; v /= 1000; } printf("%ld", d[20/3+1-1]); for (i = 20/3+1-2; i >= 0; i--) printf(",%03d", d[i]); printf("\n"); } /* Print the time in hex form */ { union /*anonymous*/ { drt_int64_t t; unsigned char b[sizeof(drt_int64_t)]; } u; u.t = t; /* Print the bytes in big-endian order */ #if DRT_BYTE_HL for (i = 0; i < sizeof(u.t); i++) printf(" %02X", u.b[i]); #else for (i = sizeof(u.t)-1; i >= 0; i--) printf(" %02X", u.b[i]); #endif printf("\n"); } /* Print the time in pseudo-broken-down form */ { drt_time_t v = t; struct drt_tm tm; tm.tm_nsec = v % DRT_TIME_TICKS_PER_SEC; tm.tm_nsec *= 1000000000/DRT_TIME_TICKS_PER_SEC; /* Nanoseconds */ v /= DRT_TIME_TICKS_PER_SEC; /* Seconds */ if (tm.tm_nsec < 0) { tm.tm_nsec += 1000000000; v--; } tm.tm_sec = v % 60; v /= 60; /* Minutes */ if (tm.tm_sec < 0) { tm.tm_sec += 60; v--; } tm.tm_min = v % 60; v /= 60; /* Hours */ if (tm.tm_min < 0) { tm.tm_min += 60; v--; } tm.tm_hour = v % 24; v /= 24; /* Days */ if (tm.tm_hour < 0) { tm.tm_hour += 24; v--; } tm.tm_year = (v * 10000) / 3652425 + DRT_TIME_ZYEAR; /* Years */ v -= (((drt_time_t)tm.tm_year - DRT_TIME_ZYEAR) * 3652425) / 10000; /* Days */ tm.tm_yday = v; if (tm.tm_yday < 0) { tm.tm_yday = ((drt_time_t)tm.tm_yday * 10000 + 3652425) / 10000; tm.tm_year--; } printf("~ %04d/%03d %02d:%02d:%02d.%09ld\n", tm.tm_year, tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_nsec ); } /* Print the time in broken-down form */ { struct drt_tm tm; drt_time_gmtime(&tm, t); printf("[%04d-%02d-%02d(%03d) %02d:%02d:%02d.%09ld %d:%s]\n", tm.tm_year, tm.tm_mon+1, tm.tm_mday, tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_nsec, tm.tm_wday, wday[tm.tm_wday] ); } /* Print the ISO time in broken-down form */ { struct tm tm; tm = *gmtime(&rt); printf("ISO time is:\n"); printf("<%04d-%02d-%02d(%03d) %02d:%02d:%02d %9s %d:%s>\n", tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_yday, tm.tm_hour, tm.tm_min, tm.tm_sec, "", tm.tm_wday, wday[tm.tm_wday] ); } return (0); } #endif /* TEST */ /* End htime.c */