• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/time.h"
6 
7 #include <sys/time.h>
8 #include <time.h>
9 
10 #include <limits>
11 
12 #include "base/basictypes.h"
13 #include "base/logging.h"
14 
15 namespace base {
16 
ToTimeSpec() const17 struct timespec TimeDelta::ToTimeSpec() const {
18   int64 microseconds = InMicroseconds();
19   time_t seconds = 0;
20   if (microseconds >= Time::kMicrosecondsPerSecond) {
21     seconds = InSeconds();
22     microseconds -= seconds * Time::kMicrosecondsPerSecond;
23   }
24   struct timespec result =
25       {seconds,
26        microseconds * Time::kNanosecondsPerMicrosecond};
27   return result;
28 }
29 
30 #if !defined(OS_MACOSX)
31 // The Time routines in this file use standard POSIX routines, or almost-
32 // standard routines in the case of timegm.  We need to use a Mach-specific
33 // function for TimeTicks::Now() on Mac OS X.
34 
35 // Time -----------------------------------------------------------------------
36 
37 // Windows uses a Gregorian epoch of 1601.  We need to match this internally
38 // so that our time representations match across all platforms.  See bug 14734.
39 //   irb(main):010:0> Time.at(0).getutc()
40 //   => Thu Jan 01 00:00:00 UTC 1970
41 //   irb(main):011:0> Time.at(-11644473600).getutc()
42 //   => Mon Jan 01 00:00:00 UTC 1601
43 static const int64 kWindowsEpochDeltaSeconds = GG_INT64_C(11644473600);
44 static const int64 kWindowsEpochDeltaMilliseconds =
45     kWindowsEpochDeltaSeconds * Time::kMillisecondsPerSecond;
46 
47 // static
48 const int64 Time::kWindowsEpochDeltaMicroseconds =
49     kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond;
50 
51 // Some functions in time.cc use time_t directly, so we provide an offset
52 // to convert from time_t (Unix epoch) and internal (Windows epoch).
53 // static
54 const int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds;
55 
56 // static
Now()57 Time Time::Now() {
58   struct timeval tv;
59   struct timezone tz = { 0, 0 };  // UTC
60   if (gettimeofday(&tv, &tz) != 0) {
61     DCHECK(0) << "Could not determine time of day";
62   }
63   // Combine seconds and microseconds in a 64-bit field containing microseconds
64   // since the epoch.  That's enough for nearly 600 centuries.  Adjust from
65   // Unix (1970) to Windows (1601) epoch.
66   return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) +
67       kWindowsEpochDeltaMicroseconds);
68 }
69 
70 // static
NowFromSystemTime()71 Time Time::NowFromSystemTime() {
72   // Just use Now() because Now() returns the system time.
73   return Now();
74 }
75 
Explode(bool is_local,Exploded * exploded) const76 void Time::Explode(bool is_local, Exploded* exploded) const {
77   // Time stores times with microsecond resolution, but Exploded only carries
78   // millisecond resolution, so begin by being lossy.  Adjust from Windows
79   // epoch (1601) to Unix epoch (1970);
80   int64 milliseconds = (us_ - kWindowsEpochDeltaMicroseconds) /
81       kMicrosecondsPerMillisecond;
82   time_t seconds = milliseconds / kMillisecondsPerSecond;
83 
84   struct tm timestruct;
85   if (is_local)
86     localtime_r(&seconds, &timestruct);
87   else
88     gmtime_r(&seconds, &timestruct);
89 
90   exploded->year         = timestruct.tm_year + 1900;
91   exploded->month        = timestruct.tm_mon + 1;
92   exploded->day_of_week  = timestruct.tm_wday;
93   exploded->day_of_month = timestruct.tm_mday;
94   exploded->hour         = timestruct.tm_hour;
95   exploded->minute       = timestruct.tm_min;
96   exploded->second       = timestruct.tm_sec;
97   exploded->millisecond  = milliseconds % kMillisecondsPerSecond;
98 }
99 
100 // static
FromExploded(bool is_local,const Exploded & exploded)101 Time Time::FromExploded(bool is_local, const Exploded& exploded) {
102   struct tm timestruct;
103   timestruct.tm_sec    = exploded.second;
104   timestruct.tm_min    = exploded.minute;
105   timestruct.tm_hour   = exploded.hour;
106   timestruct.tm_mday   = exploded.day_of_month;
107   timestruct.tm_mon    = exploded.month - 1;
108   timestruct.tm_year   = exploded.year - 1900;
109   timestruct.tm_wday   = exploded.day_of_week;  // mktime/timegm ignore this
110   timestruct.tm_yday   = 0;     // mktime/timegm ignore this
111   timestruct.tm_isdst  = -1;    // attempt to figure it out
112 #if !defined(OS_NACL)
113   timestruct.tm_gmtoff = 0;     // not a POSIX field, so mktime/timegm ignore
114   timestruct.tm_zone   = NULL;  // not a POSIX field, so mktime/timegm ignore
115 #endif
116 
117   time_t seconds;
118   if (is_local)
119     seconds = mktime(&timestruct);
120   else
121     seconds = timegm(&timestruct);
122 
123   int64 milliseconds;
124   // Handle overflow.  Clamping the range to what mktime and timegm might
125   // return is the best that can be done here.  It's not ideal, but it's better
126   // than failing here or ignoring the overflow case and treating each time
127   // overflow as one second prior to the epoch.
128   if (seconds == -1 &&
129       (exploded.year < 1969 || exploded.year > 1970)) {
130     // If exploded.year is 1969 or 1970, take -1 as correct, with the
131     // time indicating 1 second prior to the epoch.  (1970 is allowed to handle
132     // time zone and DST offsets.)  Otherwise, return the most future or past
133     // time representable.  Assumes the time_t epoch is 1970-01-01 00:00:00 UTC.
134     //
135     // The minimum and maximum representible times that mktime and timegm could
136     // return are used here instead of values outside that range to allow for
137     // proper round-tripping between exploded and counter-type time
138     // representations in the presence of possible truncation to time_t by
139     // division and use with other functions that accept time_t.
140     //
141     // When representing the most distant time in the future, add in an extra
142     // 999ms to avoid the time being less than any other possible value that
143     // this function can return.
144     if (exploded.year < 1969) {
145       milliseconds = std::numeric_limits<time_t>::min() *
146                      kMillisecondsPerSecond;
147     } else {
148       milliseconds = (std::numeric_limits<time_t>::max() *
149                       kMillisecondsPerSecond) +
150                      kMillisecondsPerSecond - 1;
151     }
152   } else {
153     milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond;
154   }
155 
156   // Adjust from Unix (1970) to Windows (1601) epoch.
157   return Time((milliseconds * kMicrosecondsPerMillisecond) +
158       kWindowsEpochDeltaMicroseconds);
159 }
160 
161 // TimeTicks ------------------------------------------------------------------
162 // FreeBSD 6 has CLOCK_MONOLITHIC but defines _POSIX_MONOTONIC_CLOCK to -1.
163 #if (defined(OS_POSIX) &&                                               \
164      defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \
165      defined(OS_FREEBSD) || defined(OS_OPENBSD) || defined(ANDROID)
166 
167 // static
Now()168 TimeTicks TimeTicks::Now() {
169   uint64_t absolute_micro;
170 
171   struct timespec ts;
172   if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
173     NOTREACHED() << "clock_gettime(CLOCK_MONOTONIC) failed.";
174     return TimeTicks();
175   }
176 
177   absolute_micro =
178       (static_cast<int64>(ts.tv_sec) * Time::kMicrosecondsPerSecond) +
179       (static_cast<int64>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond);
180 
181   return TimeTicks(absolute_micro);
182 }
183 
184 #elif defined(OS_NACL)
185 
Now()186 TimeTicks TimeTicks::Now() {
187   // Sadly, Native Client does not have _POSIX_TIMERS enabled in sys/features.h
188   // Apparently NaCl only has CLOCK_REALTIME:
189   // http://code.google.com/p/nativeclient/issues/detail?id=1159
190   return TimeTicks(clock());
191 }
192 
193 #else  // _POSIX_MONOTONIC_CLOCK
194 #error No usable tick clock function on this platform.
195 #endif  // _POSIX_MONOTONIC_CLOCK
196 
197 // static
HighResNow()198 TimeTicks TimeTicks::HighResNow() {
199   return Now();
200 }
201 
202 #endif  // !OS_MACOSX
203 
ToTimeVal() const204 struct timeval Time::ToTimeVal() const {
205   struct timeval result;
206   int64 us = us_ - kTimeTToMicrosecondsOffset;
207   result.tv_sec = us / Time::kMicrosecondsPerSecond;
208   result.tv_usec = us % Time::kMicrosecondsPerSecond;
209   return result;
210 }
211 
212 }  // namespace base
213