9#if !defined(CPP_UTILITIES_CHRONO_BASED_EXACT_TIME) && (defined(PLATFORM_MAC) || !defined(PLATFORM_UNIX))
10#define CPP_UTILITIES_CHRONO_BASED_EXACT_TIME
12#ifdef CPP_UTILITIES_CHRONO_BASED_EXACT_TIME
20const int DateTime::m_daysPerYear = 365;
21const int DateTime::m_daysPer4Years = 1461;
22const int DateTime::m_daysPer100Years = 36524;
23const int DateTime::m_daysPer400Years = 146097;
24const int DateTime::m_daysTo1601 = 584388;
25const int DateTime::m_daysTo1899 = 693593;
26const int DateTime::m_daysTo10000 = 3652059;
27const int DateTime::m_daysToMonth365[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
28const int DateTime::m_daysToMonth366[13] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
29const int DateTime::m_daysInMonth365[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
30const int DateTime::m_daysInMonth366[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
32template <
typename num1,
typename num2,
typename num3>
constexpr bool inRangeInclMax(num1 val, num2
min, num3
max)
34 return (val) >= (
min) && (val) <= (
max);
37template <
typename num1,
typename num2,
typename num3>
constexpr bool inRangeExclMax(num1 val, num2
min, num3
max)
39 return (val) >= (
min) && (val) < (
max);
78 struct tm *
const timeinfo = localtime(&timeStamp);
79 return DateTime::fromDateAndTime(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min,
80 timeinfo->tm_sec < 60 ? timeinfo->tm_sec : 59, 0);
114 return std::make_pair(expr.value, expr.delta);
129 stringstream s(stringstream::in | stringstream::out);
133 constexpr auto dateDelimiter =
'-', timeDelimiter =
':';
135 const int *
const firstTimeComponent = components + 3;
136 const int *
const firstFractionalComponent = components + 6;
137 const int *
const lastComponent = components + 8;
138 const int *componentsEnd = noMilliseconds ? firstFractionalComponent : lastComponent + 1;
139 for (
const int *
i = componentsEnd - 1;
i > components; --
i) {
140 if (
i >= firstTimeComponent && *
i == 0) {
142 }
else if (
i < firstTimeComponent && *
i == 1) {
146 for (
const int *
i = components;
i != componentsEnd; ++
i) {
147 if (
i == firstTimeComponent) {
149 }
else if (
i == firstFractionalComponent) {
152 if (
i == components) {
154 }
else if (
i < firstFractionalComponent) {
155 if (
i < firstTimeComponent) {
157 }
else if (
i > firstTimeComponent) {
161 }
else if (
i < lastComponent) {
175 s << setw(4) <<
year() <<
'-' << setw(2) <<
month() <<
'-' << setw(2) <<
day();
181 s << setw(2) <<
hour() <<
':' << setw(2) <<
minute() <<
':' << setw(2) <<
second();
183 if (!noMilliseconds && ms > 0) {
184 s <<
'.' << setw(3) << ms;
196 stringstream s(stringstream::in | stringstream::out);
198 s << setw(4) <<
year() << dateDelimiter << setw(2) <<
month() << dateDelimiter << setw(2) <<
day() <<
'T' << setw(2) <<
hour() << timeDelimiter
199 << setw(2) <<
minute() << timeDelimiter << setw(2) <<
second();
203 if (milli || micro || nano) {
204 s <<
'.' << setw(3) << milli;
206 s << setw(3) << micro;
212 if (!timeZoneDelta.
isNull()) {
219 s << setw(2) << timeZoneDelta.
hours() << timeZoneDelimiter << setw(2) << timeZoneDelta.
minutes();
285#ifdef CPP_UTILITIES_CHRONO_BASED_EXACT_TIME
287 +
static_cast<std::uint64_t
>(
288 std::chrono::time_point_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count())
292 clock_gettime(CLOCK_REALTIME, &t);
294 +
static_cast<std::uint64_t
>(t.tv_nsec) / 100);
307 throw ConversionException(
"month is out of range");
309 const auto *
const daysToMonth =
reinterpret_cast<const int *
>(
isLeapYear(
year) ? m_daysToMonth366 : m_daysToMonth365);
310 const int passedMonth =
month - 1;
312 throw ConversionException(
"day is out of range");
314 const auto passedYears =
static_cast<unsigned int>(
year - 1);
315 const auto passedDays =
static_cast<unsigned int>(
day - 1);
316 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400
317 +
static_cast<unsigned int>(daysToMonth[passedMonth]) + passedDays)
324DateTime::TickType DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
327 throw ConversionException(
"hour is out of range");
330 throw ConversionException(
"minute is out of range");
333 throw ConversionException(
"second is out of range");
336 throw ConversionException(
"millisecond is out of range");
346int DateTime::getDatePart(
DatePart part)
const
349 const auto full400YearBlocks = fullDays / m_daysPer400Years;
350 const auto daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
351 auto full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
352 if (full100YearBlocks == 4) {
353 full100YearBlocks = 3;
355 const auto daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
356 const auto full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
357 const auto daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
358 auto full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
359 if (full1YearBlocks == 4) {
363 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
365 const auto restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
369 const auto *
const daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
371 while (restDays >= daysToMonth[
month]) {
377 return restDays - daysToMonth[
month - 1] + 1;
383static DateTimeParts dateTimePartsFromParsingDistance(
const int *valueIndex,
const int *values)
385 return static_cast<DateTimeParts>((1 << (valueIndex - values + 1)) - 1);
401 int values[9] = { 0 };
402 int *
const yearIndex = values + 0;
403 int *
const monthIndex = values + 1;
404 int *
const dayIndex = values + 2;
405 int *
const hourIndex = values + 3;
406 int *
const secondsIndex = values + 5;
407 int *
const miliSecondsIndex = values + 6;
408 int *
const deltaHourIndex = values + 7;
409 int *
const valuesEnd = values + 9;
410 int *valueIndex = values;
411 unsigned int remainingDigits = 4;
412 bool deltaNegative =
false;
413 double millisecondsFact = 100.0, milliseconds = 0.0;
414 for (
const char *strIndex = str;; ++strIndex) {
415 const char c = *strIndex;
416 if (c <=
'9' && c >=
'0') {
417 if (valueIndex == miliSecondsIndex) {
418 milliseconds += (c -
'0') * millisecondsFact;
419 millisecondsFact /= 10;
421 if (!remainingDigits) {
422 if (++valueIndex == miliSecondsIndex || valueIndex >= valuesEnd) {
428 *valueIndex += c -
'0';
429 remainingDigits -= 1;
431 }
else if (c ==
'T') {
432 if (++valueIndex != hourIndex) {
436 }
else if (c ==
'-') {
437 if (valueIndex < dayIndex) {
439 }
else if (++valueIndex >= secondsIndex) {
440 valueIndex = deltaHourIndex;
441 deltaNegative =
true;
446 }
else if (c ==
'.') {
447 if (valueIndex != secondsIndex) {
452 }
else if (c ==
':') {
453 if (valueIndex < hourIndex) {
455 }
else if (valueIndex == secondsIndex) {
461 }
else if ((c ==
'+') && (++valueIndex >= secondsIndex)) {
462 valueIndex = deltaHourIndex;
463 deltaNegative =
false;
465 }
else if ((c ==
'Z') && (++valueIndex >= secondsIndex)) {
466 valueIndex = deltaHourIndex + 2;
468 }
else if (c ==
'\0') {
476 res.delta =
TimeSpan(-res.delta.totalTicks());
478 if (valueIndex < monthIndex && !*monthIndex) {
481 if (valueIndex < dayIndex && !*dayIndex) {
484 res.value =
DateTime::fromDateAndTime(*yearIndex, *monthIndex, *dayIndex, *hourIndex, values[4], *secondsIndex, milliseconds);
485 res.parts = dateTimePartsFromParsingDistance(valueIndex, values);
501 int values[7] = { 0 };
502 int *
const monthIndex = values + 1;
503 int *
const dayIndex = values + 2;
504 int *
const secondsIndex = values + 5;
505 int *valueIndex = values;
506 int *
const valuesEnd = values + 7;
507 double millisecondsFact = 100.0, milliseconds = 0.0;
508 for (
const char *strIndex = str;; ++strIndex) {
509 const char c = *strIndex;
510 if (c <=
'9' && c >=
'0') {
511 if (valueIndex > secondsIndex) {
512 milliseconds += (c -
'0') * millisecondsFact;
513 millisecondsFact /= 10;
515 Detail::raiseAndAdd(*valueIndex, 10, c);
517 }
else if ((c ==
'-' || c ==
':' || c ==
'/') || (c ==
'.' && (valueIndex == secondsIndex))
518 || ((c ==
' ' || c ==
'T') && (valueIndex == dayIndex))) {
519 if (++valueIndex == valuesEnd) {
522 }
else if (c ==
'\0') {
528 if (valueIndex < monthIndex && !*monthIndex) {
531 if (valueIndex < dayIndex && !*dayIndex) {
534 res.value =
DateTime::fromDateAndTime(values[0], values[1], *dayIndex, values[3], values[4], *secondsIndex, milliseconds);
535 res.parts = dateTimePartsFromParsingDistance(valueIndex, values);
545 auto s = std::stringstream(std::stringstream::in | std::stringstream::out);
548 s << setw(4) <<
value.year();
554 s << setw(2) <<
value.month();
560 s << setw(2) <<
value.day();
566 s << setw(2) <<
value.hour();
572 s << setw(2) <<
value.minute();
578 s << setw(2) <<
value.second();
581 const auto milli =
value.millisecond();
582 const auto micro =
value.microsecond();
583 const auto nano =
value.nanosecond();
584 s <<
'.' << setw(3) << milli;
586 s << setw(3) << micro;
594 if (d.isNegative()) {
601 s << setw(2) << d.hours();
605 s << timeZoneDelimiter;
607 s << setw(2) << d.minutes();
The ConversionException class is thrown by the various conversion functions of this library when a co...
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.
static DateTime exactGmtNow()
Returns a DateTime object that is set to the current date and time on this computer,...
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.