Used by the toybox touch test suite (and thus necessary to pass the toybox tests on a toybox-only system). --- tests/date.test | 10 ++++++++++ toys/posix/date.c | 50 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 49 insertions(+), 11 deletions(-)
From c998db70bb5a47f2290d3c5c08df398528ea4906 Mon Sep 17 00:00:00 2001 From: Elliott Hughes <e...@google.com> Date: Sat, 15 Apr 2017 11:13:31 -0700 Subject: [PATCH] Support the %N coreutils/busybox extension to date.
Used by the toybox touch test suite (and thus necessary to pass the toybox tests on a toybox-only system). --- tests/date.test | 10 ++++++++++ toys/posix/date.c | 50 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/tests/date.test b/tests/date.test index d59d7fc..f222a0f 100644 --- a/tests/date.test +++ b/tests/date.test @@ -21,3 +21,13 @@ testing "-d 111014312015.30" "TZ=UTC date -d 111014312015.30 2>&1" "Sun Nov 10 1 # Accidentally given a Unix time, we should trivially reject that. testing "Unix time missing @" "TZ=UTC date 1438053157 2>/dev/null || echo no" \ "no\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" "" "" +testing "%2N" "touch -d 2012-01-23T12:34:56.123456789 f && date -r f +%Y%m%d-%H%M%S.%2N" "20120123-123456.12\n" "" "" +testing "%8N" "touch -d 2012-01-23T12:34:56.123456789 f && date -r f +%Y%m%d-%H%M%S.%8N" "20120123-123456.12345678\n" "" "" +testing "%9N" "touch -d 2012-01-23T12:34:56.123456789 f && date -r f +%Y%m%d-%H%M%S.%9N" "20120123-123456.123456789\n" "" "" +testing "%10N" "touch -d 2012-01-23T12:34:56.123456789 f && date -r f +%Y%m%d-%H%M%S.%10N" "20120123-123456.0123456789\n" "" "" +testing "%20N" "touch -d 2012-01-23T12:34:56.123456789 f && date -r f +%Y%m%d-%H%M%S.%20N" "20120123-123456.00000000000123456789\n" "" "" +rm -f f diff --git a/toys/posix/date.c b/toys/posix/date.c index e77ff3a..c095f5d 100644 --- a/toys/posix/date.c +++ b/toys/posix/date.c @@ -26,7 +26,7 @@ config DATE -r Use modification time of FILE instead of current date -u Use UTC instead of current timezone - +FORMAT specifies display format string using these escapes: + +FORMAT specifies display format string using strftime(3) syntax: %% literal % %n newline %t tab %S seconds (00-60) %M minute (00-59) %m month (01-12) @@ -41,6 +41,8 @@ config DATE %D = "%m/%d/%y" %r = "%I : %M : %S %p" %T = "%H:%M:%S" %h = "%b" %x locale date %X locale time %c locale date/time + + As an extension, %N nanoseconds is also supported. */ #define FOR_date @@ -123,17 +125,48 @@ static int parse_default(char *str, struct tm *tm) return *str; } -void check_range(int a, int low, int high) +static void check_range(int a, int low, int high) { if (a<low) error_exit("%d<%d", a, low); if (a>high) error_exit("%d>%d", a, high); } +static void puts_time(char *fmt, struct tm *tm, long ns) +{ + char *s; + + // Find any %Ns and format them manually. + fmt = xstrdup(fmt); + for (s = fmt; s; s = strchr(s, '%')) { + int width, prec, i; + char *e = ++s, *new_fmt; + + e += strspn(s, "0123456789"); + if (*e++ != 'N') continue; + width = prec = xstrtol(s, NULL, 10); + if (width == 0) width = prec = 9; + else if (width < 9) for (i = width; i < 9; ++i) ns /= 10; + + new_fmt = xmprintf("%.*s%*.*ld%s", (int)(s-1-fmt), fmt, width, prec, ns, e); + free(fmt); + fmt = new_fmt; + } + + // Let strftime handle all the standard stuff. + if (!strftime(toybuf, sizeof(toybuf), fmt, tm)) + perror_exit("bad format '%s'", fmt); + + puts(toybuf); + free(fmt); +} + void date_main(void) { char *setdate = *toys.optargs, *format_string = "%a %b %e %H:%M:%S %Z %Y"; + struct timespec ts; struct tm tm; + memset(&ts, 0, sizeof(struct timespec)); memset(&tm, 0, sizeof(struct tm)); if (TT.showdate) { @@ -143,16 +176,14 @@ void date_main(void) if (!s || *s) goto bad_showdate; } else if (parse_default(TT.showdate, &tm)) goto bad_showdate; } else { - time_t now; - if (TT.file) { struct stat st; xstat(TT.file, &st); - now = st.st_mtim.tv_sec; - } else now = time(0); + ts = st.st_mtim; + } else clock_gettime(CLOCK_REALTIME, &ts); - ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&now, &tm); + ((toys.optflags & FLAG_u) ? gmtime_r : localtime_r)(&ts.tv_sec, &tm); } // Fall through if no arguments @@ -194,10 +225,7 @@ void date_main(void) if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date"); } - if (!strftime(toybuf, sizeof(toybuf), format_string, &tm)) - perror_exit("bad format '%s'", format_string); - puts(toybuf); - + puts_time(format_string, &tm, ts.tv_nsec); return; bad_showdate: -- 2.12.2.762.g0e3151a226-goog
_______________________________________________ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net