3 #include "../conversion/stringbuilder.h" 4 #include "../conversion/stringconversion.h" 14 const int DateTime::m_daysPerYear = 365;
15 const int DateTime::m_daysPer4Years = 1461;
16 const int DateTime::m_daysPer100Years = 36524;
17 const int DateTime::m_daysPer400Years = 146097;
18 const int DateTime::m_daysTo1601 = 584388;
19 const int DateTime::m_daysTo1899 = 693593;
20 const int DateTime::m_daysTo10000 = 3652059;
21 const int DateTime::m_daysToMonth365[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
22 const int DateTime::m_daysToMonth366[13] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
23 const int DateTime::m_daysInMonth365[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
24 const int DateTime::m_daysInMonth366[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
26 template <
typename num1,
typename num2,
typename num3> constexpr
bool inRangeInclMax(num1 val, num2
min, num3
max)
28 return (val) >= (
min) && (val) <= (
max);
31 template <
typename num1,
typename num2,
typename num3> constexpr
bool inRangeExclMax(num1 val, num2
min, num3
max)
33 return (val) >= (
min) && (val) < (
max);
59 DateTime DateTime::fromTimeStamp(time_t timeStamp)
62 struct tm *timeinfo = localtime(&timeStamp);
63 return DateTime::fromDateAndTime(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min,
64 timeinfo->tm_sec < 60 ? timeinfo->tm_sec : 59, 0);
73 DateTime DateTime::fromTimeStampGmt(time_t timeStamp)
75 return DateTime(DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(timeStamp) * TimeSpan::m_ticksPerSecond);
89 int values[6] = { 0 };
90 int *
const dayIndex = values + 2;
91 int *
const secondsIndex = values + 5;
92 int *valueIndex = values;
93 int *
const valuesEnd = values + 7;
94 double miliSecondsFact = 100.0, miliSeconds = 0.0;
95 for (
const char *strIndex = str;; ++strIndex) {
96 const char c = *strIndex;
97 if (c <= '9' && c >=
'0') {
98 if (valueIndex > secondsIndex) {
99 miliSeconds += (c -
'0') * miliSecondsFact;
100 miliSecondsFact /= 10;
103 *valueIndex += c -
'0';
105 }
else if ((c ==
'-' || c ==
':' || c ==
'/') || (c ==
'.' && (valueIndex == secondsIndex)) || (c ==
' ' && (valueIndex == dayIndex))) {
106 if (++valueIndex == valuesEnd) {
109 }
else if (c ==
'\0') {
115 return DateTime::fromDateAndTime(values[0], values[1], *dayIndex, values[3], values[4], *secondsIndex, miliSeconds);
127 std::pair<DateTime, TimeSpan> DateTime::fromIsoString(
const char *str)
129 int values[9] = { 0 };
130 int *
const dayIndex = values + 2;
131 int *
const hourIndex = values + 3;
132 int *
const secondsIndex = values + 5;
133 int *
const miliSecondsIndex = values + 6;
134 int *
const deltaHourIndex = values + 7;
135 int *valueIndex = values;
136 bool deltaNegative =
false;
137 double miliSecondsFact = 100.0, miliSeconds = 0.0;
138 for (
const char *strIndex = str;; ++strIndex) {
139 const char c = *strIndex;
140 if (c <= '9' && c >=
'0') {
141 if (valueIndex == miliSecondsIndex) {
142 miliSeconds += (c -
'0') * miliSecondsFact;
143 miliSecondsFact /= 10;
146 *valueIndex += c -
'0';
148 }
else if (c ==
'T') {
149 if (++valueIndex != hourIndex) {
152 }
else if (c ==
'-') {
153 if (valueIndex < dayIndex) {
155 }
else if (++valueIndex == deltaHourIndex) {
156 deltaNegative =
true;
160 }
else if (c ==
'.') {
161 if (valueIndex != secondsIndex) {
166 }
else if (c ==
':') {
167 if (valueIndex < hourIndex) {
169 }
else if (valueIndex == secondsIndex) {
174 }
else if ((c ==
'+') && (++valueIndex == deltaHourIndex)) {
175 deltaNegative =
false;
176 }
else if ((c ==
'Z') && (++valueIndex == deltaHourIndex)) {
178 }
else if (c ==
'\0') {
184 auto delta(TimeSpan::fromMinutes(*deltaHourIndex * 60 + values[8]));
186 delta =
TimeSpan(-delta.totalTicks());
188 return make_pair(DateTime::fromDateAndTime(values[0], values[1], *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds), delta);
199 toString(result, format, noMilliseconds);
210 stringstream s(stringstream::in | stringstream::out);
212 if (format == DateTimeOutputFormat::DateTimeAndWeekday || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
213 s << printDayOfWeek(dayOfWeek(), format == DateTimeOutputFormat::DateTimeAndShortWeekday) <<
' ';
214 if (format == DateTimeOutputFormat::DateOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
215 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
216 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day();
217 if (format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
218 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
220 if (format == DateTimeOutputFormat::TimeOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
221 || format == DateTimeOutputFormat::DateTimeAndShortWeekday) {
222 s << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' << setw(2) << second();
223 int ms = millisecond();
224 if (!noMilliseconds && ms > 0) {
225 s <<
'.' << setw(3) << ms;
235 string DateTime::toIsoString(
TimeSpan timeZoneDelta)
const 237 stringstream s(stringstream::in | stringstream::out);
239 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day() <<
'T' << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' 240 << setw(2) << second();
241 const int milli(millisecond());
242 const int micro(microsecond());
243 const int nano(nanosecond());
244 if (milli || micro || nano) {
245 s <<
'.' << setw(3) << milli;
247 s << setw(3) << micro;
249 s << nano / TimeSpan::nanosecondsPerTick;
253 if (!timeZoneDelta.
isNull()) {
260 s << setw(2) << timeZoneDelta.
hours() <<
':' << setw(2) << timeZoneDelta.
minutes();
272 const char *DateTime::printDayOfWeek(
DayOfWeek dayOfWeek,
bool abbreviation)
276 case DayOfWeek::Monday:
278 case DayOfWeek::Tuesday:
280 case DayOfWeek::Wednesday:
282 case DayOfWeek::Thursday:
284 case DayOfWeek::Friday:
286 case DayOfWeek::Saturday:
288 case DayOfWeek::Sunday:
293 case DayOfWeek::Monday:
295 case DayOfWeek::Tuesday:
297 case DayOfWeek::Wednesday:
299 case DayOfWeek::Thursday:
301 case DayOfWeek::Friday:
303 case DayOfWeek::Saturday:
305 case DayOfWeek::Sunday:
312 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_MAC) 320 clock_gettime(CLOCK_REALTIME, &t);
322 DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(t.tv_sec) * TimeSpan::m_ticksPerSecond + static_cast<uint64>(t.tv_nsec) / 100);
329 uint64 DateTime::dateToTicks(
int year,
int month,
int day)
337 const auto *
const daysToMonth =
reinterpret_cast<const int *
>(isLeapYear(year) ? m_daysToMonth366 : m_daysToMonth365);
338 const int passedMonth = month - 1;
339 if (!
inRangeInclMax(day, 1, daysToMonth[month] - daysToMonth[passedMonth])) {
342 const auto passedYears =
static_cast<unsigned int>(year - 1);
343 const auto passedDays =
static_cast<unsigned int>(day - 1);
344 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400
345 + static_cast<unsigned int>(daysToMonth[passedMonth]) + passedDays)
346 * TimeSpan::m_ticksPerDay;
352 uint64 DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
366 return static_cast<uint64>(hour * TimeSpan::m_ticksPerHour) + static_cast<uint64>(minute * TimeSpan::m_ticksPerMinute)
367 +
static_cast<uint64>(second * TimeSpan::m_ticksPerSecond) + static_cast<uint64>(millisecond * TimeSpan::m_ticksPerMillisecond);
374 int DateTime::getDatePart(
DatePart part)
const 376 const int fullDays = m_ticks / TimeSpan::m_ticksPerDay;
377 const int full400YearBlocks = fullDays / m_daysPer400Years;
378 const int daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
379 int full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
380 if (full100YearBlocks == 4) {
381 full100YearBlocks = 3;
383 const int daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
384 const int full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
385 const int daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
386 int full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
387 if (full1YearBlocks == 4) {
390 if (part == DatePart::Year) {
391 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
393 const int restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
394 if (part == DatePart::DayOfYear) {
397 const int *
const daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
399 while (restDays >= daysToMonth[month]) {
402 if (part == DatePart::Month) {
404 }
else if (part == DatePart::Day) {
405 return restDays - daysToMonth[month - 1] + 1;
constexpr bool isNegative() const
Returns ture if the time interval represented by the current TimeSpan class is negative.
constexpr bool inRangeExclMax(num1 val, num2 min, num3 max)
Represents an instant in time, typically expressed as a date and time of day.
Contains classes providing a means for handling date and time information.
constexpr int64 totalTicks() const
Returns the number of ticks that represent the value of the current TimeSpan class.
The ConversionException class is thrown by the various conversion functions of this library when a co...
Represents a time interval.
constexpr int hours() const
Returns the hours component of the time interval represented by the current TimeSpan class...
constexpr StringType argsToString(Args &&... args)
std::uint64_t uint64
unsigned 64-bit integer
constexpr bool isNull() const
Returns ture if the time interval represented by the current TimeSpan class is null.
constexpr T max(T first, T second)
Returns the greatest of the given items.
constexpr int minutes() const
Returns the minutes component of the time interval represented by the current TimeSpan class...
DatePart
Specifies the date part.
Contains several functions providing conversions between different data types.
DateTimeOutputFormat
Specifies the output format.
constexpr bool inRangeInclMax(num1 val, num2 min, num3 max)
constexpr T min(T first, T second)
Returns the smallest of the given items.
DayOfWeek
Specifies the day of the week.