date: optional support for %N. Closes bug 1861.

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@googlemail.com>
This commit is contained in:
Denys Vlasenko 2010-06-04 18:19:15 +02:00
parent 8878c24c7d
commit 6c2406ac86
2 changed files with 60 additions and 6 deletions

View File

@ -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

View File

@ -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') {