[git commit master] date: optional support for %N. Closes bug 1861.

Denys Vlasenko vda.linux at googlemail.com
Fri Jun 4 16:19:15 UTC 2010


commit: http://git.busybox.net/busybox/commit/?id=6c2406ac861f42536acb76606c90412324a0e733
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
date_main                                            862    1090    +228
clock_gettime                                          -      41     +41
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 1/0 up/down: 269/0)             Total: 269 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 coreutils/Config.in |    7 ++++++
 coreutils/date.c    |   59 +++++++++++++++++++++++++++++++++++++++++++++-----
 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') {
-- 
1.6.3.3



More information about the busybox-cvs mailing list