Date: Sun, 18 Oct 2020 13:11:43 -0700 From: Paul Eggert <eggert@cs.ucla.edu> Message-ID: <519bc685-8844-b341-31d3-91f5d8f2cb91@cs.ucla.edu> | <https://man.netbsd.org/timeval.3> says struct bintime | is meant to be used in the kernel only. Yes ... but nothing enforces that, and unenforced rules exist purely for the purposes of being broken, right? | I wonder how a nanosecond-resolution timestamp would | be converted to bintime and back without rounding error, The static inline functions used are in <sys/time.h> http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/time.h?annotate=1.79&only_wi... but they don't. If you were to do that sequence you'd typically loose a ns each time around. So we don't do that, if we have timespecs we work in timespecs, converting them backwards and forwards would be foolish. For parsedate, we start with text, so we can generate anything. Depending upon the input, we may lose precision whatever we convert that into, if the text form has sufficient precision - converting something with 15 digits after the radix into a timespec you have to lose the low order). Generating the format with the greatest precision available means we're less likely to lose - to use it for touch we'll need to convert to a timespec (and for some filesystems perhaps eventually to a timeval - or for others even to a time_t) and we might lose some of the accuracy then, but parsedate() (or some new variant thereof) output can also be used for other things than feeding to filesystem sys calls. kre ps: here's a little userland (NetBSD buildable) program, with absolutely no error checking, which demonstrates the rounding issue. #include <sys/time.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char *argv[]) { struct timespec ts, nts; struct bintime bt; ts.tv_sec = strtol(argv[1], 0, 0); ts.tv_nsec = strtol(argv[2], 0, 0); timespec2bintime(&ts, &bt); bintime2timespec(&bt, &nts); printf("%jd.%9.9ju -> %jx.%8.8jx -> %jd.%9.9ju", (intmax_t)ts.tv_sec, (intmax_t)ts.tv_nsec, (intmax_t)bt.sec, (intmax_t)bt.frac, (intmax_t)nts.tv_sec, (intmax_t)nts.tv_nsec); if (ts.tv_nsec != nts.tv_nsec) printf(" %jd ns change", (intmax_t)(nts.tv_nsec - ts.tv_nsec)); printf("\n"); return 0; }