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