diff options
-rw-r--r-- | coreutils/Config.in | 7 | ||||
-rw-r--r-- | coreutils/date.c | 59 |
2 files changed, 60 insertions, 6 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in index ead632a31..37e885c1c 100644 --- a/coreutils/Config.in +++ b/coreutils/Config.in @@ -115,6 +115,13 @@ config FEATURE_DATE_ISOFMT Enable option (-I) to output an ISO-8601 compliant date/time string. +config FEATURE_DATE_NANO + bool "Support %[num]N nanosecond format specifier" + default y + depends on DATE + help + Support %[num]N format specifier. Adds ~250 bytes of code. + config FEATURE_DATE_COMPAT bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format" default y diff --git a/coreutils/date.c b/coreutils/date.c index 4e5b3b0b8..c1390be76 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -84,9 +84,9 @@ static const char date_longopts[] ALIGN1 = int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int date_main(int argc UNUSED_PARAM, char **argv) { + struct timespec ts; struct tm tm_time; char buf_fmt_dt2str[64]; - time_t tm; unsigned opt; int ifmt = -1; char *date_str; @@ -161,11 +161,18 @@ int date_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_REFERENCE) { struct stat statbuf; xstat(filename, &statbuf); - tm = statbuf.st_mtime; + ts.tv_sec = statbuf.st_mtime; +#if ENABLE_FEATURE_DATE_NANO + ts.tv_nsec = statbuf.st_mtimensec; //or st_atim.tv_nsec? +#endif } else { - time(&tm); +#if ENABLE_FEATURE_DATE_NANO + clock_gettime(CLOCK_REALTIME, &ts); +#else + time(&ts.tv_nsec); +#endif } - localtime_r(&tm, &tm_time); + localtime_r(&ts.tv_sec, &tm_time); /* If date string is given, update tm_time, and maybe set date */ if (date_str != NULL) { @@ -184,12 +191,12 @@ int date_main(int argc UNUSED_PARAM, char **argv) /* Correct any day of week and day of year etc. fields */ tm_time.tm_isdst = -1; /* Be sure to recheck dst */ - tm = validate_tm_time(date_str, &tm_time); + ts.tv_sec = validate_tm_time(date_str, &tm_time); maybe_set_utc(opt); /* if setting time, set it */ - if ((opt & OPT_SET) && stime(&tm) < 0) { + if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) { bb_perror_msg("can't set date"); } } @@ -222,6 +229,46 @@ int date_main(int argc UNUSED_PARAM, char **argv) fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; } } +#if ENABLE_FEATURE_DATE_NANO + else { + /* User-specified fmt_dt2str */ + /* Search for and process "%N" */ + char *p = fmt_dt2str; + while ((p = strchr(p, '%')) != NULL) { + int n, m; + unsigned pres, scale; + + p++; + if (*p == '%') { + p++; + continue; + } + n = strspn(p, "0123456789"); + if (p[n] != 'N') { + p += n; + continue; + } + /* We have "%[nnn]N" */ + p[-1] = '\0'; + p[n] = '\0'; + scale = 1; + pres = 9; + if (n) { + pres = xatoi_u(p); + if (pres == 0) + pres = 9; + m = 9 - pres; + while (--m >= 0) + scale *= 10; + } + + m = p - fmt_dt2str; + p += n + 1; + fmt_dt2str = xasprintf("%s%0*u%s", fmt_dt2str, pres, (unsigned)ts.tv_nsec / scale, p); + p = fmt_dt2str + m; + } + } +#endif #define date_buf bb_common_bufsiz1 if (*fmt_dt2str == '\0') { |