New optional ZONE arg for format-time-string etc.
This simplifies time conversions in other time zones. It also prevents display-time-world tampering with TZ (Bug#21020). * admin/admin.el (add-release-logs): Use improved add-log-time-format API. * admin/merge-gnulib (GNULIB_MODULES): Add time_rz, timegm. (GNULIB_TOOL_FLAGS): Avoid flexmember, setenv, unsetenv. * configure.ac (tzalloc): Remove test for this, since Emacs no longer uses HAVE_TZALLOC directly. * doc/lispref/os.texi (Time of Day, Time Conversion) (Time Parsing): * etc/NEWS: Document the new behavior. Merge from gnulib, incorporating: 2015-07-25 strftime: fix newly-introduced bug on Solaris 2015-07-23 fprintftime, strftime: use timezone_t args * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate. * lib/strftime.c, lib/strftime.h, lib/time.in.h, m4/sys_time_h.m4: * m4/time_h.m4: Update from gnulib. * lib/time_rz.c, lib/timegm.c, m4/time_rz.m4, m4/timegm.m4: New files from gnulib. * lisp/time-stamp.el (time-stamp-string): * lisp/time.el (display-time-world-list) (display-time-world-display): Use new API, with time zone arg. * lisp/time.el (display-time-world-display): Fix race when current-time advances while we're running. * lisp/vc/add-log.el (add-log-iso8601-time-zone) (add-log-iso8601-time-string): Accept optional time zone arg. * lisp/vc/add-log.el (add-change-log-entry): * lisp/vc/log-edit.el (log-edit-changelog-ours-p): Use new arg. * nt/gnulib.mk: Propagate lib/gnulib.mk changes here. Add rules for the time module, since they're now needed for tzalloc etc. * src/conf_post.h (getenv_TZ, setenv_TZ): New macros. (emacs_getenv_TZ, emacs_setenv_TZ): New decls. * src/editfns.c: Include errno.h. (set_time_zone_rule): Omit unnecessary forward decl. (initial_tz): Remove, replacing with ... (local_tz, wall_clock_tz, utc_tz): New static vars and constants. (tzeqlen): New constant; prefer it to (sizeof "TZ=" - 1). (emacs_localtime_rz, emacs_mktime_z, xtzalloc, xtzfree) (tzlookup): New static functions. (init_editfns): New arg DUMPING. All uses changed. (init_editfns): Omit most initialization if dumping, not if !initialized. Initialize wall_clock_tz and local_tz. (emacs_nmemftime, format_time_string): Time zone argument can now be any time zone, not just a boolean for UTC or local time. All callers changed. (Fformat_time_string, Fencode_time, Fcurrent_time_string) (Fcurrent_time_zone): New optional arg ZONE. (Fdecode_time, Fset_time_zone_rule): ZONE arg can now also take the same form as with the other new additions. (decode_time_zone): Remove; no longer needed. (tzvalbuf): Now file-scope. (emacs_getenv_TZ, emacs_setenv_TZ): New functions. (syms_of_editfns): Define Qwall. * src/editfns.c (mktime_z) [!HAVE_TZALLOC]: * src/systime.h (mktime_z, timezone_t, tzalloc, tzfree) [!HAVE_TZALLOC]: Remove; now supplied by gnulib. * src/emacs.c (main): * src/lisp.h (init_editfns): Adjust to init_editfns API change.
This commit is contained in:
parent
4c55786d9b
commit
af32fa9562
26 changed files with 941 additions and 308 deletions
|
@ -38,14 +38,12 @@ Optional argument DATE is the release date, default today."
|
|||
emacs-minor-version))
|
||||
(read-string "Release date: "
|
||||
(progn (require 'add-log)
|
||||
(let ((add-log-time-zone-rule t))
|
||||
(funcall add-log-time-format))))))
|
||||
(funcall add-log-time-format nil t)))))
|
||||
(setq root (expand-file-name root))
|
||||
(unless (file-exists-p (expand-file-name "src/emacs.c" root))
|
||||
(user-error "%s doesn't seem to be the root of an Emacs source tree" root))
|
||||
(require 'add-log)
|
||||
(or date (setq date (let ((add-log-time-zone-rule t))
|
||||
(funcall add-log-time-format))))
|
||||
(or date (setq date (funcall add-log-time-format nil t)))
|
||||
(let* ((logs (process-lines "find" root "-name" "ChangeLog"))
|
||||
(entry (format "%s %s <%s>\n\n\t* Version %s released.\n\n"
|
||||
date
|
||||
|
|
|
@ -37,20 +37,20 @@ GNULIB_MODULES='
|
|||
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
|
||||
sig2str socklen stat-time stdalign stddef stdio
|
||||
stpcpy strftime strtoimax strtoumax symlink sys_stat
|
||||
sys_time time time_r timer-time timespec-add timespec-sub
|
||||
sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub
|
||||
unsetenv update-copyright utimens
|
||||
vla warnings
|
||||
'
|
||||
|
||||
GNULIB_TOOL_FLAGS='
|
||||
--avoid=close --avoid=dup
|
||||
--avoid=fchdir --avoid=fstat
|
||||
--avoid=fchdir --avoid=flexmember --avoid=fstat
|
||||
--avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow
|
||||
--avoid=open --avoid=openat-die --avoid=opendir
|
||||
--avoid=raise
|
||||
--avoid=save-cwd --avoid=select --avoid=sigprocmask
|
||||
--avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask
|
||||
--avoid=stdarg --avoid=stdbool
|
||||
--avoid=threadlib
|
||||
--avoid=threadlib --avoid=unsetenv
|
||||
--conditional-dependencies --import --no-changelog --no-vc-files
|
||||
--makefile-name=gnulib.mk
|
||||
'
|
||||
|
|
|
@ -4000,7 +4000,7 @@ AC_SUBST(KRB4LIB)
|
|||
|
||||
AC_CHECK_HEADERS(valgrind/valgrind.h)
|
||||
|
||||
AC_CHECK_FUNCS_ONCE(tzalloc tzset)
|
||||
AC_CHECK_FUNCS_ONCE(tzset)
|
||||
|
||||
ok_so_far=yes
|
||||
AC_CHECK_FUNC(socket, , ok_so_far=no)
|
||||
|
|
|
@ -1234,7 +1234,7 @@ three-element lists, with omitted @var{microsec} and @var{picosec}
|
|||
components defaulting to zero.
|
||||
|
||||
@cindex time value
|
||||
Function arguments, e.g., the @var{time-value} argument to
|
||||
Function arguments, e.g., the @var{time} argument to
|
||||
@code{current-time-string}, accept a more-general @dfn{time value}
|
||||
format, which can be a list of integers as above, or a single number
|
||||
for seconds since the epoch, or @code{nil} for the current time. You
|
||||
|
@ -1244,7 +1244,7 @@ of integers using @code{seconds-to-time}, and into other forms using
|
|||
@code{decode-time} and @code{float-time}. These functions are
|
||||
described in the following sections.
|
||||
|
||||
@defun current-time-string &optional time-value
|
||||
@defun current-time-string &optional time zone
|
||||
This function returns the current time and date as a human-readable
|
||||
string. The format does not vary for the initial part of the string,
|
||||
which contains the day of week, month, day of month, and time of day
|
||||
|
@ -1255,8 +1255,9 @@ characters from the beginning of the string rather than from the end,
|
|||
as the year might not have exactly four digits, and additional
|
||||
information may some day be added at the end.
|
||||
|
||||
The argument @var{time-value}, if given, specifies a time to format,
|
||||
instead of the current time.
|
||||
The argument @var{time}, if given, specifies a time to format,
|
||||
instead of the current time. The optional argument @var{zone}
|
||||
defaults to the current time zone rule.
|
||||
|
||||
@example
|
||||
@group
|
||||
|
@ -1275,9 +1276,9 @@ multiple of 1000, but this may change as higher-resolution clocks
|
|||
become available.
|
||||
@end defun
|
||||
|
||||
@defun float-time &optional time-value
|
||||
@defun float-time &optional time
|
||||
This function returns the current time as a floating-point number of
|
||||
seconds since the epoch. The optional argument @var{time-value}, if
|
||||
seconds since the epoch. The optional argument @var{time}, if
|
||||
given, specifies a time to convert instead of the current time.
|
||||
|
||||
@emph{Warning}: Since the result is floating point, it may not be
|
||||
|
@ -1286,14 +1287,14 @@ exact. Do not use this function if precise time stamps are required.
|
|||
@code{time-to-seconds} is an alias for this function.
|
||||
@end defun
|
||||
|
||||
@defun seconds-to-time time-value
|
||||
@defun seconds-to-time time
|
||||
This function converts a time value to list-of-integer form.
|
||||
For example, if @var{time-value} is a number, @code{(time-to-seconds
|
||||
(seconds-to-time @var{time-value}))} equals the number unless overflow
|
||||
For example, if @var{time} is a number, @code{(time-to-seconds
|
||||
(seconds-to-time @var{time}))} equals the number unless overflow
|
||||
or rounding errors occur.
|
||||
@end defun
|
||||
|
||||
@defun current-time-zone &optional time-value
|
||||
@defun current-time-zone &optional time zone
|
||||
@cindex time zone, current
|
||||
This function returns a list describing the time zone that the user is
|
||||
in.
|
||||
|
@ -1309,15 +1310,27 @@ adjustment, then the value is constant through time.
|
|||
If the operating system doesn't supply all the information necessary to
|
||||
compute the value, the unknown elements of the list are @code{nil}.
|
||||
|
||||
The argument @var{time-value}, if given, specifies a time value to
|
||||
analyze instead of the current time.
|
||||
The argument @var{time}, if given, specifies a time value to
|
||||
analyze instead of the current time. The optional argument @var{zone}
|
||||
defaults to the current time zone rule.
|
||||
@end defun
|
||||
|
||||
The current time zone is determined by the @env{TZ} environment
|
||||
@vindex TZ, environment variable
|
||||
The default time zone is determined by the @env{TZ} environment
|
||||
variable. @xref{System Environment}. For example, you can tell Emacs
|
||||
to use universal time with @code{(setenv "TZ" "UTC0")}. If @env{TZ}
|
||||
is not in the environment, Emacs uses a platform-dependent default
|
||||
time zone.
|
||||
to default to universal time with @code{(setenv "TZ" "UTC0")}. If
|
||||
@env{TZ} is not in the environment, Emacs uses system wall clock time,
|
||||
which is a platform-dependent default time zone.
|
||||
|
||||
@cindex time zone rule
|
||||
Functions that convert to and from local time accept an optional
|
||||
@dfn{time zone rule} argument, which specifies the conversion's time
|
||||
zone and daylight saving time history. If the time zone rule is
|
||||
omitted or @code{nil}, the conversion uses Emacs's default time zone.
|
||||
If it is @code{t}, the conversion uses Universal Time. If it is
|
||||
@code{wall}, the conversion uses the system wall clock time. If it is
|
||||
a string, the conversion uses the time zone rule equivalent to setting
|
||||
@env{TZ} to that string.
|
||||
|
||||
@node Time Conversion
|
||||
@section Time Conversion
|
||||
|
@ -1340,13 +1353,14 @@ count the number of years since the year 1 B.C., and do not skip zero
|
|||
as traditional Gregorian years do; for example, the year number
|
||||
@minus{}37 represents the Gregorian year 38 B.C@.
|
||||
|
||||
@defun decode-time &optional time-value
|
||||
@defun decode-time &optional time zone
|
||||
This function converts a time value into calendrical information. If
|
||||
you don't specify @var{time-value}, it decodes the current time. The return
|
||||
you don't specify @var{time}, it decodes the current time, and similarly
|
||||
@var{zone} defaults to the current time zone rule. The return
|
||||
value is a list of nine elements, as follows:
|
||||
|
||||
@example
|
||||
(@var{seconds} @var{minutes} @var{hour} @var{day} @var{month} @var{year} @var{dow} @var{dst} @var{zone})
|
||||
(@var{seconds} @var{minutes} @var{hour} @var{day} @var{month} @var{year} @var{dow} @var{dst} @var{utcoff})
|
||||
@end example
|
||||
|
||||
Here is what the elements mean:
|
||||
|
@ -1370,13 +1384,13 @@ The day of week, as an integer between 0 and 6, where 0 stands for
|
|||
Sunday.
|
||||
@item dst
|
||||
@code{t} if daylight saving time is effect, otherwise @code{nil}.
|
||||
@item zone
|
||||
An integer indicating the time zone, as the number of seconds east of
|
||||
Greenwich.
|
||||
@item utcoff
|
||||
An integer indicating the UTC offset in seconds, i.e., the number of
|
||||
seconds east of Greenwich.
|
||||
@end table
|
||||
|
||||
@strong{Common Lisp Note:} Common Lisp has different meanings for
|
||||
@var{dow} and @var{zone}.
|
||||
@var{dow} and @var{utcoff}.
|
||||
@end defun
|
||||
|
||||
@defun encode-time seconds minutes hour day month year &optional zone
|
||||
|
@ -1389,12 +1403,11 @@ Year numbers less than 100 are not treated specially. If you want them
|
|||
to stand for years above 1900, or years above 2000, you must alter them
|
||||
yourself before you call @code{encode-time}.
|
||||
|
||||
The optional argument @var{zone} defaults to the current time zone and
|
||||
its daylight saving time rules. If specified, it can be either a list
|
||||
(as you would get from @code{current-time-zone}), a string as in the
|
||||
@env{TZ} environment variable, @code{t} for Universal Time, or an
|
||||
integer (as you would get from @code{decode-time}). The specified
|
||||
zone is used without any further alteration for daylight saving time.
|
||||
The optional argument @var{zone} defaults to the current time zone rule.
|
||||
In addition to the usual time zone rule values, it can also be a list
|
||||
(as you would get from @code{current-time-zone}) or an integer (as
|
||||
from @code{decode-time}), applied without any further alteration for
|
||||
daylight saving time.
|
||||
|
||||
If you pass more than seven arguments to @code{encode-time}, the first
|
||||
six are used as @var{seconds} through @var{year}, the last argument is
|
||||
|
@ -1430,11 +1443,12 @@ This function parses the time-string @var{string} and returns the
|
|||
corresponding time value.
|
||||
@end defun
|
||||
|
||||
@defun format-time-string format-string &optional time-value universal
|
||||
@defun format-time-string format-string &optional time zone
|
||||
|
||||
This function converts @var{time-value} (or the current time, if
|
||||
@var{time-value} is omitted) to a string according to
|
||||
@var{format-string}. The argument
|
||||
This function converts @var{time} (or the current time, if
|
||||
@var{time} is omitted) to a string according to
|
||||
@var{format-string}. The conversion uses the time zone rule @var{zone}
|
||||
(or the current time zone rule, if omitted). The argument
|
||||
@var{format-string} may contain @samp{%}-sequences which say to
|
||||
substitute parts of the time. Here is a table of what the
|
||||
@samp{%}-sequences mean:
|
||||
|
|
9
etc/NEWS
9
etc/NEWS
|
@ -1014,6 +1014,15 @@ key works) by typing ‘A-[’ and ‘A-]’.
|
|||
+++
|
||||
** Time-related changes:
|
||||
|
||||
*** Time conversion functions now accept an optional ZONE argument
|
||||
that specifies the time zone rules for conversion. ZONE is omitted or
|
||||
nil for Emacs local time, t for Universal Time, ‘wall’ for system wall
|
||||
clock time, or a string as in ‘set-time-zone-rule’ for a time zone
|
||||
rule. The affected functions are ‘current-time-string’,
|
||||
‘current-time-zone’, ‘decode-time’, and ‘format-time-string’. The
|
||||
function ‘encode-time’, which already accepted a simple time zone rule
|
||||
argument, has been extended to accept all the new forms.
|
||||
|
||||
*** Time-related functions now consistently accept numbers
|
||||
(representing seconds since the epoch) and nil (representing the
|
||||
current time) as well as the usual list-of-integer representation.
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=flexmember --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
|
||||
|
||||
|
||||
MOSTLYCLEANFILES += core *.stackdump
|
||||
|
@ -655,6 +655,17 @@ EXTRA_libgnu_a_SOURCES += mktime.c
|
|||
|
||||
## end gnulib module mktime
|
||||
|
||||
## begin gnulib module mktime-internal
|
||||
|
||||
if gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31
|
||||
|
||||
endif
|
||||
EXTRA_DIST += mktime-internal.h mktime.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += mktime.c
|
||||
|
||||
## end gnulib module mktime-internal
|
||||
|
||||
## begin gnulib module openat-h
|
||||
|
||||
if gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7
|
||||
|
@ -1589,10 +1600,12 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(
|
|||
-e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \
|
||||
-e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \
|
||||
-e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \
|
||||
-e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \
|
||||
-e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
|
||||
-e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \
|
||||
-e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \
|
||||
-e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \
|
||||
-e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \
|
||||
-e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \
|
||||
-e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \
|
||||
-e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \
|
||||
|
@ -1624,6 +1637,24 @@ EXTRA_libgnu_a_SOURCES += time_r.c
|
|||
|
||||
## end gnulib module time_r
|
||||
|
||||
## begin gnulib module time_rz
|
||||
|
||||
|
||||
EXTRA_DIST += time_rz.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += time_rz.c
|
||||
|
||||
## end gnulib module time_rz
|
||||
|
||||
## begin gnulib module timegm
|
||||
|
||||
|
||||
EXTRA_DIST += mktime-internal.h timegm.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += timegm.c
|
||||
|
||||
## end gnulib module timegm
|
||||
|
||||
## begin gnulib module timespec
|
||||
|
||||
libgnu_a_SOURCES += timespec.c
|
||||
|
@ -1806,15 +1837,6 @@ EXTRA_DIST += unistd.in.h
|
|||
|
||||
## end gnulib module unistd
|
||||
|
||||
## begin gnulib module unsetenv
|
||||
|
||||
|
||||
EXTRA_DIST += unsetenv.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += unsetenv.c
|
||||
|
||||
## end gnulib module unsetenv
|
||||
|
||||
## begin gnulib module update-copyright
|
||||
|
||||
|
||||
|
|
|
@ -121,22 +121,11 @@ extern char *tzname[];
|
|||
|
||||
|
||||
#ifdef _LIBC
|
||||
# define mktime_z(tz, tm) mktime (tm)
|
||||
# define tzname __tzname
|
||||
# define tzset __tzset
|
||||
#endif
|
||||
|
||||
#if !HAVE_TM_GMTOFF
|
||||
/* Portable standalone applications should supply a "time.h" that
|
||||
declares a POSIX-compliant localtime_r, for the benefit of older
|
||||
implementations that lack localtime_r or have a nonstandard one.
|
||||
See the gnulib time_r module for one way to implement this. */
|
||||
# undef __gmtime_r
|
||||
# undef __localtime_r
|
||||
# define __gmtime_r gmtime_r
|
||||
# define __localtime_r localtime_r
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FPRINTFTIME
|
||||
# define FPRINTFTIME 0
|
||||
#endif
|
||||
|
@ -385,12 +374,7 @@ iso_week_days (int yday, int wday)
|
|||
|
||||
/* When compiling this file, GNU applications can #define my_strftime
|
||||
to a symbol (typically nstrftime) to get an extended strftime with
|
||||
extra arguments UT and NS. Emacs is a special case for now, but
|
||||
this Emacs-specific code can be removed once Emacs's config.h
|
||||
defines my_strftime. */
|
||||
#if defined emacs && !defined my_strftime
|
||||
# define my_strftime nstrftime
|
||||
#endif
|
||||
extra arguments TZ and NS. */
|
||||
|
||||
#if FPRINTFTIME
|
||||
# undef my_strftime
|
||||
|
@ -398,8 +382,9 @@ iso_week_days (int yday, int wday)
|
|||
#endif
|
||||
|
||||
#ifdef my_strftime
|
||||
# define extra_args , ut, ns
|
||||
# define extra_args_spec , int ut, int ns
|
||||
# undef HAVE_TZSET
|
||||
# define extra_args , tz, ns
|
||||
# define extra_args_spec , timezone_t tz, int ns
|
||||
#else
|
||||
# if defined COMPILE_WIDE
|
||||
# define my_strftime wcsftime
|
||||
|
@ -411,7 +396,7 @@ iso_week_days (int yday, int wday)
|
|||
# define extra_args
|
||||
# define extra_args_spec
|
||||
/* We don't have this information in general. */
|
||||
# define ut 0
|
||||
# define tz 1
|
||||
# define ns 0
|
||||
#endif
|
||||
|
||||
|
@ -483,7 +468,7 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
zone = (const char *) tp->tm_zone;
|
||||
#endif
|
||||
#if HAVE_TZNAME
|
||||
if (ut)
|
||||
if (!tz)
|
||||
{
|
||||
if (! (zone && *zone))
|
||||
zone = "GMT";
|
||||
|
@ -496,7 +481,12 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
tzset ();
|
||||
# endif
|
||||
}
|
||||
/* The tzset() call might have changed the value. */
|
||||
if (!(zone && *zone) && tp->tm_isdst >= 0)
|
||||
zone = tzname[tp->tm_isdst != 0];
|
||||
#endif
|
||||
if (! zone)
|
||||
zone = "";
|
||||
|
||||
if (hour12 > 12)
|
||||
hour12 -= 12;
|
||||
|
@ -1144,7 +1134,7 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
time_t t;
|
||||
|
||||
ltm = *tp;
|
||||
t = mktime (<m);
|
||||
t = mktime_z (tz, <m);
|
||||
|
||||
/* Generate string value for T using time_t arithmetic;
|
||||
this works even if sizeof (long) < sizeof (time_t). */
|
||||
|
@ -1319,14 +1309,6 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
to_lowcase = true;
|
||||
}
|
||||
|
||||
#if HAVE_TZNAME
|
||||
/* The tzset() call might have changed the value. */
|
||||
if (!(zone && *zone) && tp->tm_isdst >= 0)
|
||||
zone = tzname[tp->tm_isdst != 0];
|
||||
#endif
|
||||
if (! zone)
|
||||
zone = "";
|
||||
|
||||
#ifdef COMPILE_WIDE
|
||||
{
|
||||
/* The zone string is always given in multibyte form. We have
|
||||
|
@ -1366,7 +1348,7 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
#if HAVE_TM_GMTOFF
|
||||
diff = tp->tm_gmtoff;
|
||||
#else
|
||||
if (ut)
|
||||
if (!tz)
|
||||
diff = 0;
|
||||
else
|
||||
{
|
||||
|
@ -1375,7 +1357,7 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
time_t lt;
|
||||
|
||||
ltm = *tp;
|
||||
lt = mktime (<m);
|
||||
lt = mktime_z (tz, <m);
|
||||
|
||||
if (lt == (time_t) -1)
|
||||
{
|
||||
|
@ -1384,7 +1366,7 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
occurred. */
|
||||
struct tm tm;
|
||||
|
||||
if (! __localtime_r (<, &tm)
|
||||
if (! localtime_rz (tz, <, &tm)
|
||||
|| ((ltm.tm_sec ^ tm.tm_sec)
|
||||
| (ltm.tm_min ^ tm.tm_min)
|
||||
| (ltm.tm_hour ^ tm.tm_hour)
|
||||
|
@ -1394,7 +1376,7 @@ strftime_case_ (bool upcase, STREAM_OR_CHAR_T *s,
|
|||
break;
|
||||
}
|
||||
|
||||
if (! __gmtime_r (<, >m))
|
||||
if (! localtime_rz (0, <, >m))
|
||||
break;
|
||||
|
||||
diff = tm_diff (<m, >m);
|
||||
|
@ -1473,15 +1455,3 @@ my_strftime (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize)
|
|||
#if defined _LIBC && ! FPRINTFTIME
|
||||
libc_hidden_def (my_strftime)
|
||||
#endif
|
||||
|
||||
|
||||
#if defined emacs && ! FPRINTFTIME
|
||||
/* For Emacs we have a separate interface which corresponds to the normal
|
||||
strftime function plus the ut argument, but without the ns argument. */
|
||||
size_t
|
||||
emacs_strftimeu (char *s, size_t maxsize, const char *format,
|
||||
const struct tm *tp, int ut)
|
||||
{
|
||||
return my_strftime (s, maxsize, format, tp, ut, 0);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,11 +23,10 @@ extern "C" {
|
|||
|
||||
/* Just like strftime, but with two more arguments:
|
||||
POSIX requires that strftime use the local timezone information.
|
||||
When __UTC is nonzero and tm->tm_zone is NULL or the empty string,
|
||||
use UTC instead. Use __NS as the number of nanoseconds in the
|
||||
%N directive. */
|
||||
Use the timezone __TZ instead. Use __NS as the number of
|
||||
nanoseconds in the %N directive. */
|
||||
size_t nstrftime (char *, size_t, char const *, struct tm const *,
|
||||
int __utc, int __ns);
|
||||
timezone_t __tz, int __ns);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -231,6 +231,25 @@ _GL_CXXALIAS_SYS (strptime, char *, (char const *restrict __buf,
|
|||
_GL_CXXALIASWARN (strptime);
|
||||
# endif
|
||||
|
||||
# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@
|
||||
typedef struct tm_zone *timezone_t;
|
||||
_GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name));
|
||||
_GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name));
|
||||
_GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz));
|
||||
_GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz));
|
||||
_GL_FUNCDECL_SYS (localtime_rz, struct tm *,
|
||||
(timezone_t __tz, time_t const *restrict __timer,
|
||||
struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3)));
|
||||
_GL_CXXALIAS_SYS (localtime_rz, struct tm *,
|
||||
(timezone_t __tz, time_t const *restrict __timer,
|
||||
struct tm *restrict __result));
|
||||
_GL_FUNCDECL_SYS (mktime_z, time_t,
|
||||
(timezone_t __tz, struct tm *restrict __result)
|
||||
_GL_ARG_NONNULL ((2)));
|
||||
_GL_CXXALIAS_SYS (mktime_z, time_t,
|
||||
(timezone_t __tz, struct tm *restrict __result));
|
||||
# endif
|
||||
|
||||
/* Convert TM to a time_t value, assuming UTC. */
|
||||
# if @GNULIB_TIMEGM@
|
||||
# if @REPLACE_TIMEGM@
|
||||
|
|
374
lib/time_rz.c
Normal file
374
lib/time_rz.c
Normal file
|
@ -0,0 +1,374 @@
|
|||
/* Time zone functions such as tzalloc and localtime_rz
|
||||
|
||||
Copyright 2015 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
/* Although this module is not thread-safe, any races should be fairly
|
||||
rare and reasonably benign. For complete thread-safety, use a C
|
||||
library with a working timezone_t type, so that this module is not
|
||||
needed. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !HAVE_TZSET
|
||||
static void tzset (void) { }
|
||||
#endif
|
||||
|
||||
/* A time zone rule. */
|
||||
struct tm_zone
|
||||
{
|
||||
/* More abbreviations, should they be needed. Their TZ_IS_SET
|
||||
members are zero. */
|
||||
timezone_t next;
|
||||
|
||||
/* If nonzero, the rule represents the TZ environment variable set
|
||||
to the first "abbreviation" (this may be the empty string).
|
||||
Otherwise, it represents an unset TZ. */
|
||||
char tz_is_set;
|
||||
|
||||
/* A sequence of null-terminated strings packed next to each other.
|
||||
The strings are followed by an extra null byte. If TZ_IS_SET,
|
||||
there must be at least one string and the first string (which is
|
||||
actually a TZ environment value value) may be empty. Otherwise
|
||||
all strings must be nonempty.
|
||||
|
||||
Abbreviations are stored here because otherwise the values of
|
||||
tm_zone and/or tzname would be dead after changing TZ and calling
|
||||
tzset. Abbreviations never move once allocated, and are live
|
||||
until tzfree is called. */
|
||||
char abbrs[FLEXIBLE_ARRAY_MEMBER];
|
||||
};
|
||||
|
||||
/* The approximate size to use for small allocation requests. This is
|
||||
the largest "small" request for the GNU C library malloc. */
|
||||
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
|
||||
|
||||
/* Minimum size of the ABBRS member of struct abbr. ABBRS is larger
|
||||
only in the unlikely case where an abbreviation longer than this is
|
||||
used. */
|
||||
enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) };
|
||||
|
||||
static char const TZ[] = "TZ";
|
||||
|
||||
/* Magic cookie timezone_t value, for local time. It differs from
|
||||
NULL and from all other timezone_t values. Only the address
|
||||
matters; the pointer is never dereferenced. */
|
||||
static timezone_t const local_tz = (timezone_t) 1;
|
||||
|
||||
#if HAVE_TM_ZONE || HAVE_TZNAME
|
||||
|
||||
/* Return true if the values A and B differ according to the rules for
|
||||
tm_isdst: A and B differ if one is zero and the other positive. */
|
||||
static bool
|
||||
isdst_differ (int a, int b)
|
||||
{
|
||||
return !a != !b && 0 <= a && 0 <= b;
|
||||
}
|
||||
|
||||
/* Return true if A and B are equal. */
|
||||
static int
|
||||
equal_tm (const struct tm *a, const struct tm *b)
|
||||
{
|
||||
return ! ((a->tm_sec ^ b->tm_sec)
|
||||
| (a->tm_min ^ b->tm_min)
|
||||
| (a->tm_hour ^ b->tm_hour)
|
||||
| (a->tm_mday ^ b->tm_mday)
|
||||
| (a->tm_mon ^ b->tm_mon)
|
||||
| (a->tm_year ^ b->tm_year)
|
||||
| isdst_differ (a->tm_isdst, b->tm_isdst));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this
|
||||
includes its trailing null byte). Append an extra null byte to
|
||||
mark the end of ABBRS. */
|
||||
static void
|
||||
extend_abbrs (char *abbrs, char const *abbr, size_t abbr_size)
|
||||
{
|
||||
memcpy (abbrs, abbr, abbr_size);
|
||||
abbrs[abbr_size] = '\0';
|
||||
}
|
||||
|
||||
/* Return a newly allocated time zone for NAME, or NULL on failure.
|
||||
As a special case, return a nonzero constant for wall clock time, a
|
||||
constant that survives freeing. */
|
||||
timezone_t
|
||||
tzalloc (char const *name)
|
||||
{
|
||||
size_t name_size = name ? strlen (name) + 1 : 0;
|
||||
size_t abbr_size = name_size < ABBR_SIZE_MIN ? ABBR_SIZE_MIN : name_size + 1;
|
||||
timezone_t tz = malloc (offsetof (struct tm_zone, abbrs) + abbr_size);
|
||||
if (tz)
|
||||
{
|
||||
tz->next = NULL;
|
||||
tz->tz_is_set = !!name;
|
||||
extend_abbrs (tz->abbrs, name, name_size);
|
||||
}
|
||||
return tz;
|
||||
}
|
||||
|
||||
#if HAVE_TZNAME
|
||||
/* If TZNAME_ADDRESS is nonnull, an assignment of a saved abbreviation.
|
||||
TZNAME_ADDRESS should be either null, or &tzname[0], or &tzname[1].
|
||||
*TZNAME_ADDRESS = TZNAME_VALUE should be done after revert_tz
|
||||
(indirectly) calls tzset, so that revert_tz can overwrite tzset's
|
||||
assignment to tzname. Also, it should be done at the start of
|
||||
the next localtime_tz or mktime_z, to undo the overwrite. */
|
||||
static char **tzname_address;
|
||||
static char *tzname_value;
|
||||
#endif
|
||||
|
||||
/* Save into TZ any nontrivial time zone abbreviation used by TM,
|
||||
and update *TM (or prepare to update tzname) if they use the abbreviation.
|
||||
Return true if successful, false (setting errno) otherwise. */
|
||||
static bool
|
||||
save_abbr (timezone_t tz, struct tm *tm)
|
||||
{
|
||||
#if HAVE_TM_ZONE || HAVE_TZNAME
|
||||
char const *zone = NULL;
|
||||
char **tzname_zone = NULL;
|
||||
char *zone_copy = (char *) "";
|
||||
# if HAVE_TM_ZONE
|
||||
zone = tm->tm_zone;
|
||||
# endif
|
||||
# if HAVE_TZNAME
|
||||
if (! (zone && *zone) && 0 <= tm->tm_isdst)
|
||||
zone = *(tzname_zone = &tzname[0 < tm->tm_isdst]);
|
||||
# endif
|
||||
|
||||
/* No need to replace null zones, or zones within the struct tm. */
|
||||
if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1)))
|
||||
return true;
|
||||
|
||||
if (*zone)
|
||||
{
|
||||
zone_copy = tz->abbrs;
|
||||
|
||||
while (strcmp (zone_copy, zone) != 0)
|
||||
{
|
||||
if (! (*zone_copy || (zone_copy == tz->abbrs && tz->tz_is_set)))
|
||||
{
|
||||
size_t zone_size = strlen (zone) + 1;
|
||||
if (zone_size < tz->abbrs + ABBR_SIZE_MIN - zone_copy)
|
||||
extend_abbrs (zone_copy, zone, zone_size);
|
||||
else
|
||||
{
|
||||
tz = tz->next = tzalloc (zone);
|
||||
if (!tz)
|
||||
return false;
|
||||
tz->tz_is_set = 0;
|
||||
zone_copy = tz->abbrs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
zone_copy += strlen (zone_copy) + 1;
|
||||
if (!*zone_copy && tz->next)
|
||||
{
|
||||
tz = tz->next;
|
||||
zone_copy = tz->abbrs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace the zone name so that its lifetime matches that of TZ. */
|
||||
# if HAVE_TM_ZONE
|
||||
if (!tzname_zone)
|
||||
tm->tm_zone = zone_copy;
|
||||
# endif
|
||||
# if HAVE_TZNAME
|
||||
tzname_address = tzname_zone;
|
||||
tzname_value = zone_copy;
|
||||
# endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Free a time zone. */
|
||||
void
|
||||
tzfree (timezone_t tz)
|
||||
{
|
||||
if (tz != local_tz)
|
||||
while (tz)
|
||||
{
|
||||
timezone_t next = tz->next;
|
||||
free (tz);
|
||||
tz = next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get and set the TZ environment variable. These functions can be
|
||||
overridden by programs like Emacs that manage their own environment. */
|
||||
|
||||
#ifndef getenv_TZ
|
||||
static char *
|
||||
getenv_TZ (void)
|
||||
{
|
||||
return getenv (TZ);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef setenv_TZ
|
||||
static int
|
||||
setenv_TZ (char const *tz)
|
||||
{
|
||||
return tz ? setenv (TZ, tz, 1) : unsetenv (TZ);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Change the environment to match the specified timezone_t value.
|
||||
Return true if successful, false (setting errno) otherwise. */
|
||||
static bool
|
||||
change_env (timezone_t tz)
|
||||
{
|
||||
if (setenv_TZ (tz->tz_is_set ? tz->abbrs : NULL) != 0)
|
||||
return false;
|
||||
tzset ();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Temporarily set the time zone to TZ, which must not be null.
|
||||
Return LOCAL_TZ if the time zone setting is already correct.
|
||||
Otherwise return a newly allocated time zone representing the old
|
||||
setting, or NULL (setting errno) on failure. */
|
||||
static timezone_t
|
||||
set_tz (timezone_t tz)
|
||||
{
|
||||
char *env_tz = getenv_TZ ();
|
||||
if (env_tz
|
||||
? tz->tz_is_set && strcmp (tz->abbrs, env_tz) == 0
|
||||
: !tz->tz_is_set)
|
||||
return local_tz;
|
||||
else
|
||||
{
|
||||
timezone_t old_tz = tzalloc (env_tz);
|
||||
if (!old_tz)
|
||||
return old_tz;
|
||||
if (! change_env (tz))
|
||||
{
|
||||
int saved_errno = errno;
|
||||
tzfree (old_tz);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
return old_tz;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore an old setting returned by set_tz. It must not be null.
|
||||
Return true (preserving errno) if successful, false (setting errno)
|
||||
otherwise. */
|
||||
static bool
|
||||
revert_tz (timezone_t tz)
|
||||
{
|
||||
if (tz == local_tz)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
int saved_errno = errno;
|
||||
bool ok = change_env (tz);
|
||||
if (!ok)
|
||||
saved_errno = errno;
|
||||
#if HAVE_TZNAME
|
||||
if (!ok)
|
||||
tzname_address = NULL;
|
||||
if (tzname_address)
|
||||
{
|
||||
char *old_value = *tzname_address;
|
||||
*tzname_address = tzname_value;
|
||||
tzname_value = old_value;
|
||||
}
|
||||
#endif
|
||||
tzfree (tz);
|
||||
errno = saved_errno;
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore an old tzname setting that was temporarily munged by revert_tz. */
|
||||
static void
|
||||
restore_tzname (void)
|
||||
{
|
||||
#if HAVE_TZNAME
|
||||
if (tzname_address)
|
||||
{
|
||||
*tzname_address = tzname_value;
|
||||
tzname_address = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Use time zone TZ to compute localtime_r (T, TM). */
|
||||
struct tm *
|
||||
localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
|
||||
{
|
||||
restore_tzname ();
|
||||
|
||||
if (!tz)
|
||||
return gmtime_r (t, tm);
|
||||
else
|
||||
{
|
||||
timezone_t old_tz = set_tz (tz);
|
||||
if (old_tz)
|
||||
{
|
||||
tm = localtime_r (t, tm);
|
||||
if (tm && !save_abbr (tz, tm))
|
||||
tm = NULL;
|
||||
if (revert_tz (old_tz))
|
||||
return tm;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use time zone TZ to compute mktime (TM). */
|
||||
time_t
|
||||
mktime_z (timezone_t tz, struct tm *tm)
|
||||
{
|
||||
restore_tzname ();
|
||||
|
||||
if (!tz)
|
||||
return timegm (tm);
|
||||
else
|
||||
{
|
||||
timezone_t old_tz = set_tz (tz);
|
||||
if (old_tz)
|
||||
{
|
||||
time_t t = mktime (tm);
|
||||
#if HAVE_TM_ZONE || HAVE_TZNAME
|
||||
time_t badtime = -1;
|
||||
struct tm tm_1;
|
||||
if ((t != badtime
|
||||
|| (localtime_r (&t, &tm_1) && equal_tm (tm, &tm_1)))
|
||||
&& !save_abbr (tz, tm))
|
||||
t = badtime;
|
||||
#endif
|
||||
if (revert_tz (old_tz))
|
||||
return t;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
38
lib/timegm.c
Normal file
38
lib/timegm.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* Convert UTC calendar time to simple time. Like mktime but assumes UTC.
|
||||
|
||||
Copyright (C) 1994, 1997, 2003-2004, 2006-2007, 2009-2015 Free Software
|
||||
Foundation, Inc. This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _LIBC
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifndef _LIBC
|
||||
# undef __gmtime_r
|
||||
# define __gmtime_r gmtime_r
|
||||
# define __mktime_internal mktime_internal
|
||||
# include "mktime-internal.h"
|
||||
#endif
|
||||
|
||||
time_t
|
||||
timegm (struct tm *tmp)
|
||||
{
|
||||
static time_t gmtime_offset;
|
||||
tmp->tm_isdst = 0;
|
||||
return __mktime_internal (tmp, __gmtime_r, &gmtime_offset);
|
||||
}
|
|
@ -420,16 +420,8 @@ format the string."
|
|||
(or ts-format
|
||||
(setq ts-format time-stamp-format))
|
||||
(if (stringp ts-format)
|
||||
(if (stringp time-stamp-time-zone)
|
||||
(let ((ts-real-time-zone (getenv "TZ")))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setenv "TZ" time-stamp-time-zone)
|
||||
(format-time-string
|
||||
(time-stamp-string-preprocess ts-format)))
|
||||
(setenv "TZ" ts-real-time-zone)))
|
||||
(format-time-string
|
||||
(time-stamp-string-preprocess ts-format)))
|
||||
(format-time-string (time-stamp-string-preprocess ts-format)
|
||||
nil time-stamp-time-zone)
|
||||
;; handle version 1 compatibility
|
||||
(cond ((or (eq time-stamp-old-format-warn 'error)
|
||||
(and (eq time-stamp-old-format-warn 'ask)
|
||||
|
|
33
lisp/time.el
33
lisp/time.el
|
@ -160,15 +160,8 @@ LABEL is a string to display as the label of that TIMEZONE's time."
|
|||
(defcustom display-time-world-list
|
||||
;; Determine if zoneinfo style timezones are supported by testing that
|
||||
;; America/New York and Europe/London return different timezones.
|
||||
(let ((old-tz (getenv "TZ"))
|
||||
gmt nyt)
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setenv "TZ" "America/New_York")
|
||||
(setq nyt (format-time-string "%z"))
|
||||
(setenv "TZ" "Europe/London")
|
||||
(setq gmt (format-time-string "%z")))
|
||||
(setenv "TZ" old-tz))
|
||||
(let ((nyt (format-time-string "%z" nil "America/New_York"))
|
||||
(gmt (format-time-string "%z" nil "Europe/London")))
|
||||
(if (string-equal nyt gmt)
|
||||
legacy-style-world-list
|
||||
zoneinfo-style-world-list))
|
||||
|
@ -523,21 +516,19 @@ See `display-time-world'."
|
|||
"Replace current buffer text with times in various zones, based on ALIST."
|
||||
(let ((inhibit-read-only t)
|
||||
(buffer-undo-list t)
|
||||
(old-tz (getenv "TZ"))
|
||||
(now (current-time))
|
||||
(max-width 0)
|
||||
result fmt)
|
||||
(erase-buffer)
|
||||
(unwind-protect
|
||||
(dolist (zone alist)
|
||||
(let* ((label (cadr zone))
|
||||
(width (string-width label)))
|
||||
(setenv "TZ" (car zone))
|
||||
(push (cons label
|
||||
(format-time-string display-time-world-time-format))
|
||||
result)
|
||||
(when (> width max-width)
|
||||
(setq max-width width))))
|
||||
(setenv "TZ" old-tz))
|
||||
(dolist (zone alist)
|
||||
(let* ((label (cadr zone))
|
||||
(width (string-width label)))
|
||||
(push (cons label
|
||||
(format-time-string display-time-world-time-format
|
||||
now (car zone)))
|
||||
result)
|
||||
(when (> width max-width)
|
||||
(setq max-width width))))
|
||||
(setq fmt (concat "%-" (int-to-string max-width) "s %s\n"))
|
||||
(dolist (timedata (nreverse result))
|
||||
(insert (format fmt (car timedata) (cdr timedata))))
|
||||
|
|
|
@ -581,8 +581,8 @@ If t, use universal time.")
|
|||
(put 'add-log-time-zone-rule 'safe-local-variable
|
||||
(lambda (x) (or (booleanp x) (stringp x))))
|
||||
|
||||
(defun add-log-iso8601-time-zone (&optional time)
|
||||
(let* ((utc-offset (or (car (current-time-zone time)) 0))
|
||||
(defun add-log-iso8601-time-zone (&optional time zone)
|
||||
(let* ((utc-offset (or (car (current-time-zone time zone)) 0))
|
||||
(sign (if (< utc-offset 0) ?- ?+))
|
||||
(sec (abs utc-offset))
|
||||
(ss (% sec 60))
|
||||
|
@ -596,12 +596,11 @@ If t, use universal time.")
|
|||
|
||||
(defvar add-log-iso8601-with-time-zone nil)
|
||||
|
||||
(defun add-log-iso8601-time-string ()
|
||||
(let ((time (format-time-string "%Y-%m-%d"
|
||||
nil (eq t add-log-time-zone-rule))))
|
||||
(defun add-log-iso8601-time-string (&optional time zone)
|
||||
(let ((date (format-time-string "%Y-%m-%d" time zone)))
|
||||
(if add-log-iso8601-with-time-zone
|
||||
(concat time " " (add-log-iso8601-time-zone))
|
||||
time)))
|
||||
(concat date " " (add-log-iso8601-time-zone time zone))
|
||||
date)))
|
||||
|
||||
(defun change-log-name ()
|
||||
"Return (system-dependent) default name for a change log file."
|
||||
|
@ -848,14 +847,8 @@ non-nil, otherwise in local time."
|
|||
(let ((new-entries
|
||||
(mapcar (lambda (addr)
|
||||
(concat
|
||||
(if (stringp add-log-time-zone-rule)
|
||||
(let ((tz (getenv "TZ")))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setenv "TZ" add-log-time-zone-rule)
|
||||
(funcall add-log-time-format))
|
||||
(setenv "TZ" tz)))
|
||||
(funcall add-log-time-format))
|
||||
(funcall add-log-time-format
|
||||
nil add-log-time-zone-rule)
|
||||
" " full-name
|
||||
" <" addr ">"))
|
||||
(if (consp mailing-address)
|
||||
|
|
|
@ -872,7 +872,8 @@ Return non-nil if it is."
|
|||
(and (boundp 'user-mail-address) user-mail-address)))
|
||||
(time (or (and (boundp 'add-log-time-format)
|
||||
(functionp add-log-time-format)
|
||||
(funcall add-log-time-format))
|
||||
(funcall add-log-time-format
|
||||
nil add-log-time-zone-rule))
|
||||
(format-time-string "%Y-%m-%d"))))
|
||||
(if (null log-edit-changelog-use-first)
|
||||
(looking-at (regexp-quote (format "%s %s <%s>" time name mail)))
|
||||
|
|
|
@ -98,6 +98,7 @@ AC_DEFUN([gl_EARLY],
|
|||
# Code from module memrchr:
|
||||
# Code from module mkostemp:
|
||||
# Code from module mktime:
|
||||
# Code from module mktime-internal:
|
||||
# Code from module multiarch:
|
||||
# Code from module nocrash:
|
||||
# Code from module openat-h:
|
||||
|
@ -141,13 +142,14 @@ AC_DEFUN([gl_EARLY],
|
|||
# Code from module tempname:
|
||||
# Code from module time:
|
||||
# Code from module time_r:
|
||||
# Code from module time_rz:
|
||||
# Code from module timegm:
|
||||
# Code from module timer-time:
|
||||
# Code from module timespec:
|
||||
# Code from module timespec-add:
|
||||
# Code from module timespec-sub:
|
||||
# Code from module u64:
|
||||
# Code from module unistd:
|
||||
# Code from module unsetenv:
|
||||
# Code from module update-copyright:
|
||||
# Code from module utimens:
|
||||
# Code from module vararrays:
|
||||
|
@ -385,15 +387,20 @@ AC_DEFUN([gl_INIT],
|
|||
gl_PREREQ_TIME_R
|
||||
fi
|
||||
gl_TIME_MODULE_INDICATOR([time_r])
|
||||
gl_TIME_RZ
|
||||
if test "$HAVE_TIMEZONE_T" = 0; then
|
||||
AC_LIBOBJ([time_rz])
|
||||
fi
|
||||
gl_TIME_MODULE_INDICATOR([time_rz])
|
||||
gl_FUNC_TIMEGM
|
||||
if test $HAVE_TIMEGM = 0 || test $REPLACE_TIMEGM = 1; then
|
||||
AC_LIBOBJ([timegm])
|
||||
gl_PREREQ_TIMEGM
|
||||
fi
|
||||
gl_TIME_MODULE_INDICATOR([timegm])
|
||||
gl_TIMER_TIME
|
||||
gl_TIMESPEC
|
||||
gl_UNISTD_H
|
||||
gl_FUNC_UNSETENV
|
||||
if test $HAVE_UNSETENV = 0 || test $REPLACE_UNSETENV = 1; then
|
||||
AC_LIBOBJ([unsetenv])
|
||||
gl_PREREQ_UNSETENV
|
||||
fi
|
||||
gl_STDLIB_MODULE_INDICATOR([unsetenv])
|
||||
gl_UTIMENS
|
||||
AC_C_VARARRAYS
|
||||
gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b=false
|
||||
|
@ -404,6 +411,7 @@ AC_DEFUN([gl_INIT],
|
|||
gl_gnulib_enabled_getgroups=false
|
||||
gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false
|
||||
gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=false
|
||||
gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31=false
|
||||
gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7=false
|
||||
gl_gnulib_enabled_pathmax=false
|
||||
gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c=false
|
||||
|
@ -506,6 +514,17 @@ AC_DEFUN([gl_INIT],
|
|||
fi
|
||||
fi
|
||||
}
|
||||
func_gl_gnulib_m4code_5264294aa0a5557541b53c8c741f7f31 ()
|
||||
{
|
||||
if ! $gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31; then
|
||||
gl_FUNC_MKTIME_INTERNAL
|
||||
if test $REPLACE_MKTIME = 1; then
|
||||
AC_LIBOBJ([mktime])
|
||||
gl_PREREQ_MKTIME
|
||||
fi
|
||||
gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31=true
|
||||
fi
|
||||
}
|
||||
func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7 ()
|
||||
{
|
||||
if ! $gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7; then
|
||||
|
@ -653,6 +672,9 @@ AC_DEFUN([gl_INIT],
|
|||
if { test $HAVE_DECL_STRTOUMAX = 0 || test $REPLACE_STRTOUMAX = 1; } && test $ac_cv_type_unsigned_long_long_int = yes; then
|
||||
func_gl_gnulib_m4code_strtoull
|
||||
fi
|
||||
if test $HAVE_TIMEGM = 0 || test $REPLACE_TIMEGM = 1; then
|
||||
func_gl_gnulib_m4code_5264294aa0a5557541b53c8c741f7f31
|
||||
fi
|
||||
m4_pattern_allow([^gl_GNULIB_ENABLED_])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_260941c0e5dc67ec9e87d1fb321c300b], [$gl_gnulib_enabled_260941c0e5dc67ec9e87d1fb321c300b])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_dirfd], [$gl_gnulib_enabled_dirfd])
|
||||
|
@ -662,6 +684,7 @@ AC_DEFUN([gl_INIT],
|
|||
AM_CONDITIONAL([gl_GNULIB_ENABLED_getgroups], [$gl_gnulib_enabled_getgroups])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], [$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1], [$gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31], [$gl_gnulib_enabled_5264294aa0a5557541b53c8c741f7f31])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7], [$gl_gnulib_enabled_03e0aaad4cb89ca757653bd367a6ccb7])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_pathmax], [$gl_gnulib_enabled_pathmax])
|
||||
AM_CONDITIONAL([gl_GNULIB_ENABLED_6099e9737f757db36c47fa9d9f02e88c], [$gl_gnulib_enabled_6099e9737f757db36c47fa9d9f02e88c])
|
||||
|
@ -938,6 +961,8 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
lib/tempname.h
|
||||
lib/time.in.h
|
||||
lib/time_r.c
|
||||
lib/time_rz.c
|
||||
lib/timegm.c
|
||||
lib/timespec-add.c
|
||||
lib/timespec-sub.c
|
||||
lib/timespec.c
|
||||
|
@ -946,7 +971,6 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
lib/u64.h
|
||||
lib/unistd.c
|
||||
lib/unistd.in.h
|
||||
lib/unsetenv.c
|
||||
lib/utimens.c
|
||||
lib/utimens.h
|
||||
lib/verify.h
|
||||
|
@ -1011,7 +1035,6 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
m4/readlink.m4
|
||||
m4/readlinkat.m4
|
||||
m4/secure_getenv.m4
|
||||
m4/setenv.m4
|
||||
m4/sha1.m4
|
||||
m4/sha256.m4
|
||||
m4/sha512.m4
|
||||
|
@ -1043,6 +1066,8 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
m4/tempname.m4
|
||||
m4/time_h.m4
|
||||
m4/time_r.m4
|
||||
m4/time_rz.m4
|
||||
m4/timegm.m4
|
||||
m4/timer_time.m4
|
||||
m4/timespec.m4
|
||||
m4/tm_gmtoff.m4
|
||||
|
|
|
@ -105,6 +105,7 @@ AC_DEFUN([gl_HEADER_SYS_TIME_H_DEFAULTS],
|
|||
HAVE_GETTIMEOFDAY=1; AC_SUBST([HAVE_GETTIMEOFDAY])
|
||||
HAVE_STRUCT_TIMEVAL=1; AC_SUBST([HAVE_STRUCT_TIMEVAL])
|
||||
HAVE_SYS_TIME_H=1; AC_SUBST([HAVE_SYS_TIME_H])
|
||||
HAVE_TIMEZONE_T=0; AC_SUBST([HAVE_TIMEZONE_T])
|
||||
REPLACE_GETTIMEOFDAY=0; AC_SUBST([REPLACE_GETTIMEOFDAY])
|
||||
REPLACE_STRUCT_TIMEVAL=0; AC_SUBST([REPLACE_STRUCT_TIMEVAL])
|
||||
])
|
||||
|
|
|
@ -109,6 +109,7 @@ AC_DEFUN([gl_HEADER_TIME_H_DEFAULTS],
|
|||
GNULIB_STRPTIME=0; AC_SUBST([GNULIB_STRPTIME])
|
||||
GNULIB_TIMEGM=0; AC_SUBST([GNULIB_TIMEGM])
|
||||
GNULIB_TIME_R=0; AC_SUBST([GNULIB_TIME_R])
|
||||
GNULIB_TIME_RZ=0; AC_SUBST([GNULIB_TIME_RZ])
|
||||
dnl Assume proper GNU behavior unless another module says otherwise.
|
||||
HAVE_DECL_LOCALTIME_R=1; AC_SUBST([HAVE_DECL_LOCALTIME_R])
|
||||
HAVE_NANOSLEEP=1; AC_SUBST([HAVE_NANOSLEEP])
|
||||
|
|
21
m4/time_rz.m4
Normal file
21
m4/time_rz.m4
Normal file
|
@ -0,0 +1,21 @@
|
|||
dnl Time zone functions: tzalloc, localtime_rz, etc.
|
||||
|
||||
dnl Copyright (C) 2015 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl Written by Paul Eggert.
|
||||
|
||||
AC_DEFUN([gl_TIME_RZ],
|
||||
[
|
||||
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
|
||||
AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
|
||||
AC_REQUIRE([AC_STRUCT_TIMEZONE])
|
||||
AC_CHECK_FUNCS_ONCE([tzset])
|
||||
|
||||
AC_CHECK_TYPES([timezone_t], [], [], [[#include <time.h>]])
|
||||
if test "$ac_cv_type_timezone_t" = yes; then
|
||||
HAVE_TIMEZONE_T=1
|
||||
fi
|
||||
])
|
26
m4/timegm.m4
Normal file
26
m4/timegm.m4
Normal file
|
@ -0,0 +1,26 @@
|
|||
# timegm.m4 serial 11
|
||||
dnl Copyright (C) 2003, 2007, 2009-2015 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
AC_DEFUN([gl_FUNC_TIMEGM],
|
||||
[
|
||||
AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
|
||||
AC_REQUIRE([gl_FUNC_MKTIME])
|
||||
REPLACE_TIMEGM=0
|
||||
AC_CHECK_FUNCS_ONCE([timegm])
|
||||
if test $ac_cv_func_timegm = yes; then
|
||||
if test $gl_cv_func_working_mktime = no; then
|
||||
# Assume that timegm is buggy if mktime is.
|
||||
REPLACE_TIMEGM=1
|
||||
fi
|
||||
else
|
||||
HAVE_TIMEGM=0
|
||||
fi
|
||||
])
|
||||
|
||||
# Prerequisites of lib/timegm.c.
|
||||
AC_DEFUN([gl_PREREQ_TIMEGM], [
|
||||
:
|
||||
])
|
88
nt/gnulib.mk
88
nt/gnulib.mk
|
@ -43,7 +43,7 @@
|
|||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --avoid=close --avoid=dup --avoid=fchdir --avoid=flexmember --avoid=fstat --avoid=malloc-posix --avoid=msvc-inval --avoid=msvc-nothrow --avoid=open --avoid=openat-die --avoid=opendir --avoid=raise --avoid=save-cwd --avoid=select --avoid=setenv --avoid=sigprocmask --avoid=stdarg --avoid=stdbool --avoid=threadlib --avoid=unsetenv --makefile-name=gnulib.mk --conditional-dependencies --no-libtool --macro-prefix=gl --no-vc-files alloca-opt binary-io byteswap c-ctype c-strcase careadlinkat close-stream count-one-bits count-trailing-zeros crypto/md5 crypto/sha1 crypto/sha256 crypto/sha512 dtoastr dtotimespec dup2 environ execinfo faccessat fcntl fcntl-h fdatasync fdopendir filemode fstatat fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog intprops largefile lstat manywarnings memrchr mkostemp mktime pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat sig2str socklen stat-time stdalign stddef stdio stpcpy strftime strtoimax strtoumax symlink sys_stat sys_time time time_r time_rz timegm timer-time timespec-add timespec-sub unsetenv update-copyright utimens vla warnings
|
||||
|
||||
|
||||
MOSTLYCLEANFILES += core *.stackdump
|
||||
|
@ -487,6 +487,17 @@ EXTRA_libgnu_a_SOURCES += mktime.c
|
|||
|
||||
## end gnulib module mktime
|
||||
|
||||
## begin gnulib module mktime-internal
|
||||
|
||||
if gl_GNULIB_ENABLED_5264294aa0a5557541b53c8c741f7f31
|
||||
|
||||
endif
|
||||
EXTRA_DIST += mktime-internal.h mktime.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += mktime.c
|
||||
|
||||
## end gnulib module mktime-internal
|
||||
|
||||
## begin gnulib module openat-h
|
||||
|
||||
if gl_GNULIB_ENABLED_03e0aaad4cb89ca757653bd367a6ccb7
|
||||
|
@ -944,6 +955,54 @@ EXTRA_libgnu_a_SOURCES += symlink.c
|
|||
|
||||
## end gnulib module symlink
|
||||
|
||||
## begin gnulib module time
|
||||
|
||||
BUILT_SOURCES += time.h
|
||||
|
||||
# We need the following in order to create <time.h> when the system
|
||||
# doesn't have one that works with the given compiler.
|
||||
time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
|
||||
$(AM_V_GEN)rm -f $@-t $@ && \
|
||||
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
|
||||
sed -e 's|@''GUARD_PREFIX''@|GL|g' \
|
||||
-e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
|
||||
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
|
||||
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
|
||||
-e 's|@''NEXT_TIME_H''@|$(NEXT_TIME_H)|g' \
|
||||
-e 's/@''GNULIB_GETTIMEOFDAY''@/$(GNULIB_GETTIMEOFDAY)/g' \
|
||||
-e 's/@''GNULIB_MKTIME''@/$(GNULIB_MKTIME)/g' \
|
||||
-e 's/@''GNULIB_NANOSLEEP''@/$(GNULIB_NANOSLEEP)/g' \
|
||||
-e 's/@''GNULIB_STRPTIME''@/$(GNULIB_STRPTIME)/g' \
|
||||
-e 's/@''GNULIB_TIMEGM''@/$(GNULIB_TIMEGM)/g' \
|
||||
-e 's/@''GNULIB_TIME_R''@/$(GNULIB_TIME_R)/g' \
|
||||
-e 's/@''GNULIB_TIME_RZ''@/$(GNULIB_TIME_RZ)/g' \
|
||||
-e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \
|
||||
-e 's|@''HAVE_NANOSLEEP''@|$(HAVE_NANOSLEEP)|g' \
|
||||
-e 's|@''HAVE_STRPTIME''@|$(HAVE_STRPTIME)|g' \
|
||||
-e 's|@''HAVE_TIMEGM''@|$(HAVE_TIMEGM)|g' \
|
||||
-e 's|@''HAVE_TIMEZONE_T''@|$(HAVE_TIMEZONE_T)|g' \
|
||||
-e 's|@''REPLACE_GMTIME''@|$(REPLACE_GMTIME)|g' \
|
||||
-e 's|@''REPLACE_LOCALTIME''@|$(REPLACE_LOCALTIME)|g' \
|
||||
-e 's|@''REPLACE_LOCALTIME_R''@|$(REPLACE_LOCALTIME_R)|g' \
|
||||
-e 's|@''REPLACE_MKTIME''@|$(REPLACE_MKTIME)|g' \
|
||||
-e 's|@''REPLACE_NANOSLEEP''@|$(REPLACE_NANOSLEEP)|g' \
|
||||
-e 's|@''REPLACE_TIMEGM''@|$(REPLACE_TIMEGM)|g' \
|
||||
-e 's|@''PTHREAD_H_DEFINES_STRUCT_TIMESPEC''@|$(PTHREAD_H_DEFINES_STRUCT_TIMESPEC)|g' \
|
||||
-e 's|@''SYS_TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(SYS_TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
|
||||
-e 's|@''TIME_H_DEFINES_STRUCT_TIMESPEC''@|$(TIME_H_DEFINES_STRUCT_TIMESPEC)|g' \
|
||||
-e 's|@''UNISTD_H_DEFINES_STRUCT_TIMESPEC''@|$(UNISTD_H_DEFINES_STRUCT_TIMESPEC)|g' \
|
||||
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
|
||||
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
|
||||
-e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
|
||||
< $(srcdir)/time.in.h; \
|
||||
} > $@-t && \
|
||||
mv $@-t $@
|
||||
MOSTLYCLEANFILES += time.h time.h-t
|
||||
|
||||
EXTRA_DIST += time.in.h
|
||||
|
||||
## end gnulib module time
|
||||
|
||||
## begin gnulib module time_r
|
||||
|
||||
|
||||
|
@ -953,6 +1012,24 @@ EXTRA_libgnu_a_SOURCES += time_r.c
|
|||
|
||||
## end gnulib module time_r
|
||||
|
||||
## begin gnulib module time_rz
|
||||
|
||||
|
||||
EXTRA_DIST += time_rz.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += time_rz.c
|
||||
|
||||
## end gnulib module time_rz
|
||||
|
||||
## begin gnulib module timegm
|
||||
|
||||
|
||||
EXTRA_DIST += mktime-internal.h timegm.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += timegm.c
|
||||
|
||||
## end gnulib module timegm
|
||||
|
||||
## begin gnulib module timespec
|
||||
|
||||
libgnu_a_SOURCES += timespec.c
|
||||
|
@ -981,15 +1058,6 @@ EXTRA_DIST += u64.h
|
|||
|
||||
## end gnulib module u64
|
||||
|
||||
## begin gnulib module unsetenv
|
||||
|
||||
|
||||
EXTRA_DIST += unsetenv.c
|
||||
|
||||
EXTRA_libgnu_a_SOURCES += unsetenv.c
|
||||
|
||||
## end gnulib module unsetenv
|
||||
|
||||
## begin gnulib module update-copyright
|
||||
|
||||
|
||||
|
|
|
@ -206,6 +206,13 @@ extern void _DebPrint (const char *fmt, ...);
|
|||
#define RE_TRANSLATE_P(TBL) (!EQ (TBL, make_number (0)))
|
||||
#endif
|
||||
|
||||
/* Tell time_rz.c to use Emacs's getter and setter for TZ.
|
||||
Only Emacs uses time_rz so this is OK. */
|
||||
#define getenv_TZ emacs_getenv_TZ
|
||||
#define setenv_TZ emacs_setenv_TZ
|
||||
extern char *emacs_getenv_TZ (void);
|
||||
extern int emacs_setenv_TZ (char const *);
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
|
324
src/editfns.c
324
src/editfns.c
|
@ -44,8 +44,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <intprops.h>
|
||||
#include <strftime.h>
|
||||
#include <verify.h>
|
||||
|
@ -65,9 +67,8 @@ extern Lisp_Object w32_get_internal_run_time (void);
|
|||
#endif
|
||||
|
||||
static struct lisp_time lisp_time_struct (Lisp_Object, int *);
|
||||
static void set_time_zone_rule (char const *);
|
||||
static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec,
|
||||
bool, struct tm *);
|
||||
Lisp_Object, struct tm *);
|
||||
static long int tm_gmtoff (struct tm *);
|
||||
static int tm_diff (struct tm *, struct tm *);
|
||||
static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
|
||||
|
@ -76,8 +77,13 @@ static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
|
|||
# define HAVE_TM_GMTOFF false
|
||||
#endif
|
||||
|
||||
/* The startup value of the TZ environment variable; null if unset. */
|
||||
static char const *initial_tz;
|
||||
enum { tzeqlen = sizeof "TZ=" - 1 };
|
||||
|
||||
/* Time zones equivalent to current local time, to wall clock time,
|
||||
and to UTC, respectively. */
|
||||
static timezone_t local_tz;
|
||||
static timezone_t wall_clock_tz;
|
||||
static timezone_t const utc_tz = 0;
|
||||
|
||||
/* A valid but unlikely setting for the TZ environment variable.
|
||||
It is OK (though a bit slower) if the user chooses this value. */
|
||||
|
@ -94,8 +100,97 @@ init_and_cache_system_name (void)
|
|||
cached_system_name = Vsystem_name;
|
||||
}
|
||||
|
||||
static struct tm *
|
||||
emacs_localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
|
||||
{
|
||||
tm = localtime_rz (tz, t, tm);
|
||||
if (!tm && errno == ENOMEM)
|
||||
memory_full (SIZE_MAX);
|
||||
return tm;
|
||||
}
|
||||
|
||||
static time_t
|
||||
emacs_mktime_z (timezone_t tz, struct tm *tm)
|
||||
{
|
||||
errno = 0;
|
||||
time_t t = mktime_z (tz, tm);
|
||||
if (t == (time_t) -1 && errno == ENOMEM)
|
||||
memory_full (SIZE_MAX);
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Allocate a timezone, signaling on failure. */
|
||||
static timezone_t
|
||||
xtzalloc (char const *name)
|
||||
{
|
||||
timezone_t tz = tzalloc (name);
|
||||
if (!tz)
|
||||
memory_full (SIZE_MAX);
|
||||
return tz;
|
||||
}
|
||||
|
||||
/* Free a timezone, except do not free the time zone for local time.
|
||||
Freeing utc_tz is also a no-op. */
|
||||
static void
|
||||
xtzfree (timezone_t tz)
|
||||
{
|
||||
if (tz != local_tz)
|
||||
tzfree (tz);
|
||||
}
|
||||
|
||||
/* Convert the Lisp time zone rule ZONE to a timezone_t object.
|
||||
The returned value either is 0, or is LOCAL_TZ, or is newly allocated.
|
||||
If SETTZ, set Emacs local time to the time zone rule; otherwise,
|
||||
the caller should eventually pass the returned value to xtzfree. */
|
||||
static timezone_t
|
||||
tzlookup (Lisp_Object zone, bool settz)
|
||||
{
|
||||
static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d";
|
||||
char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)];
|
||||
char const *zone_string;
|
||||
timezone_t new_tz;
|
||||
|
||||
if (NILP (zone))
|
||||
return local_tz;
|
||||
else if (EQ (zone, Qt))
|
||||
{
|
||||
zone_string = "UTC0";
|
||||
new_tz = utc_tz;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EQ (zone, Qwall))
|
||||
zone_string = 0;
|
||||
else if (STRINGP (zone))
|
||||
zone_string = SSDATA (zone);
|
||||
else if (INTEGERP (zone))
|
||||
{
|
||||
EMACS_INT abszone = eabs (XINT (zone)), hour = abszone / (60 * 60);
|
||||
int min = (abszone / 60) % 60, sec = abszone % 60;
|
||||
sprintf (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0], hour, min, sec);
|
||||
zone_string = tzbuf;
|
||||
}
|
||||
else
|
||||
xsignal2 (Qerror, build_string ("Invalid time zone specification"),
|
||||
zone);
|
||||
new_tz = xtzalloc (zone_string);
|
||||
}
|
||||
|
||||
if (settz)
|
||||
{
|
||||
block_input ();
|
||||
emacs_setenv_TZ (zone_string);
|
||||
timezone_t old_tz = local_tz;
|
||||
local_tz = new_tz;
|
||||
tzfree (old_tz);
|
||||
unblock_input ();
|
||||
}
|
||||
|
||||
return new_tz;
|
||||
}
|
||||
|
||||
void
|
||||
init_editfns (void)
|
||||
init_editfns (bool dumping)
|
||||
{
|
||||
const char *user_name;
|
||||
register char *p;
|
||||
|
@ -108,7 +203,7 @@ init_editfns (void)
|
|||
#ifndef CANNOT_DUMP
|
||||
/* When just dumping out, set the time zone to a known unlikely value
|
||||
and skip the rest of this function. */
|
||||
if (!initialized)
|
||||
if (dumping)
|
||||
{
|
||||
# ifdef HAVE_TZSET
|
||||
xputenv (dump_tz_string);
|
||||
|
@ -119,7 +214,6 @@ init_editfns (void)
|
|||
#endif
|
||||
|
||||
char *tz = getenv ("TZ");
|
||||
initial_tz = tz;
|
||||
|
||||
#if !defined CANNOT_DUMP && defined HAVE_TZSET
|
||||
/* If the execution TZ happens to be the same as the dump TZ,
|
||||
|
@ -127,7 +221,7 @@ init_editfns (void)
|
|||
to force the underlying implementation to reload the TZ info.
|
||||
This is needed on implementations that load TZ info from files,
|
||||
since the TZ file contents may differ between dump and execution. */
|
||||
if (tz && strcmp (tz, &dump_tz_string[sizeof "TZ=" - 1]) == 0)
|
||||
if (tz && strcmp (tz, &dump_tz_string[tzeqlen]) == 0)
|
||||
{
|
||||
++*tz;
|
||||
tzset ();
|
||||
|
@ -135,9 +229,10 @@ init_editfns (void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Call set_time_zone_rule now, so that its call to putenv is done
|
||||
/* Set the time zone rule now, so that the call to putenv is done
|
||||
before multiple threads are active. */
|
||||
set_time_zone_rule (tz);
|
||||
wall_clock_tz = xtzalloc (0);
|
||||
tzlookup (tz ? build_string (tz) : Qwall, true);
|
||||
|
||||
pw = getpwuid (getuid ());
|
||||
#ifdef MSDOS
|
||||
|
@ -1206,7 +1301,7 @@ of the user with that uid, or nil if there is no such user. */)
|
|||
(That can happen if Emacs is dumpable
|
||||
but you decide to run `temacs -l loadup' and not dump. */
|
||||
if (NILP (Vuser_login_name))
|
||||
init_editfns ();
|
||||
init_editfns (false);
|
||||
|
||||
if (NILP (uid))
|
||||
return Vuser_login_name;
|
||||
|
@ -1229,7 +1324,7 @@ This ignores the environment variables LOGNAME and USER, so it differs from
|
|||
(That can happen if Emacs is dumpable
|
||||
but you decide to run `temacs -l loadup' and not dump. */
|
||||
if (NILP (Vuser_login_name))
|
||||
init_editfns ();
|
||||
init_editfns (false);
|
||||
return Vuser_real_login_name;
|
||||
}
|
||||
|
||||
|
@ -1384,30 +1479,6 @@ check_time_validity (int validity)
|
|||
}
|
||||
}
|
||||
|
||||
/* A substitute for mktime_z on platforms that lack it. It's not
|
||||
thread-safe, but should be good enough for Emacs in typical use. */
|
||||
#ifndef HAVE_TZALLOC
|
||||
static time_t
|
||||
mktime_z (timezone_t tz, struct tm *tm)
|
||||
{
|
||||
char *oldtz = getenv ("TZ");
|
||||
USE_SAFE_ALLOCA;
|
||||
if (oldtz)
|
||||
{
|
||||
size_t oldtzsize = strlen (oldtz) + 1;
|
||||
char *oldtzcopy = SAFE_ALLOCA (oldtzsize);
|
||||
oldtz = strcpy (oldtzcopy, oldtz);
|
||||
}
|
||||
block_input ();
|
||||
set_time_zone_rule (tz);
|
||||
time_t t = mktime (tm);
|
||||
set_time_zone_rule (oldtz);
|
||||
unblock_input ();
|
||||
SAFE_FREE ();
|
||||
return t;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Return the upper part of the time T (everything but the bottom 16 bits). */
|
||||
static EMACS_INT
|
||||
hi_time (time_t t)
|
||||
|
@ -1848,7 +1919,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, local time otherwise.
|
||||
Use the time zone specified by TZ.
|
||||
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
|
||||
|
@ -1859,7 +1930,7 @@ or (if you need time as a string) `format-time-string'. */)
|
|||
bytes in FORMAT and it does not support nanoseconds. */
|
||||
static size_t
|
||||
emacs_nmemftime (char *s, size_t maxsize, const char *format,
|
||||
size_t format_len, const struct tm *tp, bool ut, int ns)
|
||||
size_t format_len, const struct tm *tp, timezone_t tz, int ns)
|
||||
{
|
||||
size_t total = 0;
|
||||
|
||||
|
@ -1876,7 +1947,7 @@ emacs_nmemftime (char *s, size_t maxsize, const char *format,
|
|||
if (s)
|
||||
s[0] = '\1';
|
||||
|
||||
result = nstrftime (s, maxsize, format, tp, ut, ns);
|
||||
result = nstrftime (s, maxsize, format, tp, tz, ns);
|
||||
|
||||
if (s)
|
||||
{
|
||||
|
@ -1901,8 +1972,9 @@ DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0,
|
|||
TIME is specified as (HIGH LOW USEC PSEC), as returned by
|
||||
`current-time' or `file-attributes'. The obsolete form (HIGH . LOW)
|
||||
is also still accepted.
|
||||
The third, optional, argument UNIVERSAL, if non-nil, means describe TIME
|
||||
as Universal Time; nil means describe TIME in the local time zone.
|
||||
The optional ZONE is omitted or nil for Emacs local time, t for
|
||||
Universal Time, `wall' for system wall clock time, or a string as in
|
||||
`set-time-zone-rule' for a time zone rule.
|
||||
The value is a copy of FORMAT-STRING, but with certain constructs replaced
|
||||
by text that describes the specified date and time in TIME:
|
||||
|
||||
|
@ -1951,8 +2023,8 @@ The modifiers are `E' and `O'. For certain characters X,
|
|||
|
||||
For example, to produce full ISO 8601 format, use "%FT%T%z".
|
||||
|
||||
usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
|
||||
(Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
|
||||
usage: (format-time-string FORMAT-STRING &optional TIME ZONE) */)
|
||||
(Lisp_Object format_string, Lisp_Object timeval, Lisp_Object zone)
|
||||
{
|
||||
struct timespec t = lisp_time_argument (timeval);
|
||||
struct tm tm;
|
||||
|
@ -1961,12 +2033,12 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
|
|||
format_string = code_convert_string_norecord (format_string,
|
||||
Vlocale_coding_system, 1);
|
||||
return format_time_string (SSDATA (format_string), SBYTES (format_string),
|
||||
t, ! NILP (universal), &tm);
|
||||
t, zone, &tm);
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
format_time_string (char const *format, ptrdiff_t formatlen,
|
||||
struct timespec t, bool ut, struct tm *tmp)
|
||||
struct timespec t, Lisp_Object zone, struct tm *tmp)
|
||||
{
|
||||
char buffer[4000];
|
||||
char *buf = buffer;
|
||||
|
@ -1976,36 +2048,48 @@ format_time_string (char const *format, ptrdiff_t formatlen,
|
|||
int ns = t.tv_nsec;
|
||||
USE_SAFE_ALLOCA;
|
||||
|
||||
tmp = ut ? gmtime_r (&t.tv_sec, tmp) : localtime_r (&t.tv_sec, tmp);
|
||||
timezone_t tz = tzlookup (zone, false);
|
||||
tmp = emacs_localtime_rz (tz, &t.tv_sec, tmp);
|
||||
if (! tmp)
|
||||
time_overflow ();
|
||||
{
|
||||
xtzfree (tz);
|
||||
time_overflow ();
|
||||
}
|
||||
synchronize_system_time_locale ();
|
||||
|
||||
while (true)
|
||||
{
|
||||
buf[0] = '\1';
|
||||
len = emacs_nmemftime (buf, size, format, formatlen, tmp, ut, ns);
|
||||
len = emacs_nmemftime (buf, size, format, formatlen, tmp, tz, ns);
|
||||
if ((0 < len && len < size) || (len == 0 && buf[0] == '\0'))
|
||||
break;
|
||||
|
||||
/* Buffer was too small, so make it bigger and try again. */
|
||||
len = emacs_nmemftime (NULL, SIZE_MAX, format, formatlen, tmp, ut, ns);
|
||||
len = emacs_nmemftime (NULL, SIZE_MAX, format, formatlen, tmp, tz, ns);
|
||||
if (STRING_BYTES_BOUND <= len)
|
||||
string_overflow ();
|
||||
{
|
||||
xtzfree (tz);
|
||||
string_overflow ();
|
||||
}
|
||||
size = len + 1;
|
||||
buf = SAFE_ALLOCA (size);
|
||||
}
|
||||
|
||||
xtzfree (tz);
|
||||
bufstring = make_unibyte_string (buf, len);
|
||||
SAFE_FREE ();
|
||||
return code_convert_string_norecord (bufstring, Vlocale_coding_system, 0);
|
||||
}
|
||||
|
||||
DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 1, 0,
|
||||
doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST ZONE).
|
||||
DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0,
|
||||
doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF).
|
||||
The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED),
|
||||
as from `current-time' and `file-attributes', or nil to use the
|
||||
current time. The obsolete form (HIGH . LOW) is also still accepted.
|
||||
The optional ZONE is omitted or nil for Emacs local time, t for
|
||||
Universal Time, `wall' for system wall clock time, or a string as in
|
||||
`set-time-zone-rule' for a time zone rule.
|
||||
|
||||
The list has the following nine members: SEC is an integer between 0
|
||||
and 60; SEC is 60 for a leap second, which only some operating systems
|
||||
support. MINUTE is an integer between 0 and 59. HOUR is an integer
|
||||
|
@ -2013,15 +2097,20 @@ between 0 and 23. DAY is an integer between 1 and 31. MONTH is an
|
|||
integer between 1 and 12. YEAR is an integer indicating the
|
||||
four-digit year. DOW is the day of week, an integer between 0 and 6,
|
||||
where 0 is Sunday. DST is t if daylight saving time is in effect,
|
||||
otherwise nil. ZONE is an integer indicating the number of seconds
|
||||
east of Greenwich. (Note that Common Lisp has different meanings for
|
||||
DOW and ZONE.) */)
|
||||
(Lisp_Object specified_time)
|
||||
otherwise nil. UTCOFF is an integer indicating the UTC offset in
|
||||
seconds, i.e., the number of seconds east of Greenwich. (Note that
|
||||
Common Lisp has different meanings for DOW and UTCOFF.)
|
||||
|
||||
usage: (decode-time &optional TIME ZONE) */)
|
||||
(Lisp_Object specified_time, Lisp_Object zone)
|
||||
{
|
||||
time_t time_spec = lisp_seconds_argument (specified_time);
|
||||
struct tm local_tm, gmt_tm;
|
||||
timezone_t tz = tzlookup (zone, false);
|
||||
struct tm *tm = emacs_localtime_rz (tz, &time_spec, &local_tm);
|
||||
xtzfree (tz);
|
||||
|
||||
if (! (localtime_r (&time_spec, &local_tm)
|
||||
if (! (tm
|
||||
&& MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year
|
||||
&& local_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE))
|
||||
time_overflow ();
|
||||
|
@ -2059,35 +2148,13 @@ check_tm_member (Lisp_Object obj, int offset)
|
|||
return n - offset;
|
||||
}
|
||||
|
||||
/* Decode ZONE as a time zone specification. */
|
||||
|
||||
static Lisp_Object
|
||||
decode_time_zone (Lisp_Object zone)
|
||||
{
|
||||
if (EQ (zone, Qt))
|
||||
return build_string ("UTC0");
|
||||
else if (STRINGP (zone))
|
||||
return zone;
|
||||
else if (INTEGERP (zone))
|
||||
{
|
||||
static char const tzbuf_format[] = "XXX%s%"pI"d:%02d:%02d";
|
||||
char tzbuf[sizeof tzbuf_format + INT_STRLEN_BOUND (EMACS_INT)];
|
||||
EMACS_INT abszone = eabs (XINT (zone)), zone_hr = abszone / (60 * 60);
|
||||
int zone_min = (abszone / 60) % 60, zone_sec = abszone % 60;
|
||||
|
||||
return make_formatted_string (tzbuf, tzbuf_format, &"-"[XINT (zone) < 0],
|
||||
zone_hr, zone_min, zone_sec);
|
||||
}
|
||||
else
|
||||
xsignal2 (Qerror, build_string ("Invalid time zone specification"), zone);
|
||||
}
|
||||
|
||||
DEFUN ("encode-time", Fencode_time, Sencode_time, 6, MANY, 0,
|
||||
doc: /* Convert SECOND, MINUTE, HOUR, DAY, MONTH, YEAR and ZONE to internal time.
|
||||
This is the reverse operation of `decode-time', which see.
|
||||
ZONE defaults to the current time zone rule. This can
|
||||
be a string or t (as from `set-time-zone-rule'), or it can be a list
|
||||
\(as from `current-time-zone') or an integer (as from `decode-time')
|
||||
The optional ZONE is omitted or nil for Emacs local time, t for
|
||||
Universal Time, `wall' for system wall clock time, or a string as in
|
||||
`set-time-zone-rule' for a time zone rule. It can also be a list (as
|
||||
from `current-time-zone') or an integer (as from `decode-time')
|
||||
applied without consideration for daylight saving time.
|
||||
|
||||
You can pass more than 7 arguments; then the first six arguments
|
||||
|
@ -2120,14 +2187,9 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
|
|||
|
||||
if (CONSP (zone))
|
||||
zone = XCAR (zone);
|
||||
if (NILP (zone))
|
||||
value = mktime (&tm);
|
||||
else
|
||||
{
|
||||
timezone_t tz = tzalloc (SSDATA (decode_time_zone (zone)));
|
||||
value = mktime_z (tz, &tm);
|
||||
tzfree (tz);
|
||||
}
|
||||
timezone_t tz = tzlookup (zone, false);
|
||||
value = emacs_mktime_z (tz, &tm);
|
||||
xtzfree (tz);
|
||||
|
||||
if (value == (time_t) -1)
|
||||
time_overflow ();
|
||||
|
@ -2135,7 +2197,8 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
|
|||
return list2i (hi_time (value), lo_time (value));
|
||||
}
|
||||
|
||||
DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
|
||||
DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string,
|
||||
0, 2, 0,
|
||||
doc: /* Return the current local time, as a human-readable string.
|
||||
Programs can use this function to decode a time,
|
||||
since the number of columns in each field is fixed
|
||||
|
@ -2148,17 +2211,24 @@ If SPECIFIED-TIME is given, it is a time to format instead of the
|
|||
current time. The argument should have the form (HIGH LOW . IGNORED).
|
||||
Thus, you can use times obtained from `current-time' and from
|
||||
`file-attributes'. SPECIFIED-TIME can also have the form (HIGH . LOW),
|
||||
but this is considered obsolete. */)
|
||||
(Lisp_Object specified_time)
|
||||
but this is considered obsolete.
|
||||
|
||||
The optional ZONE is omitted or nil for Emacs local time, t for
|
||||
Universal Time, `wall' for system wall clock time, or a string as in
|
||||
`set-time-zone-rule' for a time zone rule. */)
|
||||
(Lisp_Object specified_time, Lisp_Object zone)
|
||||
{
|
||||
time_t value = lisp_seconds_argument (specified_time);
|
||||
timezone_t tz = tzlookup (zone, false);
|
||||
|
||||
/* Convert to a string in ctime format, except without the trailing
|
||||
newline, and without the 4-digit year limit. Don't use asctime
|
||||
or ctime, as they might dump core if the year is outside the
|
||||
range -999 .. 9999. */
|
||||
struct tm tm;
|
||||
if (! localtime_r (&value, &tm))
|
||||
struct tm *tmp = emacs_localtime_rz (tz, &value, &tm);
|
||||
xtzfree (tz);
|
||||
if (! tmp)
|
||||
time_overflow ();
|
||||
|
||||
static char const wday_name[][4] =
|
||||
|
@ -2210,7 +2280,7 @@ tm_gmtoff (struct tm *a)
|
|||
#endif
|
||||
}
|
||||
|
||||
DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0,
|
||||
DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 2, 0,
|
||||
doc: /* Return the offset and name for the local time zone.
|
||||
This returns a list of the form (OFFSET NAME).
|
||||
OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).
|
||||
|
@ -2221,11 +2291,13 @@ instead of using the current time. The argument should have the form
|
|||
(HIGH LOW . IGNORED). Thus, you can use times obtained from
|
||||
`current-time' and from `file-attributes'. SPECIFIED-TIME can also
|
||||
have the form (HIGH . LOW), but this is considered obsolete.
|
||||
Optional second arg ZONE is omitted or nil for the local time zone, or
|
||||
a string as in `set-time-zone-rule'.
|
||||
|
||||
Some operating systems cannot provide all this information to Emacs;
|
||||
in this case, `current-time-zone' returns a list containing nil for
|
||||
the data it can't find. */)
|
||||
(Lisp_Object specified_time)
|
||||
(Lisp_Object specified_time, Lisp_Object zone)
|
||||
{
|
||||
struct timespec value;
|
||||
struct tm local_tm, gmt_tm;
|
||||
|
@ -2233,7 +2305,8 @@ the data it can't find. */)
|
|||
|
||||
zone_offset = Qnil;
|
||||
value = make_timespec (lisp_seconds_argument (specified_time), 0);
|
||||
zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value, 0, &local_tm);
|
||||
zone_name = format_time_string ("%Z", sizeof "%Z" - 1, value,
|
||||
zone, &local_tm);
|
||||
|
||||
if (HAVE_TM_GMTOFF || gmtime_r (&value.tv_sec, &gmt_tm))
|
||||
{
|
||||
|
@ -2259,42 +2332,48 @@ the data it can't find. */)
|
|||
}
|
||||
|
||||
DEFUN ("set-time-zone-rule", Fset_time_zone_rule, Sset_time_zone_rule, 1, 1, 0,
|
||||
doc: /* Set the local time zone using TZ, a string specifying a time zone rule.
|
||||
If TZ is nil, use implementation-defined default time zone information.
|
||||
If TZ is t, use Universal Time. If TZ is an integer, it is treated as in
|
||||
`encode-time'.
|
||||
doc: /* Set the Emacs local time zone using TZ, a string specifying a time zone rule.
|
||||
If TZ is nil or `wall', use system wall clock time. If TZ is t, use
|
||||
Universal Time. If TZ is an integer, treat it as in `encode-time'.
|
||||
|
||||
Instead of calling this function, you typically want (setenv "TZ" TZ).
|
||||
That changes both the environment of the Emacs process and the
|
||||
variable `process-environment', whereas `set-time-zone-rule' affects
|
||||
only the former. */)
|
||||
Instead of calling this function, you typically want something else.
|
||||
To temporarily use a different time zone rule for just one invocation
|
||||
of `decode-time', `encode-time', or `format-time-string', pass the
|
||||
function a ZONE argument. To change local time consistently
|
||||
throughout Emacs, call (setenv "TZ" TZ): this changes both the
|
||||
environment of the Emacs process and the variable
|
||||
`process-environment', whereas `set-time-zone-rule' affects only the
|
||||
former. */)
|
||||
(Lisp_Object tz)
|
||||
{
|
||||
const char *tzstring = NILP (tz) ? initial_tz : SSDATA (decode_time_zone (tz));
|
||||
|
||||
block_input ();
|
||||
set_time_zone_rule (tzstring);
|
||||
unblock_input ();
|
||||
|
||||
tzlookup (NILP (tz) ? Qwall : tz, true);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
/* Set the local time zone rule to TZSTRING.
|
||||
/* A buffer holding a string of the form "TZ=value", intended
|
||||
to be part of the environment. If TZ is supposed to be unset,
|
||||
the buffer string is "tZ=". */
|
||||
static char *tzvalbuf;
|
||||
|
||||
/* Get the local time zone rule. */
|
||||
char *
|
||||
emacs_getenv_TZ (void)
|
||||
{
|
||||
return tzvalbuf[0] == 'T' ? tzvalbuf + tzeqlen : 0;
|
||||
}
|
||||
|
||||
/* Set the local time zone rule to TZSTRING, which can be null to
|
||||
denote wall clock time. Do not record the setting in LOCAL_TZ.
|
||||
|
||||
This function is not thread-safe, in theory because putenv is not,
|
||||
but mostly because of the static storage it updates. Other threads
|
||||
that invoke localtime etc. may be adversely affected while this
|
||||
function is executing. */
|
||||
|
||||
static void
|
||||
set_time_zone_rule (const char *tzstring)
|
||||
int
|
||||
emacs_setenv_TZ (const char *tzstring)
|
||||
{
|
||||
/* A buffer holding a string of the form "TZ=value", intended
|
||||
to be part of the environment. */
|
||||
static char *tzvalbuf;
|
||||
static ptrdiff_t tzvalbufsize;
|
||||
|
||||
int tzeqlen = sizeof "TZ=" - 1;
|
||||
ptrdiff_t tzstringlen = tzstring ? strlen (tzstring) : 0;
|
||||
char *tzval = tzvalbuf;
|
||||
bool new_tzvalbuf = tzvalbufsize <= tzeqlen + tzstringlen;
|
||||
|
@ -2346,9 +2425,7 @@ set_time_zone_rule (const char *tzstring)
|
|||
xputenv (tzval);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TZSET
|
||||
tzset ();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert NARGS Lisp objects in the array ARGS by calling INSERT_FUNC
|
||||
|
@ -4943,6 +5020,7 @@ void
|
|||
syms_of_editfns (void)
|
||||
{
|
||||
DEFSYM (Qbuffer_access_fontify_functions, "buffer-access-fontify-functions");
|
||||
DEFSYM (Qwall, "wall");
|
||||
|
||||
DEFVAR_LISP ("inhibit-field-text-motion", Vinhibit_field_text_motion,
|
||||
doc: /* Non-nil means text motion commands don't notice fields. */);
|
||||
|
|
|
@ -1552,7 +1552,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
|||
|
||||
/* This calls putenv and so must precede init_process_emacs. Also,
|
||||
it sets Voperating_system_release, which init_process_emacs uses. */
|
||||
init_editfns ();
|
||||
init_editfns (dumping);
|
||||
|
||||
/* These two call putenv. */
|
||||
#ifdef HAVE_DBUS
|
||||
|
|
|
@ -4055,7 +4055,7 @@ extern _Noreturn void time_overflow (void);
|
|||
extern Lisp_Object make_buffer_string (ptrdiff_t, ptrdiff_t, bool);
|
||||
extern Lisp_Object make_buffer_string_both (ptrdiff_t, ptrdiff_t, ptrdiff_t,
|
||||
ptrdiff_t, bool);
|
||||
extern void init_editfns (void);
|
||||
extern void init_editfns (bool);
|
||||
extern void syms_of_editfns (void);
|
||||
|
||||
/* Defined in buffer.c. */
|
||||
|
|
|
@ -106,20 +106,6 @@ extern struct timespec lisp_to_timespec (struct lisp_time);
|
|||
extern struct timespec lisp_time_argument (Lisp_Object);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_TZALLOC
|
||||
# undef mktime_z
|
||||
# undef timezone_t
|
||||
# undef tzalloc
|
||||
# undef tzfree
|
||||
# define mktime_z emacs_mktime_z
|
||||
# define timezone_t emacs_timezone_t
|
||||
# define tzalloc emacs_tzalloc
|
||||
# define tzfree emacs_tzfree
|
||||
typedef char const *timezone_t;
|
||||
INLINE timezone_t tzalloc (char const *name) { return name; }
|
||||
INLINE void tzfree (timezone_t tz) { }
|
||||
#endif
|
||||
|
||||
INLINE_HEADER_END
|
||||
|
||||
#endif /* EMACS_SYSTIME_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue