14const int DateTime::m_daysPerYear = 365;
15const int DateTime::m_daysPer4Years = 1461;
16const int DateTime::m_daysPer100Years = 36524;
17const int DateTime::m_daysPer400Years = 146097;
18const int DateTime::m_daysTo1601 = 584388;
19const int DateTime::m_daysTo1899 = 693593;
20const int DateTime::m_daysTo10000 = 3652059;
21const int DateTime::m_daysToMonth365[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
22const int DateTime::m_daysToMonth366[13] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
23const int DateTime::m_daysInMonth365[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
24const int DateTime::m_daysInMonth366[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
26template <
typename num1,
typename num2,
typename num3>
constexpr bool inRangeInclMax(num1 val, num2
min, num3
max)
28 return (val) >= (
min) && (val) <= (
max);
31template <
typename num1,
typename num2,
typename num3>
constexpr bool inRangeExclMax(num1 val, num2
min, num3
max)
33 return (val) >= (
min) && (val) < (
max);
72 struct tm *
const timeinfo = localtime(&timeStamp);
73 return DateTime::fromDateAndTime(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min,
74 timeinfo->tm_sec < 60 ? timeinfo->tm_sec : 59, 0);
108 return std::make_pair(expr.value, expr.delta);
123 stringstream s(stringstream::in | stringstream::out);
127 constexpr auto dateDelimiter =
'-', timeDelimiter =
':';
129 const int *
const firstTimeComponent = components + 3;
130 const int *
const firstFractionalComponent = components + 6;
131 const int *
const lastComponent = components + 8;
132 const int *componentsEnd = noMilliseconds ? firstFractionalComponent : lastComponent + 1;
133 for (
const int *
i = componentsEnd - 1;
i > components; --
i) {
134 if (
i >= firstTimeComponent && *
i == 0) {
136 }
else if (
i < firstTimeComponent && *
i == 1) {
140 for (
const int *
i = components;
i != componentsEnd; ++
i) {
141 if (
i == firstTimeComponent) {
143 }
else if (
i == firstFractionalComponent) {
146 if (
i == components) {
148 }
else if (
i < firstFractionalComponent) {
149 if (
i < firstTimeComponent) {
151 }
else if (
i > firstTimeComponent) {
155 }
else if (
i < lastComponent) {
169 s << setw(4) <<
year() <<
'-' << setw(2) <<
month() <<
'-' << setw(2) <<
day();
175 s << setw(2) <<
hour() <<
':' << setw(2) <<
minute() <<
':' << setw(2) <<
second();
177 if (!noMilliseconds && ms > 0) {
178 s <<
'.' << setw(3) << ms;
190 stringstream s(stringstream::in | stringstream::out);
192 s << setw(4) <<
year() << dateDelimiter << setw(2) <<
month() << dateDelimiter << setw(2) <<
day() <<
'T' << setw(2) <<
hour() << timeDelimiter
193 << setw(2) <<
minute() << timeDelimiter << setw(2) <<
second();
197 if (milli || micro || nano) {
198 s <<
'.' << setw(3) << milli;
200 s << setw(3) << micro;
206 if (!timeZoneDelta.
isNull()) {
213 s << setw(2) << timeZoneDelta.
hours() << timeZoneDelimiter << setw(2) << timeZoneDelta.
minutes();
274#if defined(PLATFORM_UNIX) && !defined(PLATFORM_MAC)
282 clock_gettime(CLOCK_REALTIME, &t);
284 +
static_cast<std::uint64_t
>(t.tv_nsec) / 100);
294 throw ConversionException(
"year is out of range");
297 throw ConversionException(
"month is out of range");
299 const auto *
const daysToMonth =
reinterpret_cast<const int *
>(
isLeapYear(
year) ? m_daysToMonth366 : m_daysToMonth365);
300 const int passedMonth =
month - 1;
302 throw ConversionException(
"day is out of range");
304 const auto passedYears =
static_cast<unsigned int>(
year - 1);
305 const auto passedDays =
static_cast<unsigned int>(
day - 1);
306 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400
307 +
static_cast<unsigned int>(daysToMonth[passedMonth]) + passedDays)
314DateTime::TickType DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
317 throw ConversionException(
"hour is out of range");
320 throw ConversionException(
"minute is out of range");
323 throw ConversionException(
"second is out of range");
326 throw ConversionException(
"millisecond is out of range");
336int DateTime::getDatePart(
DatePart part)
const
339 const auto full400YearBlocks = fullDays / m_daysPer400Years;
340 const auto daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
341 auto full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
342 if (full100YearBlocks == 4) {
343 full100YearBlocks = 3;
345 const auto daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
346 const auto full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
347 const auto daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
348 auto full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
349 if (full1YearBlocks == 4) {
353 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
355 const auto restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
359 const auto *
const daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
361 while (restDays >= daysToMonth[
month]) {
367 return restDays - daysToMonth[
month - 1] + 1;
373static DateTimeParts dateTimePartsFromParsingDistance(
const int *valueIndex,
const int *values)
375 return static_cast<DateTimeParts>((1 << (valueIndex - values + 1)) - 1);
391 int values[9] = { 0 };
392 int *
const yearIndex = values + 0;
393 int *
const monthIndex = values + 1;
394 int *
const dayIndex = values + 2;
395 int *
const hourIndex = values + 3;
396 int *
const secondsIndex = values + 5;
397 int *
const miliSecondsIndex = values + 6;
398 int *
const deltaHourIndex = values + 7;
399 int *
const valuesEnd = values + 9;
400 int *valueIndex = values;
401 unsigned int remainingDigits = 4;
402 bool deltaNegative =
false;
403 double millisecondsFact = 100.0, milliseconds = 0.0;
404 for (
const char *strIndex = str;; ++strIndex) {
405 const char c = *strIndex;
406 if (c <=
'9' && c >=
'0') {
407 if (valueIndex == miliSecondsIndex) {
408 milliseconds += (c -
'0') * millisecondsFact;
409 millisecondsFact /= 10;
411 if (!remainingDigits) {
412 if (++valueIndex == miliSecondsIndex || valueIndex >= valuesEnd) {
418 *valueIndex += c -
'0';
419 remainingDigits -= 1;
421 }
else if (c ==
'T') {
422 if (++valueIndex != hourIndex) {
426 }
else if (c ==
'-') {
427 if (valueIndex < dayIndex) {
429 }
else if (++valueIndex >= secondsIndex) {
430 valueIndex = deltaHourIndex;
431 deltaNegative =
true;
436 }
else if (c ==
'.') {
437 if (valueIndex != secondsIndex) {
442 }
else if (c ==
':') {
443 if (valueIndex < hourIndex) {
445 }
else if (valueIndex == secondsIndex) {
451 }
else if ((c ==
'+') && (++valueIndex >= secondsIndex)) {
452 valueIndex = deltaHourIndex;
453 deltaNegative =
false;
455 }
else if ((c ==
'Z') && (++valueIndex >= secondsIndex)) {
456 valueIndex = deltaHourIndex + 2;
458 }
else if (c ==
'\0') {
466 res.delta =
TimeSpan(-res.delta.totalTicks());
468 if (valueIndex < monthIndex && !*monthIndex) {
471 if (valueIndex < dayIndex && !*dayIndex) {
474 res.value =
DateTime::fromDateAndTime(*yearIndex, *monthIndex, *dayIndex, *hourIndex, values[4], *secondsIndex, milliseconds);
475 res.parts = dateTimePartsFromParsingDistance(valueIndex, values);
491 int values[7] = { 0 };
492 int *
const monthIndex = values + 1;
493 int *
const dayIndex = values + 2;
494 int *
const secondsIndex = values + 5;
495 int *valueIndex = values;
496 int *
const valuesEnd = values + 7;
497 double millisecondsFact = 100.0, milliseconds = 0.0;
498 for (
const char *strIndex = str;; ++strIndex) {
499 const char c = *strIndex;
500 if (c <=
'9' && c >=
'0') {
501 if (valueIndex > secondsIndex) {
502 milliseconds += (c -
'0') * millisecondsFact;
503 millisecondsFact /= 10;
505 Detail::raiseAndAdd(*valueIndex, 10, c);
507 }
else if ((c ==
'-' || c ==
':' || c ==
'/') || (c ==
'.' && (valueIndex == secondsIndex))
508 || ((c ==
' ' || c ==
'T') && (valueIndex == dayIndex))) {
509 if (++valueIndex == valuesEnd) {
512 }
else if (c ==
'\0') {
518 if (valueIndex < monthIndex && !*monthIndex) {
521 if (valueIndex < dayIndex && !*dayIndex) {
524 res.value =
DateTime::fromDateAndTime(values[0], values[1], *dayIndex, values[3], values[4], *secondsIndex, milliseconds);
525 res.parts = dateTimePartsFromParsingDistance(valueIndex, values);
535 auto s = std::stringstream(std::stringstream::in | std::stringstream::out);
574 s <<
'.' << setw(3) << milli;
576 s << setw(3) << micro;
584 if (d.isNegative()) {
591 s << setw(2) << d.hours();
595 s << timeZoneDelimiter;
597 s << setw(2) << d.minutes();
The ConversionException class is thrown by the various conversion functions of this library when a co...
Represents an instant in time, typically expressed as a date and time of day.
std::string toString(DateTimeOutputFormat format=DateTimeOutputFormat::DateAndTime, bool noMilliseconds=false) const
Returns the string representation of the current instance using the specified format.
int day() const
Returns the day component of the date represented by this instance.
constexpr DayOfWeek dayOfWeek() const
Returns the day of the week represented by this instance.
std::string toIsoStringWithCustomDelimiters(TimeSpan timeZoneDelta=TimeSpan(), char dateDelimiter='-', char timeDelimiter=':', char timeZoneDelimiter=':') const
Returns the string representation of the current instance in the ISO format with custom delimiters,...
bool isLeapYear() const
Returns an indication whether the year represented by this instance is a leap year.
int month() const
Returns the month component of the date represented by this instance.
constexpr DateTime()
Constructs a DateTime.
std::string toIsoString(TimeSpan timeZoneDelta=TimeSpan()) const
Returns the string representation of the current instance in the ISO format, eg.
static constexpr DateTime unixEpochStart()
Returns the DateTime object for the "1970-01-01T00:00:00Z".
constexpr int microsecond() const
Returns the microsecond component of the date represented by this instance.
static std::pair< DateTime, TimeSpan > fromIsoString(const char *str)
Parses the specified ISO date time denotation provided as C-style string.
constexpr int hour() const
Returns the hour component of the date represented by this instance.
static DateTime fromString(const std::string &str)
Parses the given std::string as DateTime.
constexpr int second() const
Returns the second component of the date represented by this instance.
static DateTime fromDateAndTime(int year=1, int month=1, int day=1, int hour=0, int minute=0, int second=0, double millisecond=0.0)
Constructs a DateTime to the specified year, month, day, hour, minute, second and millisecond.
constexpr TickType totalTicks() const
Returns the number of ticks which represent the value of the current instance.
static DateTime fromTimeStamp(std::time_t timeStamp)
Constructs a new DateTime object with the local time from the specified UNIX timeStamp.
constexpr int millisecond() const
Returns the millisecond component of the date represented by this instance.
static const char * printDayOfWeek(DayOfWeek dayOfWeek, bool abbreviation=false)
Returns the string representation as C-style string for the given day of week.
constexpr int nanosecond() const
Returns the nanosecond component of the date represented by this instance.
constexpr int minute() const
Returns the minute component of the date represented by this instance.
int year() const
Returns the year component of the date represented by this instance.
Represents a time interval.
constexpr bool isNull() const
Returns true if the time interval represented by the current TimeSpan class is null.
static constexpr TickType nanosecondsPerTick
static constexpr TickType ticksPerMillisecond
constexpr int minutes() const
Returns the minutes component of the time interval represented by the current TimeSpan class.
constexpr TickType totalTicks() const
Returns the number of ticks that represent the value of the current TimeSpan class.
static constexpr TickType ticksPerMinute
static constexpr TimeSpan fromMinutes(double minutes)
Constructs a new instance of the TimeSpan class with the specified number of minutes.
static constexpr TickType ticksPerSecond
static constexpr TickType ticksPerDay
static constexpr TickType ticksPerHour
constexpr bool isNegative() const
Returns true if the time interval represented by the current TimeSpan class is negative.
constexpr int hours() const
Returns the hours component of the time interval represented by the current TimeSpan class.
Contains all utilities provides by the c++utilities library.
DatePart
Specifies the date part.
constexpr bool inRangeExclMax(num1 val, num2 min, num3 max)
constexpr bool inRangeInclMax(num1 val, num2 min, num3 max)
StringType argsToString(Args &&...args)
constexpr T max(T first, T second)
Returns the greatest of the given items.
DateTimeParts
The DateTimeParts enum specifies which parts of a timestamp are present.
DateTimeOutputFormat
Specifies the output format.
@ DateTimeAndShortWeekday
@ IsoOmittingDefaultComponents
constexpr T min(T first, T second)
Returns the smallest of the given items.
DayOfWeek
Specifies the day of the week.
The DateTimeExpression struct holds information about a time expression (e.g.
static DateTimeExpression fromString(const char *str)
Parses the given C-style string.
std::string toIsoString(char dateDelimiter='-', char timeDelimiter=':', char timeZoneDelimiter=':') const
Returns the string representation of the current instance in the ISO format.
static DateTimeExpression fromIsoString(const char *str)
Parses the specified ISO date time denotation provided as C-style string.