diff options
-rw-r--r-- | src/nvim/os/time.c | 22 | ||||
-rw-r--r-- | src/nvim/testdir/test_functions.vim | 23 |
2 files changed, 41 insertions, 4 deletions
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index fc04cdd55b..346e40e02e 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -2,9 +2,6 @@ // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com #include <assert.h> -#include <stdint.h> -#include <stdbool.h> -#include <time.h> #include <limits.h> #include <uv.h> @@ -13,7 +10,7 @@ #include "nvim/os/time.h" #include "nvim/os/input.h" #include "nvim/event/loop.h" -#include "nvim/vim.h" +#include "nvim/os/os.h" #include "nvim/main.h" static uv_mutex_t delay_mutex; @@ -112,6 +109,10 @@ void os_microdelay(uint64_t us, bool ignoreinput) uv_mutex_unlock(&delay_mutex); } +// Cache of the current timezone name as retrieved from TZ, or an empty string +// where unset, up to 64 octets long including trailing null byte. +static char tz_cache[64]; + /// Portable version of POSIX localtime_r() /// /// @return NULL in case of error @@ -120,6 +121,19 @@ struct tm *os_localtime_r(const time_t *restrict clock, { #ifdef UNIX // POSIX provides localtime_r() as a thread-safe version of localtime(). + // + // Check to see if the environment variable TZ has changed since the last run. + // Call tzset(3) to update the global timezone variables if it has. + // POSIX standard doesn't require localtime_r() implementations to do that + // as it does with localtime(), and we don't want to call tzset() every time. + const char *tz = os_getenv("TZ"); + if (tz == NULL) { + tz = ""; + } + if (strncmp(tz_cache, tz, sizeof(tz_cache) - 1) != 0) { + tzset(); + xstrlcpy(tz_cache, tz, sizeof(tz_cache)); + } return localtime_r(clock, result); // NOLINT(runtime/threadsafe_fn) #else // Windows version of localtime() is thread-safe. diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 7822507f86..da5edbaea1 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -186,6 +186,29 @@ func Test_strftime() call assert_fails('call strftime([])', 'E730:') call assert_fails('call strftime("%Y", [])', 'E745:') + + " Check that the time changes after we change the timezone + " Save previous timezone value, if any + if exists('$TZ') + let tz = $TZ + endif + + " Force EST and then UTC, save the current hour (24-hour clock) for each + let $TZ = 'EST' | let est = strftime('%H') + let $TZ = 'UTC' | let utc = strftime('%H') + + " Those hours should be two bytes long, and should not be the same; if they + " are, a tzset(3) call may have failed somewhere + call assert_equal(strlen(est), 2) + call assert_equal(strlen(utc), 2) + call assert_notequal(est, utc) + + " If we cached a timezone value, put it back, otherwise clear it + if exists('tz') + let $TZ = tz + else + unlet $TZ + endif endfunc func Test_resolve() |