summaryrefslogtreecommitdiff
path: root/ext/date
diff options
context:
space:
mode:
Diffstat (limited to 'ext/date')
-rw-r--r--ext/date/date_core.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index 8da69c8c26..2006bd453c 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -3584,6 +3584,15 @@ date_s_nth_kday(int argc, VALUE *argv, VALUE klass)
#if !defined(HAVE_GMTIME_R)
static struct tm*
+gmtime_r(const time_t *t, struct tm *tm)
+{
+ auto struct tm *tmp = gmtime(t);
+ if (tmp)
+ *tm = *tmp;
+ return tmp;
+}
+
+static struct tm*
localtime_r(const time_t *t, struct tm *tm)
{
auto struct tm *tmp = localtime(t);
@@ -3623,6 +3632,7 @@ date_s_today(int argc, VALUE *argv, VALUE klass)
if (time(&t) == -1)
rb_sys_fail("time");
+ tzset();
if (!localtime_r(&t, &tm))
rb_sys_fail("localtime");
@@ -7838,6 +7848,7 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
rb_sys_fail("gettimeofday");
sec = tv.tv_sec;
#endif
+ tzset();
if (!localtime_r(&sec, &tm))
rb_sys_fail("localtime");
@@ -7851,8 +7862,37 @@ datetime_s_now(int argc, VALUE *argv, VALUE klass)
s = 59;
#ifdef HAVE_STRUCT_TM_TM_GMTOFF
of = tm.tm_gmtoff;
+#elif defined(HAVE_VAR_TIMEZONE)
+#ifdef HAVE_VAR_ALTZONE
+ of = (long)((tm.tm_isdst > 0) ? altzone : timezone);
#else
- of = -timezone;
+ of = (long)-timezone;
+ if (tm.tm_isdst) {
+ time_t sec2;
+
+ tm.tm_isdst = 0;
+ sec2 = mktime(&tm);
+ of += (long)difftime(sec2, sec);
+ }
+#endif
+#elif defined(HAVE_TIMEGM)
+ {
+ time_t sec2;
+
+ sec2 = timegm(&tm);
+ of = (long)difftime(sec2, sec);
+ }
+#else
+ {
+ struct tm tm2;
+ time_t sec2;
+
+ if (!gmtime_r(&sec, &tm2))
+ rb_sys_fail("gmtime");
+ tm2.tm_isdst = tm.tm_isdst;
+ sec2 = mktime(&tm2);
+ of = (long)difftime(sec, sec2);
+ }
#endif
#ifdef HAVE_CLOCK_GETTIME
sf = ts.tv_nsec;