DotNetDupe 4.0.6
C++17/20 Implementation of the .NET Base Class Library (BCL)
Loading...
Searching...
No Matches
TimeProvider.cpp
Go to the documentation of this file.
1#include "pch.h"
3
4#if defined(_WIN32)
5#include <windows.h>
6#else
7#include <chrono>
8#endif
9
10namespace DotNetDupe {
11 namespace System {
12
13 class SystemTimeProvider : public TimeProvider {
14 public:
15 DateTimeOffset GetUtcNow() const override {
17#if defined(_WIN32)
18 FILETIME ft;
19 GetSystemTimePreciseAsFileTime(&ft);
20 int64_t ticks = (((int64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
21 // Windows FILETIME starts from 1601-01-01, .NET Ticks start from 0001-01-01.
22 // Difference is 504911232000000000 ticks.
23 return DateTimeOffset(ticks + 504911232000000000LL);
24#else
25 auto now = std::chrono::system_clock::now();
26 auto duration = now.time_since_epoch();
27 auto ticks = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() / 100;
28 // Unix epoch is 1970-01-01. .NET Ticks start from 0001-01-01.
29 // Difference is 621355968000000000 ticks.
30 return DateTimeOffset(ticks + 621355968000000000LL);
31#endif
32 }
33
34 DateTimeOffset GetLocalNow() const override {
36#if defined(_WIN32)
37 SYSTEMTIME st;
38 GetLocalTime(&st);
39 FILETIME ft;
40 SystemTimeToFileTime(&st, &ft);
41 int64_t ticks = (((int64_t)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
42 return DateTimeOffset(ticks + 504911232000000000LL);
43#else
44 // Simple implementation for local now on POSIX
45 return GetUtcNow(); // TODO: Add offset
46#endif
47 }
48
49 int64_t GetTimestamp() const override {
51#if defined(_WIN32)
52 LARGE_INTEGER li;
53 QueryPerformanceCounter(&li);
54 return li.QuadPart;
55#else
56 auto now = std::chrono::steady_clock::now();
57 return std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
58#endif
59 }
60
61 int64_t GetTimestampFrequency() const override {
63#if defined(_WIN32)
64 LARGE_INTEGER li;
65 QueryPerformanceFrequency(&li);
66 return li.QuadPart;
67#else
68 return 1000000000LL; // Nanoseconds
69#endif
70 }
71 };
72
73 TimeSpan TimeProvider::GetElapsedTime(int64_t startingTimestamp) const {
75 return GetElapsedTime(startingTimestamp, GetTimestamp());
76 }
77
78 TimeSpan TimeProvider::GetElapsedTime(int64_t startingTimestamp, int64_t endingTimestamp) const {
80 double ticks = (double)(endingTimestamp - startingTimestamp) * TimeSpan::TicksPerSecond / GetTimestampFrequency();
81 return TimeSpan((int64_t)ticks);
82 }
83
86 static auto s_spSystem = SmartPointer<SystemTimeProvider>::NewShared();
87 return s_spSystem.template DynamicCast<TimeProvider>();
88 }
89 }
90}
Provides an abstraction for time, timestamps, and elapsed time calculation.
DateTimeOffset()
Initializes a new instance of DateTimeOffset to 0 ticks.
static SmartPointer< T > NewShared()
Creates a Shared SmartPointer, default constructing T.
An abstraction that provides time-related functions to enable testability of time-dependent code.
TimeSpan GetElapsedTime(int64_t startingTimestamp) const
Gets the elapsed time since the startingTimestamp was recorded.
static TimeProviderPtr GetSystem()
Gets a TimeProvider that provides the system's current time and high-resolution timer.
virtual int64_t GetTimestampFrequency() const =0
Gets the frequency of the high-frequency counter in ticks per second.
virtual int64_t GetTimestamp() const =0
Gets the current high-frequency counter value in ticks.
Represents a time interval (duration of time or elapsed time) measured as a positive or negative numb...
Definition TimeSpan.h:20
static constexpr int64_t TicksPerSecond
The number of ticks in 1 second.
Definition TimeSpan.h:26
TimeSpan()
Initializes a new instance of TimeSpan to zero duration.
Definition TimeSpan.h:38
SmartPointer< TimeProvider > TimeProviderPtr
Alias for a smart pointer to a TimeProvider.
SmartPointer< To > DynamicCast(const SmartPointer< From > &sp)