about summary refs log tree commit diff
path: root/src/rt/rust_builtin.cpp
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2012-04-03 10:32:26 -0700
committerErick Tryzelaar <erick.tryzelaar@gmail.com>2012-04-03 22:43:10 -0700
commit4a4889859e84b65617c27a08e129086267b58695 (patch)
treee9ef7852519d08de5cc3862c42e5645694ec3757 /src/rt/rust_builtin.cpp
parent72444636d32b34743e14bbd25c3ffc579b881af8 (diff)
downloadrust-4a4889859e84b65617c27a08e129086267b58695.tar.gz
rust-4a4889859e84b65617c27a08e129086267b58695.zip
std: add localtime/gmtime support.
Diffstat (limited to 'src/rt/rust_builtin.cpp')
-rw-r--r--src/rt/rust_builtin.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 684322a22a8..9c2e2c3276c 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -8,6 +8,8 @@
 #include "rust_abi.h"
 #include "rust_port.h"
 
+#include <time.h>
+
 #ifdef __APPLE__
 #include <crt_externs.h>
 #endif
@@ -448,6 +450,127 @@ precise_time_ns(uint64_t *ns) {
     *ns = t.time_ns();
 }
 
+struct rust_tm {
+    int32_t tm_sec;
+    int32_t tm_min;
+    int32_t tm_hour;
+    int32_t tm_mday;
+    int32_t tm_mon;
+    int32_t tm_year;
+    int32_t tm_wday;
+    int32_t tm_yday;
+    int32_t tm_isdst;
+    int32_t tm_gmtoff;
+    rust_str *tm_zone;
+    int32_t tm_nsec;
+};
+
+void rust_tm_to_tm(rust_tm* in_tm, tm* out_tm) {
+    memset(out_tm, 0, sizeof(tm));
+    out_tm->tm_sec = in_tm->tm_sec;
+    out_tm->tm_min = in_tm->tm_min;
+    out_tm->tm_hour = in_tm->tm_hour;
+    out_tm->tm_mday = in_tm->tm_mday;
+    out_tm->tm_mon = in_tm->tm_mon;
+    out_tm->tm_year = in_tm->tm_year;
+    out_tm->tm_wday = in_tm->tm_wday;
+    out_tm->tm_yday = in_tm->tm_yday;
+    out_tm->tm_isdst = in_tm->tm_isdst;
+}
+
+void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
+                   const char *zone, int32_t nsec) {
+    out_tm->tm_sec = in_tm->tm_sec;
+    out_tm->tm_min = in_tm->tm_min;
+    out_tm->tm_hour = in_tm->tm_hour;
+    out_tm->tm_mday = in_tm->tm_mday;
+    out_tm->tm_mon = in_tm->tm_mon;
+    out_tm->tm_year = in_tm->tm_year;
+    out_tm->tm_wday = in_tm->tm_wday;
+    out_tm->tm_yday = in_tm->tm_yday;
+    out_tm->tm_isdst = in_tm->tm_isdst;
+    out_tm->tm_gmtoff = gmtoff;
+    out_tm->tm_nsec = nsec;
+
+    if (zone != NULL) {
+        size_t size = strlen(zone);
+        str_reserve_shared(&out_tm->tm_zone, size);
+        memcpy(out_tm->tm_zone->data, zone, size);
+        out_tm->tm_zone->fill = size + 1;
+        out_tm->tm_zone->data[size] = '\0';
+    }
+}
+
+#if defined(__WIN32__)
+#define TZSET() _tzset()
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define GMTIME(clock, result) gmtime_s((result), (clock))
+#define LOCALTIME(clock, result) localtime_s((result), (clock))
+#define TIMEGM(result) _mkgmtime64(result)
+#else
+struct tm* GMTIME(const time_t *clock, tm *result) {
+    struct tm* t = gmtime(clock);
+    if (t == NULL || result == NULL) { return NULL; }
+    *result = *t;
+    return result;
+}
+struct tm* LOCALTIME(const time_t *clock, tm *result) {
+    struct tm* t = localtime(clock);
+    if (t == NULL || result == NULL) { return NULL; }
+    *result = *t;
+    return result;
+}
+#define TIMEGM(result) mktime((result)) - _timezone
+#endif
+#else
+#define TZSET() tzset()
+#define GMTIME(clock, result) gmtime_r((clock), (result))
+#define LOCALTIME(clock, result) localtime_r((clock), (result))
+#define TIMEGM(result) timegm(result)
+#endif
+
+extern "C" CDECL void
+rust_gmtime(int64_t *sec, int32_t *nsec, rust_tm *timeptr) {
+    tm tm;
+    time_t s = *sec;
+    GMTIME(&s, &tm);
+
+    tm_to_rust_tm(&tm, timeptr, 0, "UTC", *nsec);
+}
+
+extern "C" CDECL void
+rust_localtime(int64_t *sec, int32_t *nsec, rust_tm *timeptr) {
+    tm tm;
+    TZSET();
+    time_t s = *sec;
+    LOCALTIME(&s, &tm);
+
+#if defined(__WIN32__)
+    int32_t gmtoff = -timezone;
+    char zone[64];
+    strftime(zone, sizeof(zone), "%Z", &tm);
+#else
+    int32_t gmtoff = tm.tm_gmtoff;
+    const char *zone = tm.tm_zone;
+#endif
+
+    tm_to_rust_tm(&tm, timeptr, gmtoff, zone, *nsec);
+}
+
+extern "C" CDECL void
+rust_timegm(rust_tm* timeptr, int64_t *out) {
+    tm t;
+    rust_tm_to_tm(timeptr, &t);
+    *out = TIMEGM(&t);
+}
+
+extern "C" CDECL void
+rust_mktime(rust_tm* timeptr, int64_t *out) {
+    tm t;
+    rust_tm_to_tm(timeptr, &t);
+    *out = mktime(&t);
+}
+
 extern "C" CDECL rust_sched_id
 rust_get_sched_id() {
     rust_task *task = rust_get_current_task();