#include "direwolf.h" #include #include "textcolor.h" #include "dtime_now.h" /* Current time in seconds but more resolution than time(). */ /* We don't care what date a 0 value represents because we */ /* only use this to calculate elapsed real time. */ #include #ifdef __APPLE__ #include #endif /*------------------------------------------------------------------ * * Name: dtime_now * * Purpose: Return current time as double precision. * * Input: none * * Returns: Unix time, as double precision, so we can get resolution * finer than one second. * * Description: Normal unix time is in seconds since 1/1/1970 00:00:00 UTC. * Sometimes we want resolution finer than a second. * Rather than having a separate variable for the fractional * part of a second, and having extra calculations everywhere, * simply use double precision floating point to make usage * easier. * *---------------------------------------------------------------*/ double dtime_now (void) { double result; #if __WIN32__ /* 64 bit integer is number of 100 nanosecond intervals from Jan 1, 1601. */ FILETIME ft; GetSystemTimeAsFileTime (&ft); result = ((( (double)ft.dwHighDateTime * (256. * 256. * 256. * 256.) + (double)ft.dwLowDateTime ) / 10000000.) - 11644473600.); #else /* tv_sec is seconds from Jan 1, 1970. */ struct timespec ts; #ifdef __APPLE__ struct timeval tp; gettimeofday(&tp, NULL); ts.tv_nsec = tp.tv_usec * 1000; ts.tv_sec = tp.tv_sec; #else clock_gettime (CLOCK_REALTIME, &ts); #endif result = ((double)(ts.tv_sec) + (double)(ts.tv_nsec) * 0.000000001); #endif #if DEBUG text_color_set(DW_COLOR_DEBUG); dw_printf ("dtime_now() returns %.3f\n", result ); #endif return (result); } #if __WIN32__ /* * Windows doesn't have localtime_r. * It should have the equivalent localtime_s, with opposite parameter * order, but I get undefined reference when trying to use it. */ static struct tm *localtime_r(time_t *clock, struct tm *res) { struct tm *tm; tm = localtime (clock); memcpy (res, tm, sizeof(struct tm)); return (res); } #endif /*------------------------------------------------------------------ * * Name: timestamp_now * * Purpose: Convert local time to one of these formats for debug output. * * HH:MM:SS * HH:MM:SS.mmm * * Input: result_size - Size of result location. * Should be at least 9 or 13. * * show_ms - True to display milliseconds. * * Output: result - Result is placed here. * *---------------------------------------------------------------*/ void timestamp_now (char *result, int result_size, int show_ms) { double now = dtime_now(); time_t t = (int)now; struct tm tm; localtime_r (&t, &tm); strftime (result, result_size, "%H:%M:%S", &tm); if (show_ms) { int ms = (now - (int)t) * 1000; char strms[16]; if (ms == 1000) ms = 999; sprintf (strms, ".%03d", ms); strlcat (result, strms, result_size); } } /* end timestamp_now */ /*------------------------------------------------------------------ * * Name: timestamp_user_format * * Purpose: Convert local time user-specified format. e.g. * * HH:MM:SS * mm/dd/YYYY HH:MM:SS * dd/mm/YYYY HH:MM:SS * * Input: result_size - Size of result location. * * user_format - See strftime documentation. * * https://linux.die.net/man/3/strftime * https://msdn.microsoft.com/en-us/library/aa272978(v=vs.60).aspx * * Note that Windows does not support all of the Linux formats. * For example, Linux has %T which is equivalent to %H:%M:%S * * Output: result - Result is placed here. * *---------------------------------------------------------------*/ void timestamp_user_format (char *result, int result_size, char *user_format) { double now = dtime_now(); time_t t = (int)now; struct tm tm; localtime_r (&t, &tm); strftime (result, result_size, user_format, &tm); } /* end timestamp_user_format */ /*------------------------------------------------------------------ * * Name: timestamp_filename * * Purpose: Generate unique file name based on the current time. * The format will be: * * YYYYMMDD-HHMMSS-mmm * * Input: result_size - Size of result location. * Should be at least 20. * * Output: result - Result is placed here. * * Description: This is for the kissutil "-r" option which places * each received frame in a new file. It is possible to * have two packets arrive in less than a second so we * need more than one second resolution. * * What if someone wants UTC, rather than local time? * You can simply set an environment variable like this: * * TZ=UTC direwolf * * so it's probably not worth the effort to add another * option. * *---------------------------------------------------------------*/ void timestamp_filename (char *result, int result_size) { double now = dtime_now(); time_t t = (int)now; struct tm tm; localtime_r (&t, &tm); strftime (result, result_size, "%Y%m%d-%H%M%S", &tm); int ms = (now - (int)t) * 1000; char strms[16]; if (ms == 1000) ms = 999; sprintf (strms, "-%03d", ms); strlcat (result, strms, result_size); } /* end timestamp_filename */