#include <stdint.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#if !defined(__WIN32__)
#include <sys/time.h>
#include <sys/types.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#else
#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include <tchar.h>
#endif
#ifdef __APPLE__
#include <TargetConditionals.h>
#include <mach/mach_time.h>
#if !(TARGET_OS_IPHONE)
#include <crt_externs.h>
#endif
#endif
#ifdef __ANDROID__
static time_t timegm(struct tm *tm) {
time_t ret;
char *tz;
tz = getenv("TZ");
if (tz)
tz = strdup(tz);
setenv("TZ", "", 1);
tzset();
ret = mktime(tm);
if (tz) {
setenv("TZ", tz, 1);
free(tz);
} else
unsetenv("TZ");
tzset();
return ret;
}
#endif
typedef struct {
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_utcoff;
int32_t tm_nsec;
} rust_time_tm;
static void rust_time_tm_to_tm(rust_time_tm* in_tm, struct tm* out_tm) {
memset(out_tm, 0, sizeof(struct 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;
}
static void tm_to_rust_tm(struct tm* in_tm,
rust_time_tm* out_tm,
int32_t utcoff,
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_utcoff = utcoff;
out_tm->tm_nsec = nsec;
}
#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
static struct tm* GMTIME(const time_t *clock, struct tm *result) {
struct tm* t = gmtime(clock);
if (t == NULL || result == NULL) { return NULL; }
*result = *t;
return result;
}
static struct tm* LOCALTIME(const time_t *clock, struct 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
#ifdef __native_client__
#define TIMEGM(result) mktime((result)) - _timezone
#else
#define TIMEGM(result) timegm(result)
#endif
#define TZSET() tzset()
#define GMTIME(clock, result) gmtime_r((clock), (result))
#define LOCALTIME(clock, result) localtime_r((clock), (result))
#endif
void
rust_time_tzset() {
TZSET();
}
void
rust_time_gmtime(int64_t sec, int32_t nsec, rust_time_tm *timeptr) {
struct tm tm;
time_t s = sec;
GMTIME(&s, &tm);
tm_to_rust_tm(&tm, timeptr, 0, nsec);
}
void
rust_time_localtime(int64_t sec, int32_t nsec, rust_time_tm *timeptr) {
struct tm tm;
time_t s = sec;
LOCALTIME(&s, &tm);
#if defined(__WIN32__)
int32_t utcoff = -timezone;
#elif defined(__native_client__)
int32_t utcoff = _timezone;
#else
int32_t utcoff = tm.tm_gmtoff;
#endif
tm_to_rust_tm(&tm, timeptr, utcoff, nsec);
}
int64_t
rust_time_timegm(rust_time_tm* timeptr) {
struct tm t;
rust_time_tm_to_tm(timeptr, &t);
return TIMEGM(&t);
}
int64_t
rust_time_mktime(rust_time_tm* timeptr) {
struct tm t;
rust_time_tm_to_tm(timeptr, &t);
return mktime(&t);
}