aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2011-12-06 02:55:13 +0100
committerBjörn-Egil Dahlberg <[email protected]>2011-12-08 14:12:02 +0100
commit8f36514229bfaaa6ede8a2daa6aa920686d4251f (patch)
tree9542b2b4182094c1a32e54ead33d4ae85b92e0b7 /erts
parent469815129bd1ce53dc332d2c75142292e0604ef3 (diff)
downloadotp-8f36514229bfaaa6ede8a2daa6aa920686d4251f.tar.gz
otp-8f36514229bfaaa6ede8a2daa6aa920686d4251f.tar.bz2
otp-8f36514229bfaaa6ede8a2daa6aa920686d4251f.zip
Remove OS taint from datetime conversion
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/bif.c17
-rw-r--r--erts/emulator/beam/erl_time_sup.c28
-rw-r--r--erts/emulator/beam/sys.h8
3 files changed, 37 insertions, 16 deletions
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*);