1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2008 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <CoreFoundation/CFDate.h> 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <CoreFoundation/CFTimeZone.h> 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <mach/mach_time.h> 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sys/time.h> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <time.h> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_cftyperef.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The Time routines in this file use Mach and CoreFoundation APIs, since the 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// POSIX definition of time_t in Mac OS X wraps around after 2038--and 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// there are already cookie expiration dates, etc., past that time out in 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the field. Using CFDate prevents that problem, and using mach_absolute_time 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for TimeTicks gives us nice high-resolution interval timing. 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Time ----------------------------------------------------------------------- 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Core Foundation uses a double second count since 2001-01-01 00:00:00 UTC. 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The UNIX epoch is 1970-01-01 00:00:00 UTC. 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Windows uses a Gregorian epoch of 1601. We need to match this internally 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// so that our time representations match across all platforms. See bug 14734. 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// irb(main):010:0> Time.at(0).getutc() 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// => Thu Jan 01 00:00:00 UTC 1970 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// irb(main):011:0> Time.at(-11644473600).getutc() 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// => Mon Jan 01 00:00:00 UTC 1601 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int64 kWindowsEpochDeltaSeconds = GG_INT64_C(11644473600); 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int64 kWindowsEpochDeltaMilliseconds = 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kWindowsEpochDeltaSeconds * Time::kMillisecondsPerSecond; 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int64 Time::kWindowsEpochDeltaMicroseconds = 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kWindowsEpochDeltaSeconds * Time::kMicrosecondsPerSecond; 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Some functions in time.cc use time_t directly, so we provide an offset 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to convert from time_t (Unix epoch) and internal (Windows epoch). 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int64 Time::kTimeTToMicrosecondsOffset = kWindowsEpochDeltaMicroseconds; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTime Time::Now() { 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFAbsoluteTime now = 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970; 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Time(static_cast<int64>(now * kMicrosecondsPerSecond) + 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kWindowsEpochDeltaMicroseconds); 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTime Time::NowFromSystemTime() { 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Just use Now() because Now() returns the system time. 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Now(); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTime Time::FromExploded(bool is_local, const Exploded& exploded) { 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFGregorianDate date; 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date.second = exploded.second + 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded.millisecond / static_cast<double>(kMillisecondsPerSecond); 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date.minute = exploded.minute; 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date.hour = exploded.hour; 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date.day = exploded.day_of_month; 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date.month = exploded.month; 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date.year = exploded.year; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::mac::ScopedCFTypeRef<CFTimeZoneRef> 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time_zone(is_local ? CFTimeZoneCopySystem() : NULL); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFAbsoluteTime seconds = CFGregorianDateGetAbsoluteTime(date, time_zone) + 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kCFAbsoluteTimeIntervalSince1970; 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Time(static_cast<int64>(seconds * kMicrosecondsPerSecond) + 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kWindowsEpochDeltaMicroseconds); 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid Time::Explode(bool is_local, Exploded* exploded) const { 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFAbsoluteTime seconds = 834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ((static_cast<double>(us_) - kWindowsEpochDeltaMicroseconds) / 844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch kMicrosecondsPerSecond) - kCFAbsoluteTimeIntervalSince1970; 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::mac::ScopedCFTypeRef<CFTimeZoneRef> 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time_zone(is_local ? CFTimeZoneCopySystem() : NULL); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CFGregorianDate date = CFAbsoluteTimeGetGregorianDate(seconds, time_zone); 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->year = date.year; 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->month = date.month; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->day_of_month = date.day; 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->hour = date.hour; 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->minute = date.minute; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->second = date.second; 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott exploded->millisecond = 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<int>(date.second * kMillisecondsPerSecond) % 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kMillisecondsPerSecond; 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TimeTicks ------------------------------------------------------------------ 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTimeTicks TimeTicks::Now() { 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint64_t absolute_micro; 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static mach_timebase_info_data_t timebase_info; 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (timebase_info.denom == 0) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Zero-initialization of statics guarantees that denom will be 0 before 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // calling mach_timebase_info. mach_timebase_info will never set denom to 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 0 as that would be invalid, so the zero-check can be used to determine 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // whether mach_timebase_info has already been called. This is 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // recommended by Apple's QA1398. 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kern_return_t kr = mach_timebase_info(&timebase_info); 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(kr == KERN_SUCCESS); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // mach_absolute_time is it when it comes to ticks on the Mac. Other calls 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // with less precision (such as TickCount) just call through to 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // mach_absolute_time. 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // timebase_info converts absolute time tick units into nanoseconds. Convert 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to microseconds up front to stave off overflows. 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott absolute_micro = mach_absolute_time() / Time::kNanosecondsPerMicrosecond * 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timebase_info.numer / timebase_info.denom; 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Don't bother with the rollover handling that the Windows version does. 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // With numer and denom = 1 (the expected case), the 64-bit absolute time 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // reported in nanoseconds is enough to last nearly 585 years. 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TimeTicks(absolute_micro); 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTimeTicks TimeTicks::HighResNow() { 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Now(); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 140