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 >= secondsIndex)) {
175 valueIndex = deltaHourIndex;
176 deltaNegative =
false;
177 }
else if ((c ==
'Z') && (++valueIndex >= secondsIndex)) {
178 valueIndex = deltaHourIndex + 2;
179 }
else if (c ==
'\0') {
185 auto delta(TimeSpan::fromMinutes(*deltaHourIndex * 60 + values[8]));
187 delta =
TimeSpan(-delta.totalTicks());
189 return make_pair(DateTime::fromDateAndTime(values[0], values[1], *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds), delta);
200 toString(result, format, noMilliseconds);
211 stringstream s(stringstream::in | stringstream::out);
213 if (format == DateTimeOutputFormat::DateTimeAndWeekday || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
214 s << printDayOfWeek(dayOfWeek(), format == DateTimeOutputFormat::DateTimeAndShortWeekday) <<
' ';
215 if (format == DateTimeOutputFormat::DateOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
216 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
217 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day();
218 if (format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
219 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
221 if (format == DateTimeOutputFormat::TimeOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
222 || format == DateTimeOutputFormat::DateTimeAndShortWeekday) {
223 s << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' << setw(2) << second();
224 int ms = millisecond();
225 if (!noMilliseconds && ms > 0) {
226 s <<
'.' << setw(3) << ms;
236 string DateTime::toIsoString(
TimeSpan timeZoneDelta)
const 238 stringstream s(stringstream::in | stringstream::out);
240 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day() <<
'T' << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' 241 << setw(2) << second();
242 const int milli(millisecond());
243 const int micro(microsecond());
244 const int nano(nanosecond());
245 if (milli || micro || nano) {
246 s <<
'.' << setw(3) << milli;
248 s << setw(3) << micro;
250 s << nano / TimeSpan::nanosecondsPerTick;
254 if (!timeZoneDelta.
isNull()) {
261 s << setw(2) << timeZoneDelta.
hours() <<
':' << setw(2) << timeZoneDelta.
minutes();
273 const char *DateTime::printDayOfWeek(
DayOfWeek dayOfWeek,
bool abbreviation)
277 case DayOfWeek::Monday:
279 case DayOfWeek::Tuesday:
281 case DayOfWeek::Wednesday:
283 case DayOfWeek::Thursday:
285 case DayOfWeek::Friday:
287 case DayOfWeek::Saturday:
289 case DayOfWeek::Sunday:
294 case DayOfWeek::Monday:
296 case DayOfWeek::Tuesday:
298 case DayOfWeek::Wednesday:
300 case DayOfWeek::Thursday:
302 case DayOfWeek::Friday:
304 case DayOfWeek::Saturday:
306 case DayOfWeek::Sunday:
313 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_MAC) 321 clock_gettime(CLOCK_REALTIME, &t);
323 DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(t.tv_sec) * TimeSpan::m_ticksPerSecond + static_cast<uint64>(t.tv_nsec) / 100);
330 uint64 DateTime::dateToTicks(
int year,
int month,
int day)
338 const auto *
const daysToMonth = reinterpret_cast<const int *>(isLeapYear(year) ? m_daysToMonth366 : m_daysToMonth365);
339 const int passedMonth = month - 1;
340 if (!
inRangeInclMax(day, 1, daysToMonth[month] - daysToMonth[passedMonth])) {
343 const auto passedYears = static_cast<unsigned int>(year - 1);
344 const auto passedDays = static_cast<unsigned int>(day - 1);
345 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400
346 + static_cast<unsigned int>(daysToMonth[passedMonth]) + passedDays)
347 * TimeSpan::m_ticksPerDay;
353 uint64 DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
367 return static_cast<uint64>(hour * TimeSpan::m_ticksPerHour) + static_cast<uint64>(minute * TimeSpan::m_ticksPerMinute)
368 + static_cast<uint64>(second * TimeSpan::m_ticksPerSecond) + static_cast<uint64>(millisecond * TimeSpan::m_ticksPerMillisecond);
375 int DateTime::getDatePart(
DatePart part)
const 377 const int fullDays = m_ticks / TimeSpan::m_ticksPerDay;
378 const int full400YearBlocks = fullDays / m_daysPer400Years;
379 const int daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
380 int full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
381 if (full100YearBlocks == 4) {
382 full100YearBlocks = 3;
384 const int daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
385 const int full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
386 const int daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
387 int full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
388 if (full1YearBlocks == 4) {
391 if (part == DatePart::Year) {
392 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
394 const int restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
395 if (part == DatePart::DayOfYear) {
398 const int *
const daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
400 while (restDays >= daysToMonth[month]) {
403 if (part == DatePart::Month) {
405 }
else if (part == DatePart::Day) {
406 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.