88
99#pragma once
1010
11- #include < stdexcept >
11+ #include < chrono >
1212#include < string>
1313
1414namespace Azure { namespace Core {
@@ -17,28 +17,25 @@ namespace Azure { namespace Core {
1717 */
1818 class DateTime {
1919 public:
20- // / A type that represents tick spans.
21- typedef uint64_t IntervalType;
22-
23- private:
24- // Number of seconds between 01-01-1970 and 01-01-1601.
25- static constexpr IntervalType WindowsToPosixOffsetSeconds = 11644473600LL ;
20+ /* *
21+ * @brief Units of measurement the difference between instances of @DateTime.
22+ */
23+ // 1 == 100 ns (1 / 10,000,000 of a second, 7 fractional digits).
24+ typedef std::chrono::duration<int64_t , std::ratio<1 , 10000000 >> Duration;
2625
27- public:
2826 /* *
29- * @brief Defines the format applied to the fraction part from any @DateFormat
30- *
27+ * @brief Defines the format applied to the fraction part of any @DateTime.
3128 */
3229 enum class TimeFractionFormat
3330 {
34- // / Decimals are not included when there are no decimals in the source Datetime and any zeros
35- // / from the right are also removed.
31+ // / Include only meaningful fractional time digits, up to and excluding trailing zeroes.
3632 DropTrailingZeros,
3733
38- // / Decimals are included for any Datetime.
34+ // / Include all the fractional time digits up to maximum precision, even if the entire value
35+ // / is zero.
3936 AllDigits,
4037
41- // / Decimals are removed for any Datetime .
38+ // / Drop all the fractional time digits .
4239 Truncate
4340 };
4441
@@ -50,170 +47,193 @@ namespace Azure { namespace Core {
5047 // / RFC 1123.
5148 Rfc1123,
5249
53- // / ISO 8601 .
54- Iso8601 ,
50+ // / RFC 3339 .
51+ Rfc3339 ,
5552 };
5653
5754 /* *
5855 * @brief Get the current UTC time.
5956 */
60- static DateTime UtcNow ();
61-
62- // / An invalid UTC timestamp value.
63- static constexpr IntervalType UtcTimestampInvalid = static_cast <IntervalType>(-1 );
64-
65- /* *
66- * @brief Get seconds since Unix/POSIX time epoch at `01-01-1970 00:00:00`.
67- * If time is before epoch, @UtcTimestampInvalid is returned.
68- */
69- static IntervalType UtcTimestamp ()
70- {
71- auto const seconds = UtcNow ().ToInterval () / WindowsToPosixOffsetSeconds;
72- return (seconds >= WindowsToPosixOffsetSeconds) ? (seconds - WindowsToPosixOffsetSeconds)
73- : UtcTimestampInvalid;
74- }
57+ static DateTime Now ();
7558
7659 /* *
77- * @brief Construct an uninitialized (!@IsInitialized()) instance of @DateTime.
60+ * @brief Construct an instance of @DateTime.
61+ *
62+ * @param year Year.
63+ * @param month Month.
64+ * @param day Day.
65+ * @param hour Hour.
66+ * @param minute Minute.
67+ * @param second Seconds.
68+ *
69+ * @throw std::invalid_argument If any parameter is invalid.
7870 */
79- DateTime () : m_interval(0 ) {}
71+ explicit DateTime (
72+ int16_t year,
73+ int8_t month = 1 ,
74+ int8_t day = 1 ,
75+ int8_t hour = 0 ,
76+ int8_t minute = 0 ,
77+ int8_t second = 0 );
8078
8179 /* *
8280 * @brief Create @DateTime from a string representing time in UTC in the specified format.
8381 *
84- * @param timeString A string with the date and time.
85- * @param format A format to which /p timeString adheres to.
82+ * @param dateTime A string with the date and time.
83+ * @param format A format to which \p dateTime string adheres to.
8684 *
87- * @return @DateTime that was constructed from the \p timeString; Uninitialized
88- * (!@IsInitialized()) @DateTime if parsing \p timeString was not successful.
85+ * @return @DateTime that was constructed from the \p dateTime string.
8986 *
90- * @throw DateTimeException If \p format is not recognized.
87+ * @throw std::invalid_argument If \p format is not recognized, or if parsing error .
9188 */
92- static DateTime FromString (
93- std::string const & timeString,
94- DateFormat format = DateFormat::Rfc1123);
89+ static DateTime Parse (std::string const & dateTime, DateFormat format);
9590
9691 private:
9792 /* *
9893 * @brief Get a string representation of the @DateTime.
9994 *
10095 * @param format The representation format to use.
10196 * @param fractionFormat The format for the fraction part of the Datetime. Only supported by
102- * ISO8601
97+ * RFC 3339.
10398 *
104- * @throw DateTimeException If year exceeds 9999, or if \p format is not recognized.
99+ * @throw std::length_error If year exceeds 9999, or if \p format is not recognized.
105100 */
106- std::string ToString (DateFormat format, TimeFractionFormat fractionFormat) const ;
101+ std::string GetString (DateFormat format, TimeFractionFormat fractionFormat) const ;
107102
108103 public:
109104 /* *
110105 * @brief Get a string representation of the @DateTime.
111106 *
112107 * @param format The representation format to use.
113108 *
114- * @throw DateTimeException If year exceeds 9999, or if \p format is not recognized.
109+ * @throw std::length_error If year exceeds 9999, or if \p format is not recognized.
115110 */
116- std::string ToString (DateFormat format = DateFormat::Rfc1123 ) const
111+ std::string GetString (DateFormat format) const
117112 {
118- return ToString (format, TimeFractionFormat::DropTrailingZeros);
113+ return GetString (format, TimeFractionFormat::DropTrailingZeros);
119114 };
120115
121116 /* *
122- * @brief Get a string representation of the @DateTime formated with ISO8601 .
117+ * @brief Get a string representation of the @DateTime formatted with RFC 3339 .
123118 *
124- * @param fractionFormat The format that is applied to the fraction part from the ISO8601 date.
119+ * @param fractionFormat The format that is applied to the fraction part from the RFC 3339 date.
125120 *
126- * @throw DateTimeException If year exceeds 9999, or if \p fractionFormat is not recognized.
121+ * @throw std::length_error If year exceeds 9999.
122+ * @throw std::invalid_argument If \p format is not recognized.
127123 */
128- std::string ToIso8601String (TimeFractionFormat fractionFormat) const
124+ std::string GetRfc3339String (TimeFractionFormat fractionFormat) const
129125 {
130- return ToString (DateFormat::Iso8601 , fractionFormat);
126+ return GetString (DateFormat::Rfc3339 , fractionFormat);
131127 };
132128
133- // / Get the integral time value.
134- IntervalType ToInterval () const { return m_interval; }
135-
136- // / Subtract an interval from @DateTime.
137- DateTime operator -(IntervalType value) const { return DateTime (m_interval - value); }
129+ /* *
130+ * @brief Add \p duration to this @DateTime.
131+ * @param duration @Duration to add.
132+ * @return Reference to this @DateTime.
133+ */
134+ DateTime& operator +=(Duration const & duration)
135+ {
136+ m_since1601 += duration;
137+ return *this ;
138+ }
138139
139- // / Add an interval to @DateTime.
140- DateTime operator +(IntervalType value) const { return DateTime (m_interval + value); }
140+ /* *
141+ * @brief Subtract \p duration from this @DateTime.
142+ * @param duration @Duration to subtract from this @DateTime.
143+ * @return Reference to this @DateTime.
144+ */
145+ DateTime& operator -=(Duration const & duration)
146+ {
147+ m_since1601 -= duration;
148+ return *this ;
149+ }
141150
142- // / Compare two instances of @DateTime for equality.
143- bool operator ==(DateTime dt) const { return m_interval == dt.m_interval ; }
151+ /* *
152+ * @brief Subtract @Duration from @DateTime.
153+ * @param duration @Duration to subtract from this @DateTime.
154+ * @return New DateTime representing subtraction result.
155+ */
156+ DateTime operator -(Duration const & duration) const { return DateTime (m_since1601 - duration); }
144157
145- // / Compare two instances of @DateTime for inequality.
146- bool operator !=(const DateTime& dt) const { return !(*this == dt); }
158+ /* *
159+ * @brief Add @Duration to @DateTime.
160+ * @param duration @Duration to add to this @DateTime.
161+ * @return New DateTime representing addition result.
162+ */
163+ DateTime operator +(Duration const & duration) const { return DateTime (m_since1601 + duration); }
147164
148- // / Compare the chronological order of two @DateTime instances.
149- bool operator >(const DateTime& dt) const { return this ->m_interval > dt.m_interval ; }
165+ /* *
166+ * @brief Get @Duration between two instances of @DateTime.
167+ * @param other @DateTime to subtract from this @DateTime.
168+ * @return @Duration between this @DateTime and the \p other.
169+ */
170+ Duration operator -(DateTime const & other) const { return m_since1601 - other.m_since1601 ; }
150171
151- // / Compare the chronological order of two @DateTime instances.
152- bool operator <(const DateTime& dt) const { return this ->m_interval < dt.m_interval ; }
172+ /* *
173+ * @brief Compare with \p other @DateTime for equality.
174+ * @param other Other @DateTime to compare with.
175+ * @return `true` if @DateTime instances are equal, `false` otherwise.
176+ */
177+ constexpr bool operator ==(DateTime const & other) const
178+ {
179+ return m_since1601 == other.m_since1601 ;
180+ }
153181
154- // / Compare the chronological order of two @DateTime instances.
155- bool operator >=(const DateTime& dt) const { return this ->m_interval >= dt.m_interval ; }
182+ /* *
183+ * @brief Compare with \p other @DateTime for inequality.
184+ * @param other Other @DateTime to compare with.
185+ * @return `true` if @DateTime instances are not equal, `false` otherwise.
186+ */
187+ constexpr bool operator !=(const DateTime& other) const { return !(*this == other); }
156188
157- // / Compare the chronological order of two @DateTime instances.
158- bool operator <=(const DateTime& dt) const { return this ->m_interval <= dt.m_interval ; }
189+ /* *
190+ * @brief Check if \p other @DateTime precedes this @DateTime chronologically.
191+ * @param other @DateTime to compare with.
192+ * @return `true` if the \p other @DateTime precedes this, `false` otherwise.
193+ */
194+ constexpr bool operator >(const DateTime& other) const { return !(*this <= other); }
159195
160- // / Create an interval from milliseconds.
161- static IntervalType FromMilliseconds (unsigned int milliseconds)
196+ /* *
197+ * @brief Check if \p other @DateTime is chronologically after this @DateTime.
198+ * @param other @DateTime to compare with.
199+ * @return `true` if the \p other @DateTime is chonologically after this @DateTime, `false`
200+ * otherwise.
201+ */
202+ constexpr bool operator <(const DateTime& other) const
162203 {
163- return milliseconds * TicksPerMillisecond ;
204+ return this -> m_since1601 < other. m_since1601 ;
164205 }
165206
166- // / Create an interval from seconds.
167- static IntervalType FromSeconds ( unsigned int seconds) { return seconds * TicksPerSecond; }
168-
169- // / Create an interval from minutes .
170- static IntervalType FromMinutes ( unsigned int minutes) { return minutes * TicksPerMinute; }
171-
172- // / Create an interval from hours.
173- static IntervalType FromHours ( unsigned int hours) { return hours * TicksPerHour ; }
207+ /* *
208+ * @brief Check if \p other @DateTime precedes this @DateTime chronologically, or is equal to
209+ * it.
210+ * @param other @DateTime to compare with .
211+ * @return `true` if the \p other @DateTime precedes or is equal to this @DateTime, `false`
212+ * otherwise.
213+ */
214+ constexpr bool operator >=( const DateTime& other) const { return !(* this < other) ; }
174215
175- // / Create an interval from days.
176- static IntervalType FromDays (unsigned int days) { return days * TicksPerDay; }
216+ /* *
217+ * @brief Check if \p other @DateTime is chronologically after or equal to this @DateTime.
218+ * @param other @DateTime to compare with.
219+ * @return `true` if the \p other @DateTime is chonologically after or equal to this @DateTime,
220+ * `false` otherwise.
221+ */
222+ constexpr bool operator <=(const DateTime& other) const
223+ {
224+ return (*this == other) || (*this < other);
225+ }
177226
178- // / Checks whether this instance of @DateTime is initialized.
179- bool IsInitialized () const { return m_interval != 0 ; }
227+ /* *
228+ * @brief Get this @DateTime representation as a @Duration from the start of the
229+ * implementation-defined epoch.
230+ * @return @Duration since the start of the implementation-defined epoch.
231+ */
232+ constexpr explicit operator Duration () const { return m_since1601; }
180233
181234 private:
182- friend IntervalType operator -(DateTime t1, DateTime t2);
183-
184- static constexpr IntervalType TicksPerMillisecond = static_cast <IntervalType>(10000 );
185- static constexpr IntervalType TicksPerSecond = 1000 * TicksPerMillisecond;
186- static constexpr IntervalType TicksPerMinute = 60 * TicksPerSecond;
187- static constexpr IntervalType TicksPerHour = 60 * TicksPerMinute;
188- static constexpr IntervalType TicksPerDay = 24 * TicksPerHour;
189-
190235 // Private constructor. Use static methods to create an instance.
191- DateTime (IntervalType interval) : m_interval(interval) {}
192-
193- // Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
194- IntervalType m_interval;
195- };
196-
197- inline DateTime::IntervalType operator -(DateTime t1, DateTime t2)
198- {
199- auto diff = (t1.m_interval - t2.m_interval );
200-
201- // Round it down to seconds
202- diff /= DateTime::TicksPerSecond;
203-
204- return static_cast <DateTime::IntervalType>(diff);
205- }
206-
207- /* *
208- * @brief An exception that gets thrown when @DateTime error occurs.
209- */
210- class DateTimeException : public std ::runtime_error {
211- public:
212- /* *
213- * @brief Construct with message string.
214- *
215- * @param msg Message string.
216- */
217- explicit DateTimeException (std::string const & msg) : std::runtime_error(msg) {}
236+ explicit DateTime (Duration const & since1601) : m_since1601(since1601) {}
237+ Duration m_since1601;
218238 };
219239}} // namespace Azure::Core
0 commit comments