1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkOncePtr.h"
9 #include "SkString.h"
10 #include "SkTime.h"
11 #include "SkTypes.h"
12 
toISO8601(SkString * dst) const13 void SkTime::DateTime::toISO8601(SkString* dst) const {
14     if (dst) {
15         int timeZoneMinutes = SkToInt(fTimeZoneMinutes);
16         char timezoneSign = timeZoneMinutes >= 0 ? '+' : '-';
17         int timeZoneHours = SkTAbs(timeZoneMinutes) / 60;
18         timeZoneMinutes = SkTAbs(timeZoneMinutes) % 60;
19         dst->printf("%04u-%02u-%02uT%02u:%02u:%02u%c%02d:%02d",
20                     static_cast<unsigned>(fYear), static_cast<unsigned>(fMonth),
21                     static_cast<unsigned>(fDay), static_cast<unsigned>(fHour),
22                     static_cast<unsigned>(fMinute),
23                     static_cast<unsigned>(fSecond), timezoneSign, timeZoneHours,
24                     timeZoneMinutes);
25     }
26 }
27 
28 
29 #ifdef SK_BUILD_FOR_WIN32
30 
31 #include "Windows.h"
GetDateTime(DateTime * dt)32 void SkTime::GetDateTime(DateTime* dt) {
33     if (dt) {
34         SYSTEMTIME st;
35         GetSystemTime(&st);
36         dt->fTimeZoneMinutes = 0;
37         dt->fYear       = st.wYear;
38         dt->fMonth      = SkToU8(st.wMonth);
39         dt->fDayOfWeek  = SkToU8(st.wDayOfWeek);
40         dt->fDay        = SkToU8(st.wDay);
41         dt->fHour       = SkToU8(st.wHour);
42         dt->fMinute     = SkToU8(st.wMinute);
43         dt->fSecond     = SkToU8(st.wSecond);
44     }
45 }
46 
47 #else // SK_BUILD_FOR_WIN32
48 
49 #include <time.h>
GetDateTime(DateTime * dt)50 void SkTime::GetDateTime(DateTime* dt) {
51     if (dt) {
52         time_t m_time;
53         time(&m_time);
54         struct tm* tstruct;
55         tstruct = gmtime(&m_time);
56         dt->fTimeZoneMinutes = 0;
57         dt->fYear       = tstruct->tm_year + 1900;
58         dt->fMonth      = SkToU8(tstruct->tm_mon + 1);
59         dt->fDayOfWeek  = SkToU8(tstruct->tm_wday);
60         dt->fDay        = SkToU8(tstruct->tm_mday);
61         dt->fHour       = SkToU8(tstruct->tm_hour);
62         dt->fMinute     = SkToU8(tstruct->tm_min);
63         dt->fSecond     = SkToU8(tstruct->tm_sec);
64     }
65 }
66 #endif // SK_BUILD_FOR_WIN32
67 
68 #if defined(_MSC_VER)
69     // TODO: try std::chrono again with MSVC 2015?
70     #include <intrin.h>
71     SK_DECLARE_STATIC_ONCE_PTR(double, ns_per_tick);
GetNSecs()72     double SkTime::GetNSecs() {
73         uint64_t ticks = __rdtsc();
74         return ticks * *ns_per_tick.get([]{
75             LARGE_INTEGER khz;  // The docs say this returns Hz, but it returns KHz.
76             QueryPerformanceFrequency(&khz);
77             return new double(1e6 / khz.QuadPart);
78         });
79     }
80 #elif defined(__MACH__)
81     // TODO: fold into std::chrono when available?
82     #include <mach/mach_time.h>
83     SK_DECLARE_STATIC_ONCE_PTR(double, ns_per_tick);
GetNSecs()84     double SkTime::GetNSecs() {
85         uint64_t ticks = mach_absolute_time();
86         return ticks * *ns_per_tick.get([]{
87             mach_timebase_info_data_t timebase;
88             (void)mach_timebase_info(&timebase);
89             return new double(timebase.numer * 1.0 / timebase.denom);
90         });
91     }
92 #else
93     // This std::chrono code looks great on Linux and Android,
94     // but MSVC 2013 returned mostly garbage (0ns times, etc).
95     #include <chrono>
GetNSecs()96     double SkTime::GetNSecs() {
97         auto now = std::chrono::high_resolution_clock::now();
98         std::chrono::duration<double, std::nano> ns = now.time_since_epoch();
99         return ns.count();
100     }
101 #endif
102