1*cdfa2a7eSchristos /* $NetBSD: timetoa.h,v 1.5 2020/05/25 20:47:20 christos Exp $ */ 28585484eSchristos 38585484eSchristos /* 48585484eSchristos * timetoa.h -- time_t related string formatting 58585484eSchristos * 68585484eSchristos * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. 78585484eSchristos * The contents of 'html/copyright.html' apply. 88585484eSchristos * 98585484eSchristos * Printing a 'time_t' has some portability pitfalls, due to it's opaque 108585484eSchristos * base type. The only requirement imposed by the standard is that it 118585484eSchristos * must be a numeric type. For all practical purposes it's a signed int, 128585484eSchristos * and 32 bits are common. 138585484eSchristos * 148585484eSchristos * Since the UN*X time epoch will cause a signed integer overflow for 158585484eSchristos * 32-bit signed int values in the year 2038, implementations slowly 168585484eSchristos * move to 64bit base types for time_t, even in 32-bit environments. In 178585484eSchristos * such an environment sizeof(time_t) could be bigger than sizeof(long) 188585484eSchristos * and the commonly used idiom of casting to long leads to truncation. 198585484eSchristos * 208585484eSchristos * As the printf() family has no standardised type specifier for time_t, 218585484eSchristos * guessing the right output format specifier is a bit troublesome and 228585484eSchristos * best done with the help of the preprocessor and "config.h". 238585484eSchristos */ 248585484eSchristos #ifndef TIMETOA_H 258585484eSchristos #define TIMETOA_H 268585484eSchristos 278585484eSchristos #include "ntp_fp.h" 288585484eSchristos #include "ntp_stdlib.h" 298585484eSchristos #include "ntp_unixtime.h" 308585484eSchristos 318585484eSchristos /* 328585484eSchristos * Given the size of time_t, guess what can be used as an unsigned value 338585484eSchristos * to hold a time_t and the printf() format specifcation. 348585484eSchristos * 358585484eSchristos * These should be used with the string constant concatenation feature 368585484eSchristos * of the compiler like this: 378585484eSchristos * 388585484eSchristos * printf("a time stamp: %" TIME_FORMAT " and more\n", a_time_t_value); 398585484eSchristos * 408585484eSchristos * It's not exactly nice, but there's not much leeway once we want to 418585484eSchristos * use the printf() family on time_t values. 428585484eSchristos */ 438585484eSchristos 448585484eSchristos #if SIZEOF_TIME_T <= SIZEOF_INT 458585484eSchristos 468585484eSchristos typedef unsigned int u_time; 478585484eSchristos #define TIME_FORMAT "d" 488585484eSchristos #define UTIME_FORMAT "u" 498585484eSchristos 508585484eSchristos #elif SIZEOF_TIME_T <= SIZEOF_LONG 518585484eSchristos 528585484eSchristos typedef unsigned long u_time; 538585484eSchristos #define TIME_FORMAT "ld" 548585484eSchristos #define UTIME_FORMAT "lu" 558585484eSchristos 568585484eSchristos #elif defined(SIZEOF_LONG_LONG) && SIZEOF_TIME_T <= SIZEOF_LONG_LONG 578585484eSchristos 588585484eSchristos typedef unsigned long long u_time; 598585484eSchristos #define TIME_FORMAT "lld" 608585484eSchristos #define UTIME_FORMAT "llu" 618585484eSchristos 628585484eSchristos #else 638585484eSchristos #include "GRONK: what size has a time_t here?" 648585484eSchristos #endif 658585484eSchristos 668585484eSchristos /* 678585484eSchristos * general fractional time stamp formatting. 688585484eSchristos * 698585484eSchristos * secs - integral seconds of time stamp 708585484eSchristos * frac - fractional units 718585484eSchristos * prec - log10 of units per second (3=milliseconds, 6=microseconds,..) 728585484eSchristos * or in other words: the count of decimal digits required. 738585484eSchristos * If prec is < 0, abs(prec) is taken for the precision and secs 748585484eSchristos * is treated as an unsigned value. 758585484eSchristos * 768585484eSchristos * The function will eventually normalise the fraction and adjust the 778585484eSchristos * seconds accordingly. 788585484eSchristos * 798585484eSchristos * This function uses the string buffer library for the return value, 808585484eSchristos * so do not keep the resulting pointers around. 818585484eSchristos */ 828585484eSchristos extern const char * 838585484eSchristos format_time_fraction(time_t secs, long frac, int prec); 848585484eSchristos 858585484eSchristos #endif /* !defined(TIMETOA_H) */ 86