aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/bif.c64
-rw-r--r--erts/emulator/beam/bif.tab6
-rw-r--r--erts/emulator/beam/erl_time_sup.c29
-rw-r--r--erts/emulator/beam/sys.h3
4 files changed, 102 insertions, 0 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 26f1b4facb..c3c247fffe 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -3385,6 +3385,70 @@ BIF_RETTYPE universaltime_to_localtime_1(BIF_ALIST_1)
BIF_RET(TUPLE2(hp, res1, res2));
}
+/* convert calendar:universaltime_to_seconds/1 */
+
+BIF_RETTYPE universaltime_to_seconds_1(BIF_ALIST_1)
+{
+ Sint year, month, day;
+ Sint hour, minute, second;
+
+ Sint64 seconds = 0;
+ Eterm *hp;
+ Uint hsz = 0;
+
+ if (!time_to_parts(BIF_ARG_1, &year, &month, &day,
+ &hour, &minute, &second))
+ BIF_ERROR(BIF_P, BADARG);
+
+ if (!univ_to_seconds(year, month, day, hour, minute, second, &seconds)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ erts_bld_sint64(NULL, &hsz, seconds);
+ hp = HAlloc(BIF_P, hsz);
+ BIF_RET(erts_bld_sint64(&hp, NULL, seconds));
+}
+
+/* convert calendar:seconds_to_universaltime/1 */
+
+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;
+
+ if (is_not_integer(BIF_ARG_1)) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+
+ seconds = (time_t)signed_val(BIF_ARG_1);
+
+ if (!gmtime_r(&seconds, &t)) {
+ 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));
+ hp += 4;
+ res2 = TUPLE3(hp,make_small(hour),make_small(minute),
+ make_small(second));
+ hp += 4;
+ BIF_RET(TUPLE2(hp, res1, res2));
+}
+
+
/**********************************************************************/
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 987008c937..0d6af46aa5 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -806,6 +806,12 @@ bif file:native_name_encoding/0
#
bif erlang:check_old_code/1
+
+#
+# New in R15B
+#
+bif erlang:universaltime_to_seconds/1
+bif erlang:seconds_to_universaltime/1
#
# Obsolete
#
diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c
index 695d08ae2d..00a4906caa 100644
--- a/erts/emulator/beam/erl_time_sup.c
+++ b/erts/emulator/beam/erl_time_sup.c
@@ -648,7 +648,36 @@ static time_t gregday(Sint year, Sint month, Sint day)
return ndays - 135140; /* 135140 = Jan 1, 1970 */
}
+#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 univ_to_seconds(Sint year, Sint month, Sint day, Sint hour, Sint minute, Sint second, Sint64 *time) {
+ Sint days;
+
+ if (!(IN_RANGE(1600, year, INT_MAX - 1) &&
+ IN_RANGE(1, month, 12) &&
+ IN_RANGE(1, day, (mdays[month] +
+ (month == 2
+ && (year % 4 == 0)
+ && (year % 100 != 0 || year % 400 == 0)))) &&
+ IN_RANGE(0, hour, 23) &&
+ IN_RANGE(0, minute, 59) &&
+ IN_RANGE(0, second, 59))) {
+ return 0;
+ }
+
+ days = gregday(year, month, day);
+ *time = SECONDS_PER_DAY;
+ *time *= days; /* don't try overflow it, it hurts */
+ *time += SECONDS_PER_HOUR * hour;
+ *time += SECONDS_PER_MINUTE * minute;
+ *time += second;
+ return 1;
+}
int
local_to_univ(Sint *year, Sint *month, Sint *day,
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index d8cd22a177..3abae2243c 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -668,6 +668,9 @@ 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 univ_to_seconds(Sint year, Sint month, Sint day,
+ Sint hour, Sint minute, Sint second,
+ Sint64* seconds);
int local_to_univ(Sint *year, Sint *month, Sint *day,
Sint *hour, Sint *minute, Sint *second, int isdst);
void get_now(Uint*, Uint*, Uint*);