michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "base/time/time.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/float_util.h" michael@0: #include "base/logging.h" michael@0: #include "base/third_party/nspr/prtime.h" michael@0: #include "base/third_party/nspr/prtypes.h" michael@0: michael@0: namespace base { michael@0: michael@0: // TimeDelta ------------------------------------------------------------------ michael@0: michael@0: int TimeDelta::InDays() const { michael@0: return static_cast(delta_ / Time::kMicrosecondsPerDay); michael@0: } michael@0: michael@0: int TimeDelta::InHours() const { michael@0: return static_cast(delta_ / Time::kMicrosecondsPerHour); michael@0: } michael@0: michael@0: int TimeDelta::InMinutes() const { michael@0: return static_cast(delta_ / Time::kMicrosecondsPerMinute); michael@0: } michael@0: michael@0: double TimeDelta::InSecondsF() const { michael@0: return static_cast(delta_) / Time::kMicrosecondsPerSecond; michael@0: } michael@0: michael@0: int64 TimeDelta::InSeconds() const { michael@0: return delta_ / Time::kMicrosecondsPerSecond; michael@0: } michael@0: michael@0: double TimeDelta::InMillisecondsF() const { michael@0: return static_cast(delta_) / Time::kMicrosecondsPerMillisecond; michael@0: } michael@0: michael@0: int64 TimeDelta::InMilliseconds() const { michael@0: return delta_ / Time::kMicrosecondsPerMillisecond; michael@0: } michael@0: michael@0: int64 TimeDelta::InMillisecondsRoundedUp() const { michael@0: return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / michael@0: Time::kMicrosecondsPerMillisecond; michael@0: } michael@0: michael@0: int64 TimeDelta::InMicroseconds() const { michael@0: return delta_; michael@0: } michael@0: michael@0: // Time ----------------------------------------------------------------------- michael@0: michael@0: // static michael@0: Time Time::Max() { michael@0: return Time(std::numeric_limits::max()); michael@0: } michael@0: michael@0: // static michael@0: Time Time::FromTimeT(time_t tt) { michael@0: if (tt == 0) michael@0: return Time(); // Preserve 0 so we can tell it doesn't exist. michael@0: if (tt == std::numeric_limits::max()) michael@0: return Max(); michael@0: return Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset); michael@0: } michael@0: michael@0: time_t Time::ToTimeT() const { michael@0: if (is_null()) michael@0: return 0; // Preserve 0 so we can tell it doesn't exist. michael@0: if (is_max()) { michael@0: // Preserve max without offset to prevent overflow. michael@0: return std::numeric_limits::max(); michael@0: } michael@0: if (std::numeric_limits::max() - kTimeTToMicrosecondsOffset <= us_) { michael@0: DLOG(WARNING) << "Overflow when converting base::Time with internal " << michael@0: "value " << us_ << " to time_t."; michael@0: return std::numeric_limits::max(); michael@0: } michael@0: return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond; michael@0: } michael@0: michael@0: // static michael@0: Time Time::FromDoubleT(double dt) { michael@0: if (dt == 0 || IsNaN(dt)) michael@0: return Time(); // Preserve 0 so we can tell it doesn't exist. michael@0: if (dt == std::numeric_limits::max()) michael@0: return Max(); michael@0: return Time(static_cast((dt * michael@0: static_cast(kMicrosecondsPerSecond)) + michael@0: kTimeTToMicrosecondsOffset)); michael@0: } michael@0: michael@0: double Time::ToDoubleT() const { michael@0: if (is_null()) michael@0: return 0; // Preserve 0 so we can tell it doesn't exist. michael@0: if (is_max()) { michael@0: // Preserve max without offset to prevent overflow. michael@0: return std::numeric_limits::max(); michael@0: } michael@0: return (static_cast(us_ - kTimeTToMicrosecondsOffset) / michael@0: static_cast(kMicrosecondsPerSecond)); michael@0: } michael@0: michael@0: #if defined(OS_POSIX) michael@0: // static michael@0: Time Time::FromTimeSpec(const timespec& ts) { michael@0: return FromDoubleT(ts.tv_sec + michael@0: static_cast(ts.tv_nsec) / michael@0: base::Time::kNanosecondsPerSecond); michael@0: } michael@0: #endif michael@0: michael@0: // static michael@0: Time Time::FromJsTime(double ms_since_epoch) { michael@0: // The epoch is a valid time, so this constructor doesn't interpret michael@0: // 0 as the null time. michael@0: if (ms_since_epoch == std::numeric_limits::max()) michael@0: return Max(); michael@0: return Time(static_cast(ms_since_epoch * kMicrosecondsPerMillisecond) + michael@0: kTimeTToMicrosecondsOffset); michael@0: } michael@0: michael@0: double Time::ToJsTime() const { michael@0: if (is_null()) { michael@0: // Preserve 0 so the invalid result doesn't depend on the platform. michael@0: return 0; michael@0: } michael@0: if (is_max()) { michael@0: // Preserve max without offset to prevent overflow. michael@0: return std::numeric_limits::max(); michael@0: } michael@0: return (static_cast(us_ - kTimeTToMicrosecondsOffset) / michael@0: kMicrosecondsPerMillisecond); michael@0: } michael@0: michael@0: int64 Time::ToJavaTime() const { michael@0: if (is_null()) { michael@0: // Preserve 0 so the invalid result doesn't depend on the platform. michael@0: return 0; michael@0: } michael@0: if (is_max()) { michael@0: // Preserve max without offset to prevent overflow. michael@0: return std::numeric_limits::max(); michael@0: } michael@0: return ((us_ - kTimeTToMicrosecondsOffset) / michael@0: kMicrosecondsPerMillisecond); michael@0: } michael@0: michael@0: // static michael@0: Time Time::UnixEpoch() { michael@0: Time time; michael@0: time.us_ = kTimeTToMicrosecondsOffset; michael@0: return time; michael@0: } michael@0: michael@0: Time Time::LocalMidnight() const { michael@0: Exploded exploded; michael@0: LocalExplode(&exploded); michael@0: exploded.hour = 0; michael@0: exploded.minute = 0; michael@0: exploded.second = 0; michael@0: exploded.millisecond = 0; michael@0: return FromLocalExploded(exploded); michael@0: } michael@0: michael@0: // static michael@0: bool Time::FromStringInternal(const char* time_string, michael@0: bool is_local, michael@0: Time* parsed_time) { michael@0: DCHECK((time_string != NULL) && (parsed_time != NULL)); michael@0: michael@0: if (time_string[0] == '\0') michael@0: return false; michael@0: michael@0: PRTime result_time = 0; michael@0: PRStatus result = PR_ParseTimeString(time_string, michael@0: is_local ? PR_FALSE : PR_TRUE, michael@0: &result_time); michael@0: if (PR_SUCCESS != result) michael@0: return false; michael@0: michael@0: result_time += kTimeTToMicrosecondsOffset; michael@0: *parsed_time = Time(result_time); michael@0: return true; michael@0: } michael@0: michael@0: // Time::Exploded ------------------------------------------------------------- michael@0: michael@0: inline bool is_in_range(int value, int lo, int hi) { michael@0: return lo <= value && value <= hi; michael@0: } michael@0: michael@0: bool Time::Exploded::HasValidValues() const { michael@0: return is_in_range(month, 1, 12) && michael@0: is_in_range(day_of_week, 0, 6) && michael@0: is_in_range(day_of_month, 1, 31) && michael@0: is_in_range(hour, 0, 23) && michael@0: is_in_range(minute, 0, 59) && michael@0: is_in_range(second, 0, 60) && michael@0: is_in_range(millisecond, 0, 999); michael@0: } michael@0: michael@0: } // namespace base