Pioneer
Loading...
Searching...
No Matches
DateTime.h
Go to the documentation of this file.
1#ifndef DATETIME_H
2#define DATETIME_H
3
4#include <string>
5
6namespace Time {
7
8 // We separate lengths of time (TimeDelta) from points in time (DateTime),
9 // because they have different operations defined on them
10 //
11 // The TimeDelta constructor takes a TimeUnit parameter, so you specify
12 // a length of time with, e.g., Time::TimeDelta(42, Time::Day)
13 //
14 // TimeUnit is an enum (rather than a set of const TimeDelta values) because
15 // that ensures the compiler will treat the values as compile time constants
16 // instead of objects that must be defined in a translation unit and initialised.
17 //
18 // The base units are (currently) microseconds, which is chosen
19 // because it's plenty high enough resolution for most uses, and it's
20 // easily understandable, and it gives good range when stored in
21 // signed 64-bit integers (approx. +/- 292277 years)
22 //
23 // The base units can be trivially changed by modifying the TimeUnit enum.
24 //
25 // DateTime is mostly about dealing with the Gregorian calendar.
26 //
27 // These types have a fairly unsophisticated understanding of the calendar
28 // and the passage of time. For example, leap seconds are not supported at all.
29 // But... I'm pretty sure we don't need leap seconds for Pioneer.
30
31 enum TimeUnit : int64_t {
34 Second = 1000ll * Millisecond,
35 Minute = 60ll * Second,
36 Hour = 60ll * Minute,
37 Day = 24ll * Hour,
38 Week = 7ll * Day
39 };
40
41 class TimeDelta;
42 class DateTime;
43
44 class TimeDelta {
45 public:
47 m_delta(0) {}
48 explicit TimeDelta(int64_t t, TimeUnit unit = Second) :
49 m_delta(t * unit) {}
50
51 int64_t GetTotalWeeks() const { return (m_delta / Week); }
52 int64_t GetTotalDays() const { return (m_delta / Day); }
53 int64_t GetTotalHours() const { return (m_delta / Hour); }
54 int64_t GetTotalMinutes() const { return (m_delta / Minute); }
55 int64_t GetTotalSeconds() const { return (m_delta / Second); }
56 int64_t GetTotalMilliseconds() const { return (m_delta / Millisecond); }
57 int64_t GetTotalMicroseconds() const { return (m_delta / Microsecond); }
58
60 {
61 m_delta += x.m_delta;
62 return *this;
63 }
65 {
66 m_delta -= x.m_delta;
67 return *this;
68 }
69
70 friend TimeDelta operator+(const TimeDelta &a, const TimeDelta &b) { return TimeDelta(a.m_delta + b.m_delta, TimeUnit(1)); }
71 friend TimeDelta operator-(const TimeDelta &a, const TimeDelta &b) { return TimeDelta(a.m_delta - b.m_delta, TimeUnit(1)); }
72 friend TimeDelta operator*(int64_t x, const TimeDelta &t) { return TimeDelta(x * t.m_delta, TimeUnit(1)); }
73 friend TimeDelta operator/(const TimeDelta &t, int64_t x) { return TimeDelta(t.m_delta / x, TimeUnit(1)); }
74 friend int64_t operator/(const TimeDelta &a, const TimeDelta &b) { return (a.m_delta / b.m_delta); }
75
76 friend DateTime operator+(const DateTime &a, const TimeDelta &b);
77 friend DateTime operator-(const DateTime &a, const TimeDelta &b);
78
79 private:
80 friend class DateTime;
81 int64_t m_delta;
82 };
83
84 class DateTime {
85 public:
87 m_timestamp(-int64_t(24 * 60 * 60) * int64_t(400 * 365 + 97) * int64_t(Second)) {}
88 // month = 1 to 12
89 // day = 1 to N where N is the number of days in the specified month and year
90 DateTime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int microsecond = 0);
91 DateTime(double gameTime);
92
93 void GetDateParts(int *year, int *month, int *day) const;
94 void GetTimeParts(int *hour, int *minute, int *second, int *microsecond = nullptr) const;
95
96 double ToGameTime() const;
97 std::string ToDateString() const;
98 std::string ToTimeString() const;
99 std::string ToDateTimeString() const { return ToStringISO8601(); }
100 std::string ToStringISO8601() const;
101
102 friend TimeDelta operator-(const DateTime &a, const DateTime &b)
103 {
104 return TimeDelta(a.m_timestamp - b.m_timestamp, TimeUnit(1));
105 }
106 friend DateTime operator+(const DateTime &a, const TimeDelta &b)
107 {
108 return DateTime(a.m_timestamp + b.m_delta);
109 }
110 friend DateTime operator-(const DateTime &a, const TimeDelta &b)
111 {
112 return DateTime(a.m_timestamp - b.m_delta);
113 }
114 friend DateTime operator+(const TimeDelta &a, const DateTime &b) { return (b + a); }
115
117 {
118 m_timestamp += x.m_delta;
119 return *this;
120 }
122 {
123 m_timestamp -= x.m_delta;
124 return *this;
125 }
126
127 friend bool operator<(const DateTime &a, const DateTime &b) { return (a.m_timestamp < b.m_timestamp); }
128 friend bool operator<=(const DateTime &a, const DateTime &b) { return (a.m_timestamp <= b.m_timestamp); }
129 friend bool operator==(const DateTime &a, const DateTime &b) { return (a.m_timestamp == b.m_timestamp); }
130 friend bool operator!=(const DateTime &a, const DateTime &b) { return (a.m_timestamp != b.m_timestamp); }
131 friend bool operator>(const DateTime &a, const DateTime &b) { return (a.m_timestamp > b.m_timestamp); }
132 friend bool operator>=(const DateTime &a, const DateTime &b) { return (a.m_timestamp >= b.m_timestamp); }
133
134 int64_t GetTimestamp() const { return m_timestamp; }
135
136 private:
137 explicit DateTime(int64_t tstamp) :
138 m_timestamp(tstamp) {}
139
140 // The timestamp is the number of microseconds since the epoch (2001-01-01T00:00:00Z)
141 //
142 // This epoch (the start of the year 2001) is chosen because it makes counting
143 // leap years easier (see DateTime constructor from date components)
144 //
145 // However, these are *not* SI microseconds, they are mean solar microseconds.
146 // SI microseconds are defined in terms of the behaviour of the caesium atom.
147 // Mean solar microseconds are defined in terms of the rotation of the Earth.
148 // This means that there are always precisely 86400 * 10^6 mean solar microseconds in each day.
149 // Since every day contains precisely the same number of mean solar microseconds, it is practical
150 // to compute the number of mean solar microseconds between any two dates (specified
151 // according to the Gregorian calendar) or to compute a date from a timestamp.
152 //
153 // If we used SI microseconds, we would need to know all past and future leap seconds to be able to correctly
154 // convert between the timestamp value and a year-month-day-hour-minute-second-microsecond tuple.
155 // Apart from making the calculations a pain in the ass, that is actually impossible for dates in the future,
156 // because leap seconds are not predictable (they're introduced as necessary based on astronomical observations)
157 //
158 // (Incidentally, this is the way all integer timestamps work, at least all the ones I've ever seen)
159 int64_t m_timestamp; // (units: microseconds; 0 means 2001-01-01T00:00:00Z)
160 };
161
162} // namespace Time
163
164#endif
Definition DateTime.h:84
DateTime & operator+=(const TimeDelta &x)
Definition DateTime.h:116
DateTime & operator-=(const TimeDelta &x)
Definition DateTime.h:121
friend bool operator==(const DateTime &a, const DateTime &b)
Definition DateTime.h:129
std::string ToTimeString() const
Definition DateTime.cpp:194
friend DateTime operator+(const TimeDelta &a, const DateTime &b)
Definition DateTime.h:114
friend bool operator!=(const DateTime &a, const DateTime &b)
Definition DateTime.h:130
friend DateTime operator+(const DateTime &a, const TimeDelta &b)
Definition DateTime.h:106
friend DateTime operator-(const DateTime &a, const TimeDelta &b)
Definition DateTime.h:110
std::string ToStringISO8601() const
Definition DateTime.cpp:203
friend bool operator>=(const DateTime &a, const DateTime &b)
Definition DateTime.h:132
int64_t GetTimestamp() const
Definition DateTime.h:134
DateTime()
Definition DateTime.h:86
std::string ToDateTimeString() const
Definition DateTime.h:99
void GetDateParts(int *year, int *month, int *day) const
Definition DateTime.cpp:96
friend bool operator<(const DateTime &a, const DateTime &b)
Definition DateTime.h:127
void GetTimeParts(int *hour, int *minute, int *second, int *microsecond=nullptr) const
Definition DateTime.cpp:149
double ToGameTime() const
Definition DateTime.cpp:174
friend bool operator<=(const DateTime &a, const DateTime &b)
Definition DateTime.h:128
friend TimeDelta operator-(const DateTime &a, const DateTime &b)
Definition DateTime.h:102
friend bool operator>(const DateTime &a, const DateTime &b)
Definition DateTime.h:131
std::string ToDateString() const
Definition DateTime.cpp:185
Definition DateTime.h:44
friend TimeDelta operator-(const TimeDelta &a, const TimeDelta &b)
Definition DateTime.h:71
int64_t GetTotalDays() const
Definition DateTime.h:52
int64_t GetTotalWeeks() const
Definition DateTime.h:51
int64_t GetTotalHours() const
Definition DateTime.h:53
int64_t GetTotalMicroseconds() const
Definition DateTime.h:57
friend DateTime operator+(const DateTime &a, const TimeDelta &b)
TimeDelta & operator+=(const TimeDelta &x)
Definition DateTime.h:59
friend DateTime operator-(const DateTime &a, const TimeDelta &b)
friend TimeDelta operator+(const TimeDelta &a, const TimeDelta &b)
Definition DateTime.h:70
friend TimeDelta operator*(int64_t x, const TimeDelta &t)
Definition DateTime.h:72
friend int64_t operator/(const TimeDelta &a, const TimeDelta &b)
Definition DateTime.h:74
TimeDelta(int64_t t, TimeUnit unit=Second)
Definition DateTime.h:48
friend TimeDelta operator/(const TimeDelta &t, int64_t x)
Definition DateTime.h:73
TimeDelta & operator-=(const TimeDelta &x)
Definition DateTime.h:64
int64_t GetTotalSeconds() const
Definition DateTime.h:55
TimeDelta()
Definition DateTime.h:46
int64_t GetTotalMinutes() const
Definition DateTime.h:54
int64_t GetTotalMilliseconds() const
Definition DateTime.h:56
Definition DateTime.h:6
TimeUnit
Definition DateTime.h:31
@ Second
Definition DateTime.h:34
@ Millisecond
Definition DateTime.h:33
@ Minute
Definition DateTime.h:35
@ Microsecond
Definition DateTime.h:32
@ Hour
Definition DateTime.h:36
@ Week
Definition DateTime.h:38
@ Day
Definition DateTime.h:37