aboutsummaryrefslogtreecommitdiff
path: root/coreutils/date.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/date.c')
-rw-r--r--coreutils/date.c104
1 files changed, 98 insertions, 6 deletions
diff --git a/coreutils/date.c b/coreutils/date.c
index 4e5b3b0b8..3d78a5336 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -51,6 +51,47 @@
51 * and does not support -Ins 51 * and does not support -Ins
52 * -D FMT is a bbox extension for _input_ conversion of -d DATE 52 * -D FMT is a bbox extension for _input_ conversion of -d DATE
53 */ 53 */
54
55//kbuild:lib-$(CONFIG_DATE) += date.o
56
57//config:config DATE
58//config: bool "date"
59//config: default y
60//config: help
61//config: date is used to set the system date or display the
62//config: current time in the given format.
63//config:
64//config:config FEATURE_DATE_ISOFMT
65//config: bool "Enable ISO date format output (-I)"
66//config: default y
67//config: depends on DATE
68//config: help
69//config: Enable option (-I) to output an ISO-8601 compliant
70//config: date/time string.
71//config:
72//config:config FEATURE_DATE_NANO
73//config: bool "Support %[num]N nanosecond format specifier"
74//config: default n
75//config: depends on DATE
76//config: help
77//config: Support %[num]N format specifier. Adds ~250 bytes of code.
78//config:
79//config:config FEATURE_DATE_COMPAT
80//config: bool "Support weird 'date MMDDhhmm[[YY]YY][.ss]' format"
81//config: default y
82//config: depends on DATE
83//config: help
84//config: System time can be set by 'date -s DATE' and simply 'date DATE',
85//config: but formats of DATE string are different. 'date DATE' accepts
86//config: a rather weird MMDDhhmm[[YY]YY][.ss] format with completely
87//config: unnatural placement of year between minutes and seconds.
88//config: date -s (and other commands like touch -d) use more sensible
89//config: formats (for one, ISO format YYYY-MM-DD hh:mm:ss.ssssss).
90//config:
91//config: With this option off, 'date DATE' is 'date -s DATE' support
92//config: the same format. With it on, 'date DATE' additionally supports
93//config: MMDDhhmm[[YY]YY][.ss] format.
94
54#include "libbb.h" 95#include "libbb.h"
55 96
56enum { 97enum {
@@ -84,9 +125,9 @@ static const char date_longopts[] ALIGN1 =
84int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 125int date_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
85int date_main(int argc UNUSED_PARAM, char **argv) 126int date_main(int argc UNUSED_PARAM, char **argv)
86{ 127{
128 struct timespec ts;
87 struct tm tm_time; 129 struct tm tm_time;
88 char buf_fmt_dt2str[64]; 130 char buf_fmt_dt2str[64];
89 time_t tm;
90 unsigned opt; 131 unsigned opt;
91 int ifmt = -1; 132 int ifmt = -1;
92 char *date_str; 133 char *date_str;
@@ -161,11 +202,22 @@ int date_main(int argc UNUSED_PARAM, char **argv)
161 if (opt & OPT_REFERENCE) { 202 if (opt & OPT_REFERENCE) {
162 struct stat statbuf; 203 struct stat statbuf;
163 xstat(filename, &statbuf); 204 xstat(filename, &statbuf);
164 tm = statbuf.st_mtime; 205 ts.tv_sec = statbuf.st_mtime;
206#if ENABLE_FEATURE_DATE_NANO
207# if defined __GLIBC__ && !defined __UCLIBC__
208 ts.tv_nsec = statbuf.st_mtim.tv_nsec;
209# else
210 ts.tv_nsec = statbuf.st_mtimensec;
211# endif
212#endif
165 } else { 213 } else {
166 time(&tm); 214#if ENABLE_FEATURE_DATE_NANO
215 clock_gettime(CLOCK_REALTIME, &ts);
216#else
217 time(&ts.tv_nsec);
218#endif
167 } 219 }
168 localtime_r(&tm, &tm_time); 220 localtime_r(&ts.tv_sec, &tm_time);
169 221
170 /* If date string is given, update tm_time, and maybe set date */ 222 /* If date string is given, update tm_time, and maybe set date */
171 if (date_str != NULL) { 223 if (date_str != NULL) {
@@ -184,12 +236,12 @@ int date_main(int argc UNUSED_PARAM, char **argv)
184 236
185 /* Correct any day of week and day of year etc. fields */ 237 /* Correct any day of week and day of year etc. fields */
186 tm_time.tm_isdst = -1; /* Be sure to recheck dst */ 238 tm_time.tm_isdst = -1; /* Be sure to recheck dst */
187 tm = validate_tm_time(date_str, &tm_time); 239 ts.tv_sec = validate_tm_time(date_str, &tm_time);
188 240
189 maybe_set_utc(opt); 241 maybe_set_utc(opt);
190 242
191 /* if setting time, set it */ 243 /* if setting time, set it */
192 if ((opt & OPT_SET) && stime(&tm) < 0) { 244 if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) {
193 bb_perror_msg("can't set date"); 245 bb_perror_msg("can't set date");
194 } 246 }
195 } 247 }
@@ -222,6 +274,46 @@ int date_main(int argc UNUSED_PARAM, char **argv)
222 fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y"; 274 fmt_dt2str = (char*)"%a %b %e %H:%M:%S %Z %Y";
223 } 275 }
224 } 276 }
277#if ENABLE_FEATURE_DATE_NANO
278 else {
279 /* User-specified fmt_dt2str */
280 /* Search for and process "%N" */
281 char *p = fmt_dt2str;
282 while ((p = strchr(p, '%')) != NULL) {
283 int n, m;
284 unsigned pres, scale;
285
286 p++;
287 if (*p == '%') {
288 p++;
289 continue;
290 }
291 n = strspn(p, "0123456789");
292 if (p[n] != 'N') {
293 p += n;
294 continue;
295 }
296 /* We have "%[nnn]N" */
297 p[-1] = '\0';
298 p[n] = '\0';
299 scale = 1;
300 pres = 9;
301 if (n) {
302 pres = xatoi_u(p);
303 if (pres == 0)
304 pres = 9;
305 m = 9 - pres;
306 while (--m >= 0)
307 scale *= 10;
308 }
309
310 m = p - fmt_dt2str;
311 p += n + 1;
312 fmt_dt2str = xasprintf("%s%0*u%s", fmt_dt2str, pres, (unsigned)ts.tv_nsec / scale, p);
313 p = fmt_dt2str + m;
314 }
315 }
316#endif
225 317
226#define date_buf bb_common_bufsiz1 318#define date_buf bb_common_bufsiz1
227 if (*fmt_dt2str == '\0') { 319 if (*fmt_dt2str == '\0') {