Home | History | Annotate | Download | only in time
      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)
     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 
     29 namespace {
     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)
     36 typedef time64_t SysTime;
     37 
     38 SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
     39   if (is_local)
     40     return mktime64(timestruct);
     41   else
     42     return timegm64(timestruct);
     43 }
     44 
     45 void 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
     53 typedef time_t SysTime;
     54 
     55 SysTime SysTimeFromTimeStruct(struct tm* timestruct, bool is_local) {
     56   if (is_local)
     57     return mktime(timestruct);
     58   else
     59     return timegm(timestruct);
     60 }
     61 
     62 void 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)
     76 base::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 
     98 namespace base {
     99 
    100 struct 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
    126 static const int64 kWindowsEpochDeltaSeconds = GG_INT64_C(11644473600);
    127 
    128 // static
    129 const 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
    135 const int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds;
    136 
    137 // static
    138 Time 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     LOG_ERRNO(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
    156 Time Time::NowFromSystemTime() {
    157   // Just use Now() because Now() returns the system time.
    158   return Now();
    159 }
    160 
    161 void 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, &timestruct, 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
    201 Time 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(&timestruct, 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(&timestruct, is_local);
    237 
    238     timestruct = timestruct0;
    239     timestruct.tm_isdst = 1;
    240     int64 seconds_isdst1 = SysTimeFromTimeStruct(&timestruct, 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
    298 TimeTicks TimeTicks::Now() {
    299   return ClockNow(CLOCK_MONOTONIC);
    300 }
    301 
    302 // static
    303 TimeTicks TimeTicks::HighResNow() {
    304   return Now();
    305 }
    306 
    307 // static
    308 bool TimeTicks::IsHighResNowFastAndReliable() {
    309   return true;
    310 }
    311 
    312 // static
    313 TimeTicks 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 #if defined(OS_CHROMEOS)
    324 // Force definition of the system trace clock; it is a chromeos-only api
    325 // at the moment and surfacing it in the right place requires mucking
    326 // with glibc et al.
    327 #define CLOCK_SYSTEM_TRACE 11
    328 
    329 // static
    330 TimeTicks TimeTicks::NowFromSystemTraceTime() {
    331   uint64_t absolute_micro;
    332 
    333   struct timespec ts;
    334   if (clock_gettime(CLOCK_SYSTEM_TRACE, &ts) != 0) {
    335     // NB: fall-back for a chrome os build running on linux
    336     return HighResNow();
    337   }
    338 
    339   absolute_micro =
    340       (static_cast<int64>(ts.tv_sec) * Time::kMicrosecondsPerSecond) +
    341       (static_cast<int64>(ts.tv_nsec) / Time::kNanosecondsPerMicrosecond);
    342 
    343   return TimeTicks(absolute_micro);
    344 }
    345 
    346 #else // !defined(OS_CHROMEOS)
    347 
    348 // static
    349 TimeTicks TimeTicks::NowFromSystemTraceTime() {
    350   return HighResNow();
    351 }
    352 
    353 #endif // defined(OS_CHROMEOS)
    354 
    355 #endif  // !OS_MACOSX
    356 
    357 // static
    358 Time Time::FromTimeVal(struct timeval t) {
    359   DCHECK_LT(t.tv_usec, static_cast<int>(Time::kMicrosecondsPerSecond));
    360   DCHECK_GE(t.tv_usec, 0);
    361   if (t.tv_usec == 0 && t.tv_sec == 0)
    362     return Time();
    363   if (t.tv_usec == static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1 &&
    364       t.tv_sec == std::numeric_limits<time_t>::max())
    365     return Max();
    366   return Time(
    367       (static_cast<int64>(t.tv_sec) * Time::kMicrosecondsPerSecond) +
    368       t.tv_usec +
    369       kTimeTToMicrosecondsOffset);
    370 }
    371 
    372 struct timeval Time::ToTimeVal() const {
    373   struct timeval result;
    374   if (is_null()) {
    375     result.tv_sec = 0;
    376     result.tv_usec = 0;
    377     return result;
    378   }
    379   if (is_max()) {
    380     result.tv_sec = std::numeric_limits<time_t>::max();
    381     result.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
    382     return result;
    383   }
    384   int64 us = us_ - kTimeTToMicrosecondsOffset;
    385   result.tv_sec = us / Time::kMicrosecondsPerSecond;
    386   result.tv_usec = us % Time::kMicrosecondsPerSecond;
    387   return result;
    388 }
    389 
    390 }  // namespace base
    391