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