From 8f36514229bfaaa6ede8a2daa6aa920686d4251f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 6 Dec 2011 02:55:13 +0100 Subject: Remove OS taint from datetime conversion --- erts/emulator/beam/bif.c | 17 ++++------------- erts/emulator/beam/erl_time_sup.c | 28 +++++++++++++++++++++++++++- erts/emulator/beam/sys.h | 8 ++++++-- 3 files changed, 37 insertions(+), 16 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index c3c247fffe..12dc7b3a48 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -3416,28 +3416,19 @@ BIF_RETTYPE seconds_to_universaltime_1(BIF_ALIST_1) Sint year, month, day; Sint hour, minute, second; Eterm res1, res2; - struct tm t; Eterm* hp; - time_t seconds = 0; + Sint64 time = 0; - if (is_not_integer(BIF_ARG_1)) { + if (!term_to_Sint64(BIF_ARG_1, &time)) { BIF_ERROR(BIF_P, BADARG); } - seconds = (time_t)signed_val(BIF_ARG_1); - - if (!gmtime_r(&seconds, &t)) { + if (!seconds_to_univ(time, &year, &month, &day, + &hour, &minute, &second)) { BIF_ERROR(BIF_P, BADARG); } - year = t.tm_year + 1900; - month = t.tm_mon + 1; - day = t.tm_hour; - minute = t.tm_min; - second = t.tm_sec; - /* isdst = t.tm_isdst */ - hp = HAlloc(BIF_P, 4+4+3); res1 = TUPLE3(hp,make_small(year),make_small(month), make_small(day)); diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c index 00a4906caa..edf03d06fb 100644 --- a/erts/emulator/beam/erl_time_sup.c +++ b/erts/emulator/beam/erl_time_sup.c @@ -651,8 +651,34 @@ static time_t gregday(Sint year, Sint month, Sint day) #define SECONDS_PER_MINUTE (60) #define SECONDS_PER_HOUR (60 * SECONDS_PER_MINUTE) #define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) -#define SECONDS_PER_YEAR (86400) +int seconds_to_univ(Sint64 time, Sint *year, Sint *month, Sint *day, + Sint *hour, Sint *minute, Sint *second) { + + Sint y,mi; + Sint64 days = time / SECONDS_PER_DAY; + Sint secs = time % SECONDS_PER_DAY; + Sint tmp = secs % SECONDS_PER_HOUR; + + *hour = secs / SECONDS_PER_HOUR; + *minute = tmp / SECONDS_PER_MINUTE; + *second = tmp % SECONDS_PER_MINUTE; + + days += 719468; + y = (10000*days + 14780) / 3652425; /* seriosly? */ + tmp = days - (365 * y + y/4 - y/100 + y/400); + + if (tmp < 0) { + y--; + tmp = days - (365*y + y/4 - y/100 + y/400); + } + mi = (100 * tmp + 52)/3060; + *month = (mi + 2) % 12 + 1; + *year = y + (mi + 2) / 12; + *day = tmp - (mi * 306 + 5)/10 + 1; + + return 1; +} int univ_to_seconds(Sint year, Sint month, Sint day, Sint hour, Sint minute, Sint second, Sint64 *time) { Sint days; diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 3abae2243c..038c319470 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -666,11 +666,15 @@ void get_localtime(int *year, int *month, int *day, int *hour, int *minute, int *second); void get_universaltime(int *year, int *month, int *day, int *hour, int *minute, int *second); -int univ_to_local(Sint *year, Sint *month, Sint *day, - Sint *hour, Sint *minute, Sint *second); +int seconds_to_univ(Sint64 seconds, + Sint *year, Sint *month, Sint *day, + Sint *hour, Sint *minute, Sint *second); int univ_to_seconds(Sint year, Sint month, Sint day, Sint hour, Sint minute, Sint second, Sint64* seconds); +int univ_to_local( + Sint *year, Sint *month, Sint *day, + Sint *hour, Sint *minute, Sint *second); int local_to_univ(Sint *year, Sint *month, Sint *day, Sint *hour, Sint *minute, Sint *second, int isdst); void get_now(Uint*, Uint*, Uint*); -- cgit v1.2.3