diff options
-rw-r--r-- | src/date.c | 60 |
1 files changed, 31 insertions, 29 deletions
diff --git a/src/date.c b/src/date.c index cc2659552..2942169fa 100644 --- a/src/date.c +++ b/src/date.c @@ -33,21 +33,19 @@ #include "getline.h" #include "posixtm.h" #include "posixver.h" +#include "timespec.h" /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "date" #define AUTHORS "David MacKenzie" -#ifndef STDC_HEADERS -size_t strftime (); -time_t time (); -#endif - int putenv (); -int stime (); -static void show_date PARAMS ((const char *format, time_t when)); +size_t nstrftime PARAMS ((char *, size_t, char const *, + struct tm const *, int, int)); + +static void show_date PARAMS ((const char *format, struct timespec when)); enum Time_spec { @@ -181,6 +179,7 @@ specifies Coordinated Universal Time. Interpreted sequences are:\n\ "), stdout); fputs (_("\ %n a newline\n\ + %N nanoseconds (000000000..999999999)\n\ %p locale's upper case AM or PM indicator\n\ %P locale's lower case am or pm indicator\n\ %r time, 12-hour (hh:mm:ss [AP]M)\n\ @@ -233,7 +232,7 @@ batch_convert (const char *input_filename, const char *format) char *line; int line_length; size_t buflen; - time_t when; + struct timespec when; if (strcmp (input_filename, "-") == 0) { @@ -261,9 +260,10 @@ batch_convert (const char *input_filename, const char *format) break; } - when = get_date (line, NULL); + when.tv_sec = get_date (line, NULL); + when.tv_nsec = 0; /* FIXME: get_date should set this. */ - if (when == -1) + if (when.tv_sec == -1) { if (line[line_length - 1] == '\n') line[line_length - 1] = '\0'; @@ -291,7 +291,7 @@ main (int argc, char **argv) int optc; const char *datestr = NULL; const char *set_datestr = NULL; - time_t when; + struct timespec when; int set_date = 0; char *format; char *batch_file = NULL; @@ -411,6 +411,7 @@ argument must be a format string beginning with `+'."), } else { + bool invalid_date = false; status = 0; if (!option_specified_date && !set_date) @@ -421,15 +422,19 @@ argument must be a format string beginning with `+'."), given in the POSIX-format. */ set_date = 1; datestr = argv[optind]; - when = posixtime (datestr, - PDS_TRAILING_YEAR | PDS_CENTURY | PDS_SECONDS); + when.tv_sec = posixtime (datestr, + (PDS_TRAILING_YEAR + | PDS_CENTURY | PDS_SECONDS)); + when.tv_nsec = 0; /* FIXME: posixtime should set this. */ + invalid_date = (when.tv_sec == (time_t) -1); format = NULL; } else { /* Prepare to print the current date/time. */ datestr = _("undefined"); - time (&when); + if (gettime (&when) != 0) + error (EXIT_FAILURE, errno, _("cannot get time of day")); format = (n_args == 1 ? argv[optind] + 1 : NULL); } } @@ -440,24 +445,27 @@ argument must be a format string beginning with `+'."), { if (stat (reference, &refstats)) error (1, errno, "%s", reference); - when = refstats.st_mtime; + when.tv_sec = refstats.st_mtime; + when.tv_nsec = TIMESPEC_NS (refstats.st_mtim); } else { - when = get_date (datestr, NULL); + when.tv_sec = get_date (datestr, NULL); + when.tv_nsec = 0; /* FIXME: get_date should set this. */ + invalid_date = (when.tv_sec == (time_t) -1); } format = (n_args == 1 ? argv[optind] + 1 : NULL); } - if (when == -1) + if (invalid_date) error (1, 0, _("invalid date `%s'"), datestr); if (set_date) { /* Set the system clock to the specified date, then regardless of the success of that operation, format and print that date. */ - if (stime (&when) == -1) + if (settime (&when) != 0) { error (0, errno, _("cannot set date")); status = 1; @@ -475,7 +483,7 @@ argument must be a format string beginning with `+'."), standard output format (ctime style but with a timezone inserted). */ static void -show_date (const char *format, time_t when) +show_date (const char *format, struct timespec when) { struct tm *tm; char *out = NULL; @@ -489,17 +497,10 @@ show_date (const char *format, time_t when) "%Y-%m-%dT%H:%M:%S%z" }; - tm = localtime (&when); + tm = localtime (&when.tv_sec); if (format == NULL) { - /* Print the date in the default format. Vanilla ANSI C strftime - doesn't support %e, but POSIX requires it. If you don't use - a GNU strftime, make sure yours supports %e. - If you are not using GNU strftime, you want to change %z - in the RFC format to %Z; this gives, however, an invalid - RFC time format outside the continental United States and GMT. */ - if (rfc_format) format = "%a, %d %b %Y %H:%M:%S %z"; else if (iso_8601_format) @@ -530,7 +531,7 @@ show_date (const char *format, time_t when) out = (char *) xrealloc (out, out_length); /* Mark the first byte of the buffer so we can detect the case - of strftime producing an empty string. Otherwise, this loop + of nstrftime producing an empty string. Otherwise, this loop would not terminate when date was invoked like this `LANG=de date +%p' on a system with good language support. */ out[0] = '\1'; @@ -538,7 +539,8 @@ show_date (const char *format, time_t when) if (rfc_format) setlocale (LC_ALL, "C"); - done = (strftime (out, out_length, format, tm) || out[0] == '\0'); + done = (nstrftime (out, out_length, format, tm, 0, when.tv_nsec) + || out[0] == '\0'); if (rfc_format) setlocale (LC_ALL, ""); |