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 <math.h>
      8 #include <limits>
      9 
     10 #include "base/float_util.h"
     11 #include "base/logging.h"
     12 #include "base/strings/sys_string_conversions.h"
     13 #include "base/third_party/nspr/prtime.h"
     14 
     15 namespace base {
     16 
     17 // TimeDelta ------------------------------------------------------------------
     18 
     19 int TimeDelta::InDays() const {
     20   return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
     21 }
     22 
     23 int TimeDelta::InHours() const {
     24   return static_cast<int>(delta_ / Time::kMicrosecondsPerHour);
     25 }
     26 
     27 int TimeDelta::InMinutes() const {
     28   return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute);
     29 }
     30 
     31 double TimeDelta::InSecondsF() const {
     32   return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
     33 }
     34 
     35 int64 TimeDelta::InSeconds() const {
     36   return delta_ / Time::kMicrosecondsPerSecond;
     37 }
     38 
     39 double TimeDelta::InMillisecondsF() const {
     40   return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
     41 }
     42 
     43 int64 TimeDelta::InMilliseconds() const {
     44   return delta_ / Time::kMicrosecondsPerMillisecond;
     45 }
     46 
     47 int64 TimeDelta::InMillisecondsRoundedUp() const {
     48   return (delta_ + Time::kMicrosecondsPerMillisecond - 1) /
     49       Time::kMicrosecondsPerMillisecond;
     50 }
     51 
     52 int64 TimeDelta::InMicroseconds() const {
     53   return delta_;
     54 }
     55 
     56 // Time -----------------------------------------------------------------------
     57 
     58 // static
     59 Time Time::Max() {
     60   return Time(std::numeric_limits<int64>::max());
     61 }
     62 
     63 // static
     64 Time Time::FromTimeT(time_t tt) {
     65   if (tt == 0)
     66     return Time();  // Preserve 0 so we can tell it doesn't exist.
     67   if (tt == std::numeric_limits<time_t>::max())
     68     return Max();
     69   return Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset);
     70 }
     71 
     72 time_t Time::ToTimeT() const {
     73   if (is_null())
     74     return 0;  // Preserve 0 so we can tell it doesn't exist.
     75   if (is_max()) {
     76     // Preserve max without offset to prevent overflow.
     77     return std::numeric_limits<time_t>::max();
     78   }
     79   if (std::numeric_limits<int64>::max() - kTimeTToMicrosecondsOffset <= us_) {
     80     DLOG(WARNING) << "Overflow when converting base::Time with internal " <<
     81                      "value " << us_ << " to time_t.";
     82     return std::numeric_limits<time_t>::max();
     83   }
     84   return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
     85 }
     86 
     87 // static
     88 Time Time::FromDoubleT(double dt) {
     89   if (dt == 0 || IsNaN(dt))
     90     return Time();  // Preserve 0 so we can tell it doesn't exist.
     91   if (dt == std::numeric_limits<double>::max())
     92     return Max();
     93   return Time(static_cast<int64>((dt *
     94                                   static_cast<double>(kMicrosecondsPerSecond)) +
     95                                  kTimeTToMicrosecondsOffset));
     96 }
     97 
     98 double Time::ToDoubleT() const {
     99   if (is_null())
    100     return 0;  // Preserve 0 so we can tell it doesn't exist.
    101   if (is_max()) {
    102     // Preserve max without offset to prevent overflow.
    103     return std::numeric_limits<double>::max();
    104   }
    105   return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
    106           static_cast<double>(kMicrosecondsPerSecond));
    107 }
    108 
    109 #if defined(OS_POSIX)
    110 // static
    111 Time Time::FromTimeSpec(const timespec& ts) {
    112   return FromDoubleT(ts.tv_sec +
    113                      static_cast<double>(ts.tv_nsec) /
    114                          base::Time::kNanosecondsPerSecond);
    115 }
    116 #endif
    117 
    118 // static
    119 Time Time::FromJsTime(double ms_since_epoch) {
    120   // The epoch is a valid time, so this constructor doesn't interpret
    121   // 0 as the null time.
    122   if (ms_since_epoch == std::numeric_limits<double>::max())
    123     return Max();
    124   return Time(static_cast<int64>(ms_since_epoch * kMicrosecondsPerMillisecond) +
    125               kTimeTToMicrosecondsOffset);
    126 }
    127 
    128 double Time::ToJsTime() const {
    129   if (is_null()) {
    130     // Preserve 0 so the invalid result doesn't depend on the platform.
    131     return 0;
    132   }
    133   if (is_max()) {
    134     // Preserve max without offset to prevent overflow.
    135     return std::numeric_limits<double>::max();
    136   }
    137   return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
    138           kMicrosecondsPerMillisecond);
    139 }
    140 
    141 // static
    142 Time Time::UnixEpoch() {
    143   Time time;
    144   time.us_ = kTimeTToMicrosecondsOffset;
    145   return time;
    146 }
    147 
    148 Time Time::LocalMidnight() const {
    149   Exploded exploded;
    150   LocalExplode(&exploded);
    151   exploded.hour = 0;
    152   exploded.minute = 0;
    153   exploded.second = 0;
    154   exploded.millisecond = 0;
    155   return FromLocalExploded(exploded);
    156 }
    157 
    158 // static
    159 bool Time::FromStringInternal(const char* time_string,
    160                               bool is_local,
    161                               Time* parsed_time) {
    162   DCHECK((time_string != NULL) && (parsed_time != NULL));
    163 
    164   if (time_string[0] == '\0')
    165     return false;
    166 
    167   PRTime result_time = 0;
    168   PRStatus result = PR_ParseTimeString(time_string,
    169                                        is_local ? PR_FALSE : PR_TRUE,
    170                                        &result_time);
    171   if (PR_SUCCESS != result)
    172     return false;
    173 
    174   result_time += kTimeTToMicrosecondsOffset;
    175   *parsed_time = Time(result_time);
    176   return true;
    177 }
    178 
    179 // Time::Exploded -------------------------------------------------------------
    180 
    181 inline bool is_in_range(int value, int lo, int hi) {
    182   return lo <= value && value <= hi;
    183 }
    184 
    185 bool Time::Exploded::HasValidValues() const {
    186   return is_in_range(month, 1, 12) &&
    187          is_in_range(day_of_week, 0, 6) &&
    188          is_in_range(day_of_month, 1, 31) &&
    189          is_in_range(hour, 0, 23) &&
    190          is_in_range(minute, 0, 59) &&
    191          is_in_range(second, 0, 60) &&
    192          is_in_range(millisecond, 0, 999);
    193 }
    194 
    195 }  // namespace base
    196