1 // ClockTime.cpp: clock and local time functions for Gnash
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <boost/cstdint.hpp>
21 #include "ClockTime.h"
24 #include <ctime> // for time_t, localtime
28 # include <sys/types.h>
29 # include <sys/timeb.h>
33 #if !defined(HAVE_TM_GMTOFF)
34 # ifdef HAVE_LONG_TIMEZONE
35 extern long timezone
; // for tzset()/long timezone;
39 /// Win32 implementation for getTicks
40 # if defined(_WIN32) || defined(WIN32)
42 # include <mmsystem.h>
49 // This needs to return milliseconds. Does it?
56 # include <sys/time.h>
68 boost::uint64_t result
= static_cast<boost::uint64_t>(tv
.tv_sec
) * 1000000L;
70 // Time Unit: microsecond
73 return static_cast<boost::uint64_t>(result
/ 1000.0);
82 /// Common non-boost function to return the present time offset.
83 /// This all seems like a terrible hack. It was moved from Date.cpp,
84 /// whence the following explanation also comes.
86 /// If the real mktime() sees isdst == 0 with a DST date, it sets
87 /// t_isdst and modifies the hour fields, but we need to set the
88 /// specified hour in the localtime in force at that time.
90 /// To do this we set tm_isdst to the correct value for that moment in time
91 /// by doing an initial conversion of the time to find out is_dst for that
92 /// moment without DST, then do the real conversion.
93 /// This may still get things wrong around the hour when the clocks go back
95 /// It also gets things wrong for very high or low time values, when the
96 /// localtime implementation fills the gmtoff element with 53 minutes (on
97 /// at least one machine, anyway).
99 clocktime::getTimeZoneOffset(double time
)
102 time_t tt
= static_cast<time_t>(time
/ 1000.0);
106 #ifdef HAVE_LOCALTIME_R
108 // If the requested time exceeds the limits we return 0; otherwise we'll
109 // be using uninitialized values
110 if (!localtime_r(&tt
, &tm
)) {
114 struct tm
*tmp
= NULL
;
115 tmp
= localtime(&tt
);
116 if (!tmp
) return 0; // We failed.
117 memcpy(&tm
, tmp
, sizeof(struct tm
));
127 #ifdef HAVE_LOCALTIME_R
128 // find out whether DST is in force
129 if (!localtime_r(&ttmp
, &tm2
)) {
133 struct tm
*tmp2
= NULL
;
134 tmp2
= localtime(&ttmp
);
135 if (!tmp2
) return 0; // We failed.
136 memcpy(&tm2
, tmp2
, sizeof(struct tm
));
139 // If mktime or localtime fail, tm2.tm_isdst should be unchanged,
140 // so 0. That's why we don't make any checks on their success.
142 tm
.tm_isdst
= tm2
.tm_isdst
;
144 #ifdef HAVE_TM_GMTOFF
148 // tm_gmtoff is in seconds east of GMT; convert to minutes.
149 offset
= tm
.tm_gmtoff
/ 60;
150 //gnash::log_debug("Using tm.tm_gmtoff. Offset is %d", offset);
155 // Find the geographical system timezone offset and add an hour if
156 // DST applies to the date.
157 // To get it really right I guess we should call both gmtime()
158 // and localtime() and look at the difference.
160 // The range of standard time is GMT-11 to GMT+14.
161 // The most extreme with DST is Chatham Island GMT+12:45 +1DST
165 # if defined(HAVE_TZSET) && defined(HAVE_LONG_TIMEZONE)
168 // timezone is seconds west of GMT
169 offset
= -timezone
/ 60;
170 //gnash::log_debug("Using tzset. Offset is %d", offset);
172 # elif !defined(WIN32) && defined(HAVE_GETTIMEOFDAY)
175 // "The use of the timezone structure is obsolete; the tz argument
176 // should normally be specified as NULL. The tz_dsttime field has
177 // never been used under Linux; it has not been and will not be
178 // supported by libc or glibc."
180 // In practice this appears to return the present time offset including dst,
181 // so adding the dst of the time specified (we do this a couple of lines
182 // down) gives the correct result when it's not presently dst, the wrong
186 gettimeofday(&tv
, &tz
);
187 offset
= -tz
.tz_minuteswest
;
188 //gnash::log_debug("Using gettimeofday. Offset is %d", offset);
190 # elif defined(HAVE_FTIME)
191 // ftime(3): "These days the contents of the timezone and dstflag
192 // fields are undefined."
193 // In practice, timezone is -120 in Italy when it should be -60.
194 // The problem here as for gettimeofday: the offset also includes dst.
199 // tb.timezone is number of minutes west of GMT
200 offset
= -tb
.timezone
;
204 offset
= 0; // No idea.
208 // Adjust by one hour if DST was in force at that time.
210 // According to http://www.timeanddate.com/time/, the only place that
211 // uses DST != +1 hour is Lord Howe Island with half an hour. Tough.
213 if (tm
.tm_isdst
== 0) {
214 // DST exists and is not in effect
216 else if (tm
.tm_isdst
> 0) {
217 // DST exists and was in effect
221 // tm_isdst is negative: cannot get TZ info.
222 // Convert and print in UTC instead.
224 gnash::log_error(_("Cannot get requested timezone information"));