aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_time_sup.c
diff options
context:
space:
mode:
authorPatrik Nyblom <[email protected]>2010-06-10 15:53:19 +0200
committerPatrik Nyblom <[email protected]>2010-06-23 14:54:43 +0200
commit7e6fe78278c203c3756ce0d6bf23a6bd6cf7bb5d (patch)
treea58173e9f6773e43a6a41c1db5d5ed69077ba9b4 /erts/emulator/beam/erl_time_sup.c
parentc1e94fa9a6fe4ae717d35dfbd1b628dc2e06d26a (diff)
downloadotp-7e6fe78278c203c3756ce0d6bf23a6bd6cf7bb5d.tar.gz
otp-7e6fe78278c203c3756ce0d6bf23a6bd6cf7bb5d.tar.bz2
otp-7e6fe78278c203c3756ce0d6bf23a6bd6cf7bb5d.zip
Teach erl_time_sup to handle timezones w/o DST on FreeBSD as on other platforms
This change handles erlang:localtime_to_universaltime(...,true) in timezones without DST in a consistent way over platforms. Specifically BSD did return an (accurate) -1 from mktime, which blew things up. Now all platforms regard no DST as a DST with delta zero. Linux, SunOS, MacOS etc already did this, why the behaviour on BSD was updated to the slightly incorrect one instead of breaking backward compatibility on most other platforms. Before this change, erlang:localtime_to_universaltime({{2008, 8, 1}, {0, 0, 0}},true) would return {1969, 12, 31}, {23, 59, 59}} when TZ=UTC on FreeBSD, now it mimics the behaviour of other systems and returns {{2008, 8, 1},{0, 0, 0}}. The problem was originally reported by Paul Guyot on erlang-bugs mailing list: http://www.erlang.org/pipermail/erlang-bugs/2008-November/001077.html This correction replaces earlier BSD specific open source patches for this problem.
Diffstat (limited to 'erts/emulator/beam/erl_time_sup.c')
-rw-r--r--erts/emulator/beam/erl_time_sup.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index c15f85f8f1..7b8706ea13 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -650,6 +650,22 @@ local_to_univ(Sint *year, Sint *month, Sint *day,
t.tm_sec = *second;
t.tm_isdst = isdst;
the_clock = mktime(&t);
+ if (the_clock == -1) {
+ if (isdst) {
+ /* If this is a timezone without DST and the OS (correctly)
+ refuses to give us a DST time, we simulate the Linux/Solaris
+ behaviour of giving the same data as if is_dst was not set. */
+ t.tm_isdst = 0;
+ the_clock = mktime(&t);
+ if (the_clock == -1) {
+ /* Failed anyway, something else is bad - will be a badarg */
+ return 0;
+ }
+ } else {
+ /* Something else is the matter, badarg. */
+ return 0;
+ }
+ }
#ifdef HAVE_GMTIME_R
gmtime_r(&the_clock, (tm = &tmbuf));
#else
@@ -663,6 +679,10 @@ local_to_univ(Sint *year, Sint *month, Sint *day,
*second = tm->tm_sec;
return 1;
}
+#if defined(HAVE_POSIX2TIME) && defined(HAVE_DECL_POSIX2TIME) && \
+ !HAVE_DECL_POSIX2TIME
+extern time_t posix2time(time_t);
+#endif
int
univ_to_local(Sint *year, Sint *month, Sint *day,