[Toybox] [PATCH v2] xparsedate properly detect whether format contains seconds.

HONG Yifan elsk at google.com
Tue Sep 17 15:08:40 PDT 2024


The code below with "If format didn't already specify seconds, grab
seconds" detects whether the format contains seconds by relying on the
index of the format (with an i>2 predicate). However, the format
"%a %b %e %H:%M:%S %Z %Y" does not end with seconds, so we shouldn't
parse fraction of seconds here. On the other hand, the format
"%H:%M:%S" ends with seconds, so we should parse fraction of seconds
there.

Add a test for it; the test uses a >60 number for fraction of seconds
to trigger the bug before the fix. Without the fix, "12:34:56.777" are
recognized as "12:34:77", which is an invalid time.

Fixes: d1a446687a9c
    ("xparsedate: support default date(1) output format.")
---
 lib/xwrap.c     | 3 ++-
 tests/date.test | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/xwrap.c b/lib/xwrap.c
index d07f355a..e5b35bb7 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -1025,8 +1025,9 @@ void xparsedate(char *str, time_t *t, unsigned *nano, int endian)
   // Formats with seconds come first. Posix can't agree on whether 12 digits
   // has year before (touch -t) or year after (date), so support both.
   char *s = str, *p, *oldtz = 0, *formats[] = {"%Y-%m-%d %T", "%Y-%m-%dT%T",
+    "%H:%M:%S",
     "%a %b %e %H:%M:%S %Z %Y", // date(1) output format in POSIX/C locale.
-    "%H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%d", "%H:%M", "%m%d%H%M",
+    "%Y-%m-%d %H:%M", "%Y-%m-%d", "%H:%M", "%m%d%H%M",
     endian ? "%m%d%H%M%y" : "%y%m%d%H%M",
     endian ? "%m%d%H%M%C%y" : "%C%y%m%d%H%M"};
 
diff --git a/tests/date.test b/tests/date.test
index 9777edb3..3ec2659e 100644
--- a/tests/date.test
+++ b/tests/date.test
@@ -42,6 +42,9 @@ testing "Unix time missing @" "TZ=$tz date 1438053157 2>/dev/null || echo no" \
 testing "-d 12:34" 'TZ=UTC date -d 12:34 | grep -q " 12:34:00 UTC $this_year" && echo OK' "OK\n" "" ""
 testing "-d 12:34:56" 'TZ=UTC date -d 12:34:56 | grep -q " 12:34:56 UTC $this_year" && echo OK' "OK\n" "" ""
 
+# Test fraction
+testing "-d 12:34:56.777" 'date -d 12:34:56.777 +%H:%M:%S.%3N | grep -q "12:34:56.777" && echo OK' "OK\n" "" ""
+
 # Test the %N extension to srtftime(3) format strings.
 testing "%N" "touch -d 2012-01-23T12:34:56.123456789 f && date -r f +%Y%m%d-%H%M%S.%N" "20120123-123456.123456789\n" "" ""
 testing "%1N" "touch -d 2012-01-23T12:34:56.123456789 f && date -r f +%Y%m%d-%H%M%S.%1N" "20120123-123456.1\n" "" ""
-- 
2.46.0.662.g92d0881bb0-goog



More information about the Toybox mailing list