Home | History | Annotate | Download | only in base
      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 
     17 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
     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
     71 Time Time::NowFromSystemTime() {
     72   // Just use Now() because Now() returns the system time.
     73   return Now();
     74 }
     75 
     76 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
    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
    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 
    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
    198 TimeTicks TimeTicks::HighResNow() {
    199   return Now();
    200 }
    201 
    202 #endif  // !OS_MACOSX
    203 
    204 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