summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/Config.in7
-rw-r--r--coreutils/date.c59
2 files changed, 60 insertions, 6 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index ead632a..37e885c 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 4e5b3b0..c1390be 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') {