From 0cd39a246af30d141be2676f1b4c1fd6616dfec5 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 31 Dec 2021 00:45:03 -0800 Subject: [PATCH 4/5] date: %-N now means suppress extra digits * NEWS, doc/coreutils.texi: Mention this. * bootstrap.conf (gnulib_modules): Add gettime-res. * src/date.c (res_width, adjust_resolution): New functions. (main): Adjust %-N to be %9N, or whatever, before using it. --- NEWS | 4 ++++ bootstrap.conf | 1 + doc/coreutils.texi | 6 ++++++ src/date.c | 40 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index b9d36c724..79320820f 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,10 @@ GNU coreutils NEWS -*- outline -*- ** Changes in behavior + date +'%-N' now suppresses excess trailing digits, instead of always + padding them with zeros to 9 digits. It uses clock_getres and + clock_gettime to infer the clock resolution. + timeout --foreground --kill-after=... will now exit with status 137 if the kill signal was sent, which is consistent with the behavior when the --foreground option is not specified. This allows users to diff --git a/bootstrap.conf b/bootstrap.conf index c2f74f406..afa2cdcb9 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -119,6 +119,7 @@ gnulib_modules=" getpass-gnu gettext-h gettime + gettime-res getugroups getusershell git-version-gen diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 49d2afbe2..aa970da6c 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -16227,6 +16227,12 @@ The following optional flags can appear after the @samp{%}: (hyphen) Do not pad the field; useful if the output is intended for human consumption. This is a GNU extension. +As a special case, @samp{%-N} outputs only enough trailing digits to +not lose information, assuming that the timestamp's resolution is the +same as the current hardware clock. For example, if the hardware +clock resolution is 1 microsecond, @samp{%s.%-N} outputs something +like @samp{1640890100.395710}. + @item _ (underscore) Pad with spaces; useful if you need a fixed number of characters in the output, but zeros are too distracting. diff --git a/src/date.c b/src/date.c index 4a7a4e243..b0a53ba6c 100644 --- a/src/date.c +++ b/src/date.c @@ -281,6 +281,39 @@ Show the local time for 9AM next Friday on the west coast of the US\n\ exit (status); } +/* Yield the number of decimal digits needed to output a time with the + nanosecond resolution RES, without losing information. */ + +static int +res_width (long int res) +{ + int i = 9; + for (long long int r = 1; (r *= 10) <= res; ) + i--; + return i; +} + +/* Return a newly allocated copy of FORMAT with each "%-N" adjusted to + be "%9N", "%6N", or whatever other resolution is appropriate for + the current platform. If no "%-N" appears, return NULL. */ + +static char * +adjust_resolution (char const *format) +{ + char *copy = NULL; + + for (char const *f = format; *f; f++) + if (f[0] == '%' && f[1] == '-' && f[2] == 'N') + { + if (!copy) + copy = xstrdup (format); + copy[f + 1 - format] = '0' + res_width (gettime_res ()); + f += 2; + } + + return copy; +} + /* Parse each line in INPUT_FILENAME as with --date and display each resulting time and date. If the file cannot be opened, tell why then exit. Issue a diagnostic for any lines that cannot be parsed. @@ -505,11 +538,13 @@ main (int argc, char **argv) } } + char *format_copy = adjust_resolution (format); + char const *format_res = format_copy ? format_copy : format; char const *tzstring = getenv ("TZ"); timezone_t tz = tzalloc (tzstring); if (batch_file != NULL) - ok = batch_convert (batch_file, format, tz, tzstring); + ok = batch_convert (batch_file, format_res, tz, tzstring); else { bool valid_date = true; @@ -568,10 +603,11 @@ main (int argc, char **argv) } } - ok &= show_date (format, when, tz); + ok &= show_date (format_res, when, tz); } IF_LINT (tzfree (tz)); + IF_LINT (free (format_copy)); return ok ? EXIT_SUCCESS : EXIT_FAILURE; } -- 2.32.0