13const int DateTime::m_daysPerYear = 365;
14const int DateTime::m_daysPer4Years = 1461;
15const int DateTime::m_daysPer100Years = 36524;
16const int DateTime::m_daysPer400Years = 146097;
17const int DateTime::m_daysTo1601 = 584388;
18const int DateTime::m_daysTo1899 = 693593;
19const int DateTime::m_daysTo10000 = 3652059;
20const int DateTime::m_daysToMonth365[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
21const int DateTime::m_daysToMonth366[13] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
22const int DateTime::m_daysInMonth365[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
23const int DateTime::m_daysInMonth366[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
25template <
typename num1,
typename num2,
typename num3>
constexpr bool inRangeInclMax(num1 val, num2
min, num3
max)
27 return (val) >= (
min) && (val) <= (
max);
30template <
typename num1,
typename num2,
typename num3>
constexpr bool inRangeExclMax(num1 val, num2
min, num3
max)
32 return (val) >= (
min) && (val) < (
max);
71 struct tm *
const timeinfo = localtime(&timeStamp);
72 return DateTime::fromDateAndTime(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min,
73 timeinfo->tm_sec < 60 ? timeinfo->tm_sec : 59, 0);
107 return std::make_pair(expr.value, expr.delta);
122 stringstream s(stringstream::in | stringstream::out);
126 constexpr auto dateDelimiter =
'-', timeDelimiter =
':';
128 const int *
const firstTimeComponent = components + 3;
129 const int *
const firstFractionalComponent = components + 6;
130 const int *
const lastComponent = components + 8;
131 const int *componentsEnd = noMilliseconds ? firstFractionalComponent : lastComponent + 1;
132 for (
const int *
i = componentsEnd - 1;
i > components; --
i) {
133 if (
i >= firstTimeComponent && *
i == 0) {
135 }
else if (
i < firstTimeComponent && *
i == 1) {
139 for (
const int *
i = components;
i != componentsEnd; ++
i) {
140 if (
i == firstTimeComponent) {
142 }
else if (
i == firstFractionalComponent) {
145 if (
i == components) {
147 }
else if (
i < firstFractionalComponent) {
148 if (
i < firstTimeComponent) {
150 }
else if (
i > firstTimeComponent) {
154 }
else if (
i < lastComponent) {
168 s << setw(4) <<
year() <<
'-' << setw(2) <<
month() <<
'-' << setw(2) <<
day();
174 s << setw(2) <<
hour() <<
':' << setw(2) <<
minute() <<
':' << setw(2) <<
second();
176 if (!noMilliseconds && ms > 0) {
177 s <<
'.' << setw(3) << ms;
189 stringstream s(stringstream::in | stringstream::out);
191 s << setw(4) <<
year() << dateDelimiter << setw(2) <<
month() << dateDelimiter << setw(2) <<
day() <<
'T' << setw(2) <<
hour() << timeDelimiter
192 << setw(2) <<
minute() << timeDelimiter << setw(2) <<
second();
196 if (milli || micro || nano) {
197 s <<
'.' << setw(3) << milli;
199 s << setw(3) << micro;
205 if (!timeZoneDelta.
isNull()) {
212 s << setw(2) << timeZoneDelta.
hours() << timeZoneDelimiter << setw(2) << timeZoneDelta.
minutes();
273#if defined(PLATFORM_UNIX) && !defined(PLATFORM_MAC)
281 clock_gettime(CLOCK_REALTIME, &t);
283 +
static_cast<std::uint64_t
>(t.tv_nsec) / 100);
293 throw ConversionException(
"year is out of range");
296 throw ConversionException(
"month is out of range");
298 const auto *
const daysToMonth =
reinterpret_cast<const int *
>(
isLeapYear(
year) ? m_daysToMonth366 : m_daysToMonth365);
299 const int passedMonth =
month - 1;
301 throw ConversionException(
"day is out of range");
303 const auto passedYears =
static_cast<unsigned int>(
year - 1);
304 const auto passedDays =
static_cast<unsigned int>(
day - 1);
305 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400
306 +
static_cast<unsigned int>(daysToMonth[passedMonth]) + passedDays)
313DateTime::TickType DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
316 throw ConversionException(
"hour is out of range");
319 throw ConversionException(
"minute is out of range");
322 throw ConversionException(
"second is out of range");
325 throw ConversionException(
"millisecond is out of range");
335int DateTime::getDatePart(
DatePart part)
const
338 const auto full400YearBlocks = fullDays / m_daysPer400Years;
339 const auto daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
340 auto full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
341 if (full100YearBlocks == 4) {
342 full100YearBlocks = 3;
344 const auto daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
345 const auto full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
346 const auto daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
347 auto full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
348 if (full1YearBlocks == 4) {
352 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
354 const auto restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
358 const auto *
const daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
360 while (restDays >= daysToMonth[
month]) {
366 return restDays - daysToMonth[
month - 1] + 1;
372static DateTimeParts dateTimePartsFromParsingDistance(
const int *valueIndex,
const int *values)
374 return static_cast<DateTimeParts>((1 << (valueIndex - values + 1)) - 1);
390 int values[9] = { 0 };
391 int *
const yearIndex = values + 0;
392 int *
const monthIndex = values + 1;
393 int *
const dayIndex = values + 2;
394 int *
const hourIndex = values + 3;
395 int *
const secondsIndex = values + 5;
396 int *
const miliSecondsIndex = values + 6;
397 int *
const deltaHourIndex = values + 7;
398 int *
const valuesEnd = values + 9;
399 int *valueIndex = values;
400 unsigned int remainingDigits = 4;
401 bool deltaNegative =
false;
402 double millisecondsFact = 100.0, milliseconds = 0.0;
403 for (
const char *strIndex = str;; ++strIndex) {
404 const char c = *strIndex;
405 if (c <=
'9' && c >=
'0') {
406 if (valueIndex == miliSecondsIndex) {
407 milliseconds += (c -
'0') * millisecondsFact;
408 millisecondsFact /= 10;
410 if (!remainingDigits) {
411 if (++valueIndex == miliSecondsIndex || valueIndex >= valuesEnd) {
417 *valueIndex += c -
'0';
418 remainingDigits -= 1;
420 }
else if (c ==
'T') {
421 if (++valueIndex != hourIndex) {
425 }
else if (c ==
'-') {
426 if (valueIndex < dayIndex) {
428 }
else if (++valueIndex >= secondsIndex) {
429 valueIndex = deltaHourIndex;
430 deltaNegative =
true;
435 }
else if (c ==
'.') {
436 if (valueIndex != secondsIndex) {
441 }
else if (c ==
':') {
442 if (valueIndex < hourIndex) {
444 }
else if (valueIndex == secondsIndex) {
450 }
else if ((c ==
'+') && (++valueIndex >= secondsIndex)) {
451 valueIndex = deltaHourIndex;
452 deltaNegative =
false;
454 }
else if ((c ==
'Z') && (++valueIndex >= secondsIndex)) {
455 valueIndex = deltaHourIndex + 2;
457 }
else if (c ==
'\0') {
465 res.delta =
TimeSpan(-res.delta.totalTicks());
467 if (valueIndex < monthIndex && !*monthIndex) {
470 if (valueIndex < dayIndex && !*dayIndex) {
473 res.value =
DateTime::fromDateAndTime(*yearIndex, *monthIndex, *dayIndex, *hourIndex, values[4], *secondsIndex, milliseconds);
474 res.parts = dateTimePartsFromParsingDistance(valueIndex, values);
490 int values[7] = { 0 };
491 int *
const monthIndex = values + 1;
492 int *
const dayIndex = values + 2;
493 int *
const secondsIndex = values + 5;
494 int *valueIndex = values;
495 int *
const valuesEnd = values + 7;
496 double millisecondsFact = 100.0, milliseconds = 0.0;
497 for (
const char *strIndex = str;; ++strIndex) {
498 const char c = *strIndex;
499 if (c <=
'9' && c >=
'0') {
500 if (valueIndex > secondsIndex) {
501 milliseconds += (c -
'0') * millisecondsFact;
502 millisecondsFact /= 10;
504 Detail::raiseAndAdd(*valueIndex, 10, c);
506 }
else if ((c ==
'-' || c ==
':' || c ==
'/') || (c ==
'.' && (valueIndex == secondsIndex))
507 || ((c ==
' ' || c ==
'T') && (valueIndex == dayIndex))) {
508 if (++valueIndex == valuesEnd) {
511 }
else if (c ==
'\0') {
517 if (valueIndex < monthIndex && !*monthIndex) {
520 if (valueIndex < dayIndex && !*dayIndex) {
523 res.value =
DateTime::fromDateAndTime(values[0], values[1], *dayIndex, values[3], values[4], *secondsIndex, milliseconds);
524 res.parts = dateTimePartsFromParsingDistance(valueIndex, values);
534 auto s = std::stringstream(std::stringstream::in | std::stringstream::out);
537 s << setw(4) <<
value.year();
543 s << setw(2) <<
value.month();
549 s << setw(2) <<
value.day();
555 s << setw(2) <<
value.hour();
561 s << setw(2) <<
value.minute();
567 s << setw(2) <<
value.second();
570 const auto milli =
value.millisecond();
571 const auto micro =
value.microsecond();
572 const auto nano =
value.nanosecond();
573 s <<
'.' << setw(3) << milli;
575 s << setw(3) << micro;
583 if (d.isNegative()) {
590 s << setw(2) << d.hours();
594 s << timeZoneDelimiter;
596 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 provided 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.