From a4180391acf904dde6ec72bd37b8f908f69ac3e8 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 31 Jan 2011 23:23:48 -0800 Subject: [PATCH] format-time-string now supports subsecond time stamp resolution --- doc/lispref/ChangeLog | 5 +++++ doc/lispref/os.texi | 8 +++++++- etc/ChangeLog | 5 +++++ etc/NEWS | 4 ++++ src/ChangeLog | 10 ++++++++++ src/editfns.c | 25 ++++++++++++++++--------- 6 files changed, 47 insertions(+), 10 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 063ea78c09a..a3a89219bff 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,8 @@ +2011-02-01 Paul Eggert + + format-time-string now supports subsecond time stamp resolution + * os.texi (Time Parsing): Document %N. + 2011-01-28 Chong Yidong * vol1.texi (Top): diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 576f847d98e..b226d676462 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -21,7 +21,7 @@ terminal and the screen. * System Environment:: Distinguish the name and kind of system. * User Identification:: Finding the name and user id of the user. * Time of Day:: Getting the current time. -* Time Conversion:: Converting a time from numeric form to +* Time Conversion:: Converting a time from numeric form to calendrical data and vice versa. * Time Parsing:: Converting a time from numeric form to text and vice versa. @@ -1336,6 +1336,12 @@ This stands for the month (01-12). This stands for the minute (00-59). @item %n This stands for a newline. +@item %N +This stands for the nanoseconds (000000000-999999999). To ask for +fewer digits, use @samp{%3N} for milliseconds, @samp{%6N} for +microseconds, etc. Any excess digits are discarded, without rounding. +Currently Emacs time stamps are at best microsecond resolution so the +last three digits generated by plain @samp{%N} are always zero. @item %p This stands for @samp{AM} or @samp{PM}, as appropriate. @item %r diff --git a/etc/ChangeLog b/etc/ChangeLog index db1c5d41c34..45dfb211bb0 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog @@ -1,3 +1,8 @@ +2011-02-01 Paul Eggert + + format-time-string now supports subsecond time stamp resolution + * NEWS: Document this. + 2011-01-28 Paul Eggert Redo spelling of Makefile variables to conform to POSIX. diff --git a/etc/NEWS b/etc/NEWS index a20ecd4fe7f..d1110b193cb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -169,6 +169,10 @@ get and set the SELinux context of a file. *** Tramp offers handlers for file-selinux-context and set-file-selinux-context for remote machines which support SELinux. ++++ +** The function format-time-string now supports the %N directive, for +higher-resolution time stamps. + ** The function kill-emacs is now run upon receipt of the signals SIGTERM and SIGHUP, and upon SIGINT in batch mode. diff --git a/src/ChangeLog b/src/ChangeLog index 2353116c8bd..c0c09875121 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2011-02-01 Paul Eggert + + format-time-string now supports subsecond time stamp resolution + * editfns.c (emacs_nmemftime): Renamed from emacs_memftimeu, + for consistency with its new argument and with gnulib nstrftime. + All callers changed. New argument NS. + (Fformat_time_string): Check that the time argument's microseconds + component, if any, is in range; this avoids integer overflow and + also nstrftime needs this. Document %N. + 2011-01-31 Andreas Schwab * image.c (DEF_IMGLIB_FN): Add parameter rettype, use it instead diff --git a/src/editfns.c b/src/editfns.c index 7364a5bcf15..1733580ee32 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -92,8 +92,8 @@ static void find_field (Lisp_Object, Lisp_Object, Lisp_Object, EMACS_INT *, Lisp_Object, EMACS_INT *); static void update_buffer_properties (EMACS_INT, EMACS_INT); static Lisp_Object region_limit (int); -static size_t emacs_memftimeu (char *, size_t, const char *, - size_t, const struct tm *, int); +static size_t emacs_nmemftime (char *, size_t, const char *, + size_t, const struct tm *, int, int); static void general_insert_function (void (*) (const unsigned char *, EMACS_INT), void (*) (Lisp_Object, EMACS_INT, EMACS_INT, EMACS_INT, @@ -1549,6 +1549,7 @@ or (if you need time as a string) `format-time-string'. */) /* Write information into buffer S of size MAXSIZE, according to the FORMAT of length FORMAT_LEN, using time information taken from *TP. Default to Universal Time if UT is nonzero, local time otherwise. + Use NS as the number of nanoseconds in the %N directive. Return the number of bytes written, not including the terminating '\0'. If S is NULL, nothing will be written anywhere; so to determine how many bytes would be written, use NULL for S and @@ -1557,7 +1558,8 @@ or (if you need time as a string) `format-time-string'. */) This function behaves like nstrftime, except it allows null bytes in FORMAT and it does not support nanoseconds. */ static size_t -emacs_memftimeu (char *s, size_t maxsize, const char *format, size_t format_len, const struct tm *tp, int ut) +emacs_nmemftime (char *s, size_t maxsize, const char *format, + size_t format_len, const struct tm *tp, int ut, int ns) { size_t total = 0; @@ -1574,7 +1576,7 @@ emacs_memftimeu (char *s, size_t maxsize, const char *format, size_t format_len, if (s) s[0] = '\1'; - result = nstrftime (s, maxsize, format, tp, ut, 0); + result = nstrftime (s, maxsize, format, tp, ut, ns); if (s) { @@ -1620,6 +1622,7 @@ by text that describes the specified date and time in TIME: %p is the locale's equivalent of either AM or PM. %M is the minute. %S is the second. +%N is the nanosecond, %6N the microsecond, %3N the millisecond, etc. %Z is the time zone name, %z is the numeric form. %s is the number of seconds since 1970-01-01 00:00:00 +0000. @@ -1649,13 +1652,17 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". */) { time_t value; int size; + int usec; + int ns; struct tm *tm; int ut = ! NILP (universal); CHECK_STRING (format_string); - if (! lisp_time_argument (time, &value, NULL)) + if (! (lisp_time_argument (time, &value, &usec) + && 0 <= usec && usec < 1000000)) error ("Invalid time specification"); + ns = usec * 1000; format_string = code_convert_string_norecord (format_string, Vlocale_coding_system, 1); @@ -1678,9 +1685,9 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". */) buf[0] = '\1'; BLOCK_INPUT; - result = emacs_memftimeu (buf, size, SSDATA (format_string), + result = emacs_nmemftime (buf, size, SSDATA (format_string), SBYTES (format_string), - tm, ut); + tm, ut, ns); UNBLOCK_INPUT; if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0')) return code_convert_string_norecord (make_unibyte_string (buf, result), @@ -1688,10 +1695,10 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z". */) /* If buffer was too small, make it bigger and try again. */ BLOCK_INPUT; - result = emacs_memftimeu (NULL, (size_t) -1, + result = emacs_nmemftime (NULL, (size_t) -1, SSDATA (format_string), SBYTES (format_string), - tm, ut); + tm, ut, ns); UNBLOCK_INPUT; size = result + 1; } -- 2.11.4.GIT