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