1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/time/time.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <CoreFoundation/CFDate.h> 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <CoreFoundation/CFTimeZone.h> 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <mach/mach.h> 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <mach/mach_time.h> 110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <stddef.h> 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <stdint.h> 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/sysctl.h> 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/time.h> 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <sys/types.h> 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <time.h> 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h" 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/mac/mach_logging.h" 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/mac/scoped_cftyperef.h" 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/mac/scoped_mach_port.h" 220d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/macros.h" 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/numerics/safe_conversions.h" 240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "build/build_config.h" 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint64_t ComputeCurrentTicks() { 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_IOS) 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // On iOS mach_absolute_time stops while the device is sleeping. Instead use 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // now - KERN_BOOTTIME to get a time difference that is not impacted by clock 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // changes. KERN_BOOTTIME will be updated by the system whenever the system 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // clock change. 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat struct timeval boottime; 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int mib[2] = {CTL_KERN, KERN_BOOTTIME}; 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t size = sizeof(boottime); 370c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez int kr = sysctl(mib, arraysize(mib), &boottime, &size, nullptr, 0); 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ(KERN_SUCCESS, kr); 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::TimeDelta time_difference = base::Time::Now() - 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (base::Time::FromTimeT(boottime.tv_sec) + 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::TimeDelta::FromMicroseconds(boottime.tv_usec)); 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return time_difference.InMicroseconds(); 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static mach_timebase_info_data_t timebase_info; 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (timebase_info.denom == 0) { 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Zero-initialization of statics guarantees that denom will be 0 before 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // calling mach_timebase_info. mach_timebase_info will never set denom to 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // 0 as that would be invalid, so the zero-check can be used to determine 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // whether mach_timebase_info has already been called. This is 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // recommended by Apple's QA1398. 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat kern_return_t kr = mach_timebase_info(&timebase_info); 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MACH_DCHECK(kr == KERN_SUCCESS, kr) << "mach_timebase_info"; 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // mach_absolute_time is it when it comes to ticks on the Mac. Other calls 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // with less precision (such as TickCount) just call through to 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // mach_absolute_time. 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // timebase_info converts absolute time tick units into nanoseconds. Convert 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // to microseconds up front to stave off overflows. 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::CheckedNumeric<uint64_t> result( 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat mach_absolute_time() / base::Time::kNanosecondsPerMicrosecond); 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat result *= timebase_info.numer; 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat result /= timebase_info.denom; 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Don't bother with the rollover handling that the Windows version does. 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // With numer and denom = 1 (the expected case), the 64-bit absolute time 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // reported in nanoseconds is enough to last nearly 585 years. 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return base::checked_cast<int64_t>(result.ValueOrDie()); 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(OS_IOS) 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratint64_t ComputeThreadTicks() { 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_IOS) 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NOTREACHED(); 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#else 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::mac::ScopedMachSendRight thread(mach_thread_self()); 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat mach_msg_type_number_t thread_info_count = THREAD_BASIC_INFO_COUNT; 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat thread_basic_info_data_t thread_info_data; 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (thread.get() == MACH_PORT_NULL) { 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DLOG(ERROR) << "Failed to get mach_thread_self()"; 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat kern_return_t kr = thread_info( 880d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko thread.get(), 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat THREAD_BASIC_INFO, 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat reinterpret_cast<thread_info_t>(&thread_info_data), 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat &thread_info_count); 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MACH_DCHECK(kr == KERN_SUCCESS, kr) << "thread_info"; 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::CheckedNumeric<int64_t> absolute_micros( 9594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez thread_info_data.user_time.seconds + 9694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez thread_info_data.system_time.seconds); 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat absolute_micros *= base::Time::kMicrosecondsPerSecond; 9894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez absolute_micros += (thread_info_data.user_time.microseconds + 9994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez thread_info_data.system_time.microseconds); 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return absolute_micros.ValueOrDie(); 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif // defined(OS_IOS) 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The Time routines in this file use Mach and CoreFoundation APIs, since the 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// POSIX definition of time_t in Mac OS X wraps around after 2038--and 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// there are already cookie expiration dates, etc., past that time out in 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// the field. Using CFDate prevents that problem, and using mach_absolute_time 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// for TimeTicks gives us nice high-resolution interval timing. 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Time ----------------------------------------------------------------------- 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Core Foundation uses a double second count since 2001-01-01 00:00:00 UTC. 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The UNIX epoch is 1970-01-01 00:00:00 UTC. 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Windows uses a Gregorian epoch of 1601. We need to match this internally 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// so that our time representations match across all platforms. See bug 14734. 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// irb(main):010:0> Time.at(0).getutc() 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// => Thu Jan 01 00:00:00 UTC 1970 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// irb(main):011:0> Time.at(-11644473600).getutc() 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// => Mon Jan 01 00:00:00 UTC 1601 1240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkostatic const int64_t kWindowsEpochDeltaSeconds = INT64_C(11644473600); 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 1270d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkoconst int64_t Time::kWindowsEpochDeltaMicroseconds = 128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Some functions in time.cc use time_t directly, so we provide an offset 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// to convert from time_t (Unix epoch) and internal (Windows epoch). 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 1330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkoconst int64_t Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTime Time::Now() { 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return FromCFAbsoluteTime(CFAbsoluteTimeGetCurrent()); 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTime Time::FromCFAbsoluteTime(CFAbsoluteTime t) { 1420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, 1430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko "CFAbsoluteTime must have an infinity value"); 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (t == 0) 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return Time(); // Consider 0 as a null Time. 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (t == std::numeric_limits<CFAbsoluteTime>::infinity()) 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return Max(); 1480d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return Time(static_cast<int64_t>((t + kCFAbsoluteTimeIntervalSince1970) * 1490d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko kMicrosecondsPerSecond) + 1500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko kWindowsEpochDeltaMicroseconds); 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratCFAbsoluteTime Time::ToCFAbsoluteTime() const { 1540d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko static_assert(std::numeric_limits<CFAbsoluteTime>::has_infinity, 1550d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko "CFAbsoluteTime must have an infinity value"); 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (is_null()) 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return 0; // Consider 0 as a null Time. 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (is_max()) 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return std::numeric_limits<CFAbsoluteTime>::infinity(); 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return (static_cast<CFAbsoluteTime>(us_ - kWindowsEpochDeltaMicroseconds) / 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat kMicrosecondsPerSecond) - kCFAbsoluteTimeIntervalSince1970; 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTime Time::NowFromSystemTime() { 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Just use Now() because Now() returns the system time. 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return Now(); 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 1710c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavezbool Time::FromExploded(bool is_local, const Exploded& exploded, Time* time) { 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( 17345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko is_local 17445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ? CFTimeZoneCopySystem() 17545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); 17645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( 17745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko kCFAllocatorDefault, kCFGregorianCalendar)); 17845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CFCalendarSetTimeZone(gregorian, time_zone); 17945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CFAbsoluteTime absolute_time; 18045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // 'S' is not defined in componentDesc in Apple documentation, but can be 18145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // found at http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c 18245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CFCalendarComposeAbsoluteTime( 18345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko gregorian, &absolute_time, "yMdHmsS", exploded.year, exploded.month, 18445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, 18545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko exploded.millisecond); 18645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CFAbsoluteTime seconds = absolute_time + kCFAbsoluteTimeIntervalSince1970; 1870c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 1880c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez base::Time converted_time = 1890c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez Time(static_cast<int64_t>(seconds * kMicrosecondsPerSecond) + 1900c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez kWindowsEpochDeltaMicroseconds); 1910c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 1920c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // If |exploded.day_of_month| is set to 31 1930c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // on a 28-30 day month, it will return the first day of the next month. 1940c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // Thus round-trip the time and compare the initial |exploded| with 1950c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez // |utc_to_exploded| time. 1960c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez base::Time::Exploded to_exploded; 1970c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez if (!is_local) 1980c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez converted_time.UTCExplode(&to_exploded); 1990c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez else 2000c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez converted_time.LocalExplode(&to_exploded); 2010c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 2020c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez if (ExplodedMostlyEquals(to_exploded, exploded)) { 2030c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez *time = converted_time; 2040c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez return true; 2050c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez } 2060c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 2070c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez *time = Time(0); 2080c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez return false; 209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid Time::Explode(bool is_local, Exploded* exploded) const { 212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Avoid rounding issues, by only putting the integral number of seconds 213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (rounded towards -infinity) into a |CFAbsoluteTime| (which is a |double|). 2140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko int64_t microsecond = us_ % kMicrosecondsPerSecond; 215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (microsecond < 0) 216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat microsecond += kMicrosecondsPerSecond; 217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat CFAbsoluteTime seconds = ((us_ - microsecond) / kMicrosecondsPerSecond) - 218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat kWindowsEpochDeltaSeconds - 219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat kCFAbsoluteTimeIntervalSince1970; 220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::ScopedCFTypeRef<CFTimeZoneRef> time_zone( 22245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko is_local 22345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ? CFTimeZoneCopySystem() 22445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko : CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, 0)); 22545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko base::ScopedCFTypeRef<CFCalendarRef> gregorian(CFCalendarCreateWithIdentifier( 22645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko kCFAllocatorDefault, kCFGregorianCalendar)); 22745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CFCalendarSetTimeZone(gregorian, time_zone); 22845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int second, day_of_week; 22945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // 'E' sets the day of week, but is not defined in componentDesc in Apple 23045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // documentation. It can be found in open source code here: 23145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // http://www.opensource.apple.com/source/CF/CF-855.17/CFCalendar.c 23245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko CFCalendarDecomposeAbsoluteTime(gregorian, seconds, "yMdHmsE", 23345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko &exploded->year, &exploded->month, 23445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko &exploded->day_of_month, &exploded->hour, 23545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko &exploded->minute, &second, &day_of_week); 236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Make sure seconds are rounded down towards -infinity. 23745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko exploded->second = floor(second); 23845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // |Exploded|'s convention for day of week is 0 = Sunday, i.e. different 23945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko // from CF's 1 = Sunday. 24045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko exploded->day_of_week = (day_of_week - 1) % 7; 241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Calculate milliseconds ourselves, since we rounded the |seconds|, making 242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // sure to round towards -infinity. 243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat exploded->millisecond = 244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (microsecond >= 0) ? microsecond / kMicrosecondsPerMillisecond : 245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (microsecond - kMicrosecondsPerMillisecond + 1) / 246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat kMicrosecondsPerMillisecond; 247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TimeTicks ------------------------------------------------------------------ 250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTimeTicks TimeTicks::Now() { 253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return TimeTicks(ComputeCurrentTicks()); 254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool TimeTicks::IsHighResolution() { 258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return true; 259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static 26294ffa55491333f3dcc701befd0d2652922916d99Luis Hector ChavezTimeTicks::Clock TimeTicks::GetClock() { 26394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#if defined(OS_IOS) 26494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME; 26594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#else 26694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return Clock::MAC_MACH_ABSOLUTE_TIME; 26794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#endif // defined(OS_IOS) 26894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez} 26994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 27094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez// static 271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratThreadTicks ThreadTicks::Now() { 272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return ThreadTicks(ComputeThreadTicks()); 273b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 274b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 275b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 276