1 // Copyright (c) 2012 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/time.h" 6 7 #include <sys/time.h> 8 #include <time.h> 9 #if defined(OS_ANDROID) 10 #include <time64.h> 11 #endif 12 13 #include <limits> 14 15 #include "base/basictypes.h" 16 #include "base/logging.h" 17 18 #if defined(OS_ANDROID) 19 #include "base/os_compat_android.h" 20 #elif defined(OS_NACL) 21 #include "base/os_compat_nacl.h" 22 #endif 23 24 namespace { 25 26 // Define a system-specific SysTime that wraps either to a time_t or 27 // a time64_t depending on the host system, and associated convertion. 28 // See crbug.com/162007 29 #if defined(OS_ANDROID) 30 typedef time64_t SysTime; 31 32 SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { 33 if (is_local) 34 return mktime64(timestruct); 35 else 36 return timegm64(timestruct); 37 } 38 39 void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { 40 if (is_local) 41 localtime64_r(&t, timestruct); 42 else 43 gmtime64_r(&t, timestruct); 44 } 45 46 #else // OS_ANDROID 47 typedef time_t SysTime; 48 49 SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) { 50 if (is_local) 51 return mktime(timestruct); 52 else 53 return timegm(timestruct); 54 } 55 56 void SysTimeToTimeStruct(SysTime t, struct tm* timestruct, bool is_local) { 57 if (is_local) 58 localtime_r(&t, timestruct); 59 else 60 gmtime_r(&t, timestruct); 61 } 62 #endif // OS_ANDROID 63 64 #if !defined(OS_MACOSX) 65 // Helper function to get results from clock_gettime() as TimeTicks object. 66 // Minimum requirement is MONOTONIC_CLOCK to be supported on the system. 67 // FreeBSD 6 has CLOCK_MONOTONIC but defines _POSIX_MONOTONIC_CLOCK to -1. 68 #if (defined(OS_POSIX) && \ 69 defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0) || \ 70 defined(OS_BSD) || defined(OS_ANDROID) 71 base::TimeTicks ClockNow(clockid_t clk_id) { 72 uint64_t absolute_micro; 73 74 struct timespec ts; 75 if (clock_gettime(clk_id, &ts) != 0) { 76 NOTREACHED() << "clock_gettime(" << clk_id << ") failed."; 77 return base::TimeTicks(); 78 } 79 80 absolute_micro = 81 (static_cast<int64>(ts.tv_sec) * base::Time::kMicrosecondsPerSecond) + 82 (static_cast<int64>(ts.tv_nsec) / base::Time::kNanosecondsPerMicrosecond); 83 84 return base::TimeTicks::FromInternalValue(absolute_micro); 85 } 86 #else // _POSIX_MONOTONIC_CLOCK 87 #error No usable tick clock function on this platform. 88 #endif // _POSIX_MONOTONIC_CLOCK 89 #endif // !defined(OS_MACOSX) 90 91 } // namespace 92 93 namespace base { 94 95 struct timespec TimeDelta::ToTimeSpec() const { 96 int64 microseconds = InMicroseconds(); 97 time_t seconds = 0; 98 if (microseconds >= Time::kMicrosecondsPerSecond) { 99 seconds = InSeconds(); 100 microseconds -= seconds * Time::kMicrosecondsPerSecond; 101 } 102 struct timespec result = 103 {seconds, 104 static_cast<long>(microseconds * Time::kNanosecondsPerMicrosecond)}; 105 return result; 106 } 107 108 #if !defined(OS_MACOSX) 109 // The Time routines in this file use standard POSIX routines, or almost- 110 // standard routines in the case of timegm. We need to use a Mach-specific 111 // function for TimeTicks::Now() on Mac OS X. 112 113 // Time ----------------------------------------------------------------------- 114 115 // Windows uses a Gregorian epoch of 1601. We need to match this internally 116 // so that our time representations match across all platforms. See bug 14734. 117 // irb(main):010:0> Time.at(0).getutc() 118 // => Thu Jan 01 00:00:00 UTC 1970 119 // irb(main):011:0> Time.at(-11644473600).getutc() 120 // => Mon Jan 01 00:00:00 UTC 1601 121 static const int64 kWindowsEpochDeltaSeconds = GG_INT64_C(11644473600); 122 static const int64 kWindowsEpochDeltaMilliseconds = 123 kWindowsEpochDeltaSeconds * Time::kMillisecondsPerSecond; 124 125 // static 126 const int64 Time::kWindowsEpochDeltaMicroseconds = 127 kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; 128 129 // Some functions in time.cc use time_t directly, so we provide an offset 130 // to convert from time_t (Unix epoch) and internal (Windows epoch). 131 // static 132 const int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; 133 134 // static 135 Time Time::Now() { 136 struct timeval tv; 137 struct timezone tz = { 0, 0 }; // UTC 138 if (gettimeofday(&tv, &tz) != 0) { 139 DCHECK(0) << "Could not determine time of day"; 140 LOG_ERRNO(ERROR) << "Call to gettimeofday failed."; 141 // Return null instead of uninitialized |tv| value, which contains random 142 // garbage data. This may result in the crash seen in crbug.com/147570. 143 return Time(); 144 } 145 // Combine seconds and microseconds in a 64-bit field containing microseconds 146 // since the epoch. That's enough for nearly 600 centuries. Adjust from 147 // Unix (1970) to Windows (1601) epoch. 148 return Time((tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec) + 149 kWindowsEpochDeltaMicroseconds); 150 } 151 152 // static 153 Time Time::NowFromSystemTime() { 154 // Just use Now() because Now() returns the system time. 155 return Now(); 156 } 157 158 void Time::Explode(bool is_local, Exploded* exploded) const { 159 // Time stores times with microsecond resolution, but Exploded only carries 160 // millisecond resolution, so begin by being lossy. Adjust from Windows 161 // epoch (1601) to Unix epoch (1970); 162 int64 microseconds = us_ - kWindowsEpochDeltaMicroseconds; 163 // The following values are all rounded towards -infinity. 164 int64 milliseconds; // Milliseconds since epoch. 165 SysTime seconds; // Seconds since epoch. 166 int millisecond; // Exploded millisecond value (0-999). 167 if (microseconds >= 0) { 168 // Rounding towards -infinity <=> rounding towards 0, in this case. 169 milliseconds = microseconds / kMicrosecondsPerMillisecond; 170 seconds = milliseconds / kMillisecondsPerSecond; 171 millisecond = milliseconds % kMillisecondsPerSecond; 172 } else { 173 // Round these *down* (towards -infinity). 174 milliseconds = (microseconds - kMicrosecondsPerMillisecond + 1) / 175 kMicrosecondsPerMillisecond; 176 seconds = (milliseconds - kMillisecondsPerSecond + 1) / 177 kMillisecondsPerSecond; 178 // Make this nonnegative (and between 0 and 999 inclusive). 179 millisecond = milliseconds % kMillisecondsPerSecond; 180 if (millisecond < 0) 181 millisecond += kMillisecondsPerSecond; 182 } 183 184 struct tm timestruct; 185 SysTimeToTimeStruct(seconds, ×truct, is_local); 186 187 exploded->year = timestruct.tm_year + 1900; 188 exploded->month = timestruct.tm_mon + 1; 189 exploded->day_of_week = timestruct.tm_wday; 190 exploded->day_of_month = timestruct.tm_mday; 191 exploded->hour = timestruct.tm_hour; 192 exploded->minute = timestruct.tm_min; 193 exploded->second = timestruct.tm_sec; 194 exploded->millisecond = millisecond; 195 } 196 197 // static 198 Time Time::FromExploded(bool is_local, const Exploded& exploded) { 199 struct tm timestruct; 200 timestruct.tm_sec = exploded.second; 201 timestruct.tm_min = exploded.minute; 202 timestruct.tm_hour = exploded.hour; 203 timestruct.tm_mday = exploded.day_of_month; 204 timestruct.tm_mon = exploded.month - 1; 205 timestruct.tm_year = exploded.year - 1900; 206 timestruct.tm_wday = exploded.day_of_week; // mktime/timegm ignore this 207 timestruct.tm_yday = 0; // mktime/timegm ignore this 208 timestruct.tm_isdst = -1; // attempt to figure it out 209 #if !defined(OS_NACL) && !defined(OS_SOLARIS) 210 timestruct.tm_gmtoff = 0; // not a POSIX field, so mktime/timegm ignore 211 timestruct.tm_zone = NULL; // not a POSIX field, so mktime/timegm ignore 212 #endif 213 214 215 int64 milliseconds; 216 SysTime seconds; 217 218 // Certain exploded dates do not really exist due to daylight saving times, 219 // and this causes mktime() to return implementation-defined values when 220 // tm_isdst is set to -1. On Android, the function will return -1, while the 221 // C libraries of other platforms typically return a liberally-chosen value. 222 // Handling this requires the special code below. 223 224 // SysTimeFromTimeStruct() modifies the input structure, save current value. 225 struct tm timestruct0 = timestruct; 226 227 seconds = SysTimeFromTimeStruct(×truct, is_local); 228 if (seconds == -1) { 229 // Get the time values with tm_isdst == 0 and 1, then select the closest one 230 // to UTC 00:00:00 that isn't -1. 231 timestruct = timestruct0; 232 timestruct.tm_isdst = 0; 233 int64 seconds_isdst0 = SysTimeFromTimeStruct(×truct, is_local); 234 235 timestruct = timestruct0; 236 timestruct.tm_isdst = 1; 237 int64 seconds_isdst1 = SysTimeFromTimeStruct(×truct, is_local); 238 239 // seconds_isdst0 or seconds_isdst1 can be -1 for some timezones. 240 // E.g. "CLST" (Chile Summer Time) returns -1 for 'tm_isdt == 1'. 241 if (seconds_isdst0 < 0) 242 seconds = seconds_isdst1; 243 else if (seconds_isdst1 < 0) 244 seconds = seconds_isdst0; 245 else 246 seconds = std::min(seconds_isdst0, seconds_isdst1); 247 } 248 249 // Handle overflow. Clamping the range to what mktime and timegm might 250 // return is the best that can be done here. It's not ideal, but it's better 251 // than failing here or ignoring the overflow case and treating each time 252 // overflow as one second prior to the epoch. 253 if (seconds == -1 && 254 (exploded.year < 1969 || exploded.year > 1970)) { 255 // If exploded.year is 1969 or 1970, take -1 as correct, with the 256 // time indicating 1 second prior to the epoch. (1970 is allowed to handle 257 // time zone and DST offsets.) Otherwise, return the most future or past 258 // time representable. Assumes the time_t epoch is 1970-01-01 00:00:00 UTC. 259 // 260 // The minimum and maximum representible times that mktime and timegm could 261 // return are used here instead of values outside that range to allow for 262 // proper round-tripping between exploded and counter-type time 263 // representations in the presence of possible truncation to time_t by 264 // division and use with other functions that accept time_t. 265 // 266 // When representing the most distant time in the future, add in an extra 267 // 999ms to avoid the time being less than any other possible value that 268 // this function can return. 269 270 // On Android, SysTime is int64, special care must be taken to avoid 271 // overflows. 272 const int64 min_seconds = (sizeof(SysTime) < sizeof(int64)) 273 ? std::numeric_limits<SysTime>::min() 274 : std::numeric_limits<int32_t>::min(); 275 const int64 max_seconds = (sizeof(SysTime) < sizeof(int64)) 276 ? std::numeric_limits<SysTime>::max() 277 : std::numeric_limits<int32_t>::max(); 278 if (exploded.year < 1969) { 279 milliseconds = min_seconds * kMillisecondsPerSecond; 280 } else { 281 milliseconds = max_seconds * kMillisecondsPerSecond; 282 milliseconds += (kMillisecondsPerSecond - 1); 283 } 284 } else { 285 milliseconds = seconds * kMillisecondsPerSecond + exploded.millisecond; 286 } 287 288 // Adjust from Unix (1970) to Windows (1601) epoch. 289 return Time((milliseconds * kMicrosecondsPerMillisecond) + 290 kWindowsEpochDeltaMicroseconds); 291 } 292 293 // TimeTicks ------------------------------------------------------------------ 294 // static 295 TimeTicks TimeTicks::Now() { 296 return ClockNow(CLOCK_MONOTONIC); 297 } 298 299 // static 300 TimeTicks TimeTicks::HighResNow() { 301 return Now(); 302 } 303 304 // static 305 TimeTicks TimeTicks::ThreadNow() { 306 #if defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0) 307 return ClockNow(CLOCK_THREAD_CPUTIME_ID); 308 #else 309 NOTREACHED(); 310 return TimeTicks(); 311 #endif 312 } 313 314 #if defined(OS_CHROMEOS) 315 // Force definition of the system trace clock; it is a chromeos-only api 316 // at the moment and surfacing it in the right place requires mucking 317 // with glibc et al. 318 #define CLOCK_SYSTEM_TRACE 11 319 320 // static 321 TimeTicks TimeTicks::NowFromSystemTraceTime() { 322 uint64_t absolute_micro; 323 324 struct timespec ts; 325 if (clock_gettime(CLOCK_SYSTEM_TRACE, &ts) != 0) { 326 // NB: fall-back for a chrome os build running on linux 327 return HighResNow(); 328 } 329 330 absolute_micro = 331 (static_cast<int64>(ts.tv_sec) * Time::kMicrosecondsPerSecond) + 332 (static_cast<int64>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond); 333 334 return TimeTicks(absolute_micro); 335 } 336 337 #else // !defined(OS_CHROMEOS) 338 339 // static 340 TimeTicks TimeTicks::NowFromSystemTraceTime() { 341 return HighResNow(); 342 } 343 344 #endif // defined(OS_CHROMEOS) 345 346 #endif // !OS_MACOSX 347 348 // static 349 Time Time::FromTimeVal(struct timeval t) { 350 DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond)); 351 DCHECK_GE(t.tv_usec, 0); 352 if (t.tv_usec == 0 && t.tv_sec == 0) 353 return Time(); 354 if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 && 355 t.tv_sec == std::numeric_limits<time_t>::max()) 356 return Max(); 357 return Time( 358 (static_cast<int64>(t.tv_sec) * Time::kMicrosecondsPerSecond) + 359 t.tv_usec + 360 kTimeTToMicrosecondsOffset); 361 } 362 363 struct timeval Time::ToTimeVal() const { 364 struct timeval result; 365 if (is_null()) { 366 result.tv_sec = 0; 367 result.tv_usec = 0; 368 return result; 369 } 370 if (is_max()) { 371 result.tv_sec = std::numeric_limits<time_t>::max(); 372 result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1; 373 return result; 374 } 375 int64 us = us_ - kTimeTToMicrosecondsOffset; 376 result.tv_sec = us / Time::kMicrosecondsPerSecond; 377 result.tv_usec = us % Time::kMicrosecondsPerSecond; 378 return result; 379 } 380 381 } // namespace base 382