return timegm(tm);
}
+#elif defined(__MINGW32__)
+
+static inline
+time_t bt_timegm(struct tm *tm)
+{
+ return _mkgmtime(tm);
+}
+
#else
-#include <string.h>
-#include <stdlib.h>
+#include <errno.h>
/*
- * Note: Below implementation of timegm() is not thread safe
- * as it changes the environment
- * variable TZ. It is OK as long as it is kept in self-contained program,
- * but should not be used within thread-safe library code.
+ * This is a simple implementation of timegm() it just turns the "struct tm" into
+ * a GMT time_t. It does not normalize any of the fields of the "struct tm", nor
+ * does it set tm_wday or tm_yday.
*/
+static inline
+int bt_leapyear(int year)
+{
+ return ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0));
+}
+
static inline
time_t bt_timegm(struct tm *tm)
{
- time_t ret;
- char *tz;
-
- tz = getenv("TZ");
- /*
- * Make a temporary copy, as the environment variable will be
- * modified.
- */
- if (tz) {
- tz = strdup(tz);
- if (!tz) {
- /*
- * Memory allocation error.
- */
- return (time_t) -1;
+ int year, month, total_days;
+
+ int monthlen[2][12] = {
+ /* Days per month for a regular year */
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ /* Days per month for a leap year */
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ };
+
+ if ((tm->tm_mon >= 12) ||
+ (tm->tm_mday >= 32) ||
+ (tm->tm_hour >= 24) ||
+ (tm->tm_min >= 60) ||
+ (tm->tm_sec >= 61)) {
+ errno = EOVERFLOW;
+ return (time_t) -1;
+ }
+
+ /* Add 365 days for each year since 1970 */
+ total_days = 365 * (tm->tm_year - 70);
+
+ /* Add one day for each leap year since 1970 */
+ for (year = 70; year < tm->tm_year; year++) {
+ if (bt_leapyear(1900 + year)) {
+ total_days++;
}
}
- /* Temporarily setting TZ to 1 for UTC */
- setenv("TZ", "", 1);
- tzset();
- ret = mktime(tm);
- if (tz) {
- setenv("TZ", tz, 1);
- free(tz);
- } else {
- unsetenv("TZ");
+ /* Add days for each remaining month */
+ for (month = 0; month < tm->tm_mon; month++) {
+ total_days += monthlen[bt_leapyear(1900 + year)][month];
}
- tzset();
- return ret;
+
+ /* Add remaining days */
+ total_days += tm->tm_mday - 1;
+
+ return ((((total_days * 24) + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec);
}
#endif