]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
date: %-N now means suppress extra digits
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 31 Dec 2021 08:45:03 +0000 (00:45 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 31 Dec 2021 18:53:29 +0000 (10:53 -0800)
* 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
bootstrap.conf
doc/coreutils.texi
src/date.c

diff --git a/NEWS b/NEWS
index b9d36c724bfef9d148854c69b4104681f7bda328..79320820f87f4b4433b888707f4dd5e069f6545c 100644 (file)
--- 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
index c2f74f406664626e915eba9acfa52127c7750ef7..afa2cdcb93c334e11a900387dd3c12d0bec3cbac 100644 (file)
@@ -119,6 +119,7 @@ gnulib_modules="
   getpass-gnu
   gettext-h
   gettime
+  gettime-res
   getugroups
   getusershell
   git-version-gen
index 49d2afbe209cec12340e6f41dae7c82358d3e5af..aa970da6c4ea6284baee5fb288254c27bbbdac35 100644 (file)
@@ -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.
index 4a7a4e24364050d81707703cd55d71afc20d49d2..b0a53ba6c0f1648742408ef0be79de92ca187c0c 100644 (file)
@@ -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;
 }