3 #include "../conversion/stringbuilder.h" 4 #include "../conversion/stringconversion.h" 10 #if defined(PLATFORM_UNIX) 18 const int DateTime::m_daysPerYear = 365;
19 const int DateTime::m_daysPer4Years = 1461;
20 const int DateTime::m_daysPer100Years = 36524;
21 const int DateTime::m_daysPer400Years = 146097;
22 const int DateTime::m_daysTo1601 = 584388;
23 const int DateTime::m_daysTo1899 = 693593;
24 const int DateTime::m_daysTo10000 = 3652059;
25 const int DateTime::m_daysToMonth365[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
26 const int DateTime::m_daysToMonth366[13] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
27 const int DateTime::m_daysInMonth365[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
28 const int DateTime::m_daysInMonth366[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
30 template <
typename num1,
typename num2,
typename num3> constexpr
bool inRangeInclMax(num1 val, num2 min, num3 max)
32 return (val) >= (min) && (val) <= (max);
35 template <
typename num1,
typename num2,
typename num3> constexpr
bool inRangeExclMax(num1 val, num2 min, num3 max)
37 return (val) >= (min) && (val) < (max);
63 DateTime DateTime::fromTimeStamp(time_t timeStamp)
66 struct tm *timeinfo = localtime(&timeStamp);
67 return DateTime::fromDateAndTime(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min,
68 timeinfo->tm_sec < 60 ? timeinfo->tm_sec : 59, 0);
77 DateTime DateTime::fromTimeStampGmt(time_t timeStamp)
79 return DateTime(DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(timeStamp) * TimeSpan::m_ticksPerSecond);
93 int values[6] = { 0 };
94 int *
const dayIndex = values + 2;
95 int *
const secondsIndex = values + 5;
96 int *valueIndex = values;
97 int *
const valuesEnd = values + 7;
98 double miliSecondsFact = 100.0, miliSeconds = 0.0;
99 for (
const char *strIndex = str;; ++strIndex) {
100 const char c = *strIndex;
101 if (c <= '9' && c >=
'0') {
102 if (valueIndex > secondsIndex) {
103 miliSeconds += (c -
'0') * miliSecondsFact;
104 miliSecondsFact /= 10;
107 *valueIndex += c -
'0';
109 }
else if ((c ==
'-' || c ==
':' || c ==
'/') || (c ==
'.' && (valueIndex == secondsIndex)) || (c ==
' ' && (valueIndex == dayIndex))) {
110 if (++valueIndex == valuesEnd) {
113 }
else if (c ==
'\0') {
119 return DateTime::fromDateAndTime(values[0], values[1], *dayIndex, values[3], values[4], *secondsIndex, miliSeconds);
130 std::pair<DateTime, TimeSpan> DateTime::fromIsoString(
const char *str)
132 int values[9] = { 0 };
133 int *
const dayIndex = values + 2;
134 int *
const hourIndex = values + 3;
135 int *
const secondsIndex = values + 5;
136 int *
const miliSecondsIndex = values + 6;
137 int *
const deltaHourIndex = values + 7;
138 int *valueIndex = values;
139 bool deltaNegative =
false;
140 double miliSecondsFact = 100.0, miliSeconds = 0.0;
141 for (
const char *strIndex = str;; ++strIndex) {
142 const char c = *strIndex;
143 if (c <= '9' && c >=
'0') {
144 if (valueIndex == miliSecondsIndex) {
145 miliSeconds += (c -
'0') * miliSecondsFact;
146 miliSecondsFact /= 10;
149 *valueIndex += c -
'0';
151 }
else if (c ==
'T') {
152 if (++valueIndex != hourIndex) {
155 }
else if (c ==
'-') {
156 if (valueIndex < dayIndex) {
161 }
else if (c ==
'.') {
162 if (valueIndex != secondsIndex) {
167 }
else if (c ==
':') {
168 if (valueIndex < hourIndex) {
170 }
else if (valueIndex == secondsIndex) {
175 }
else if ((c ==
'+') && (++valueIndex == deltaHourIndex)) {
176 deltaNegative =
false;
177 }
else if ((c ==
'-') && (++valueIndex == deltaHourIndex)) {
178 deltaNegative =
true;
179 }
else if (c ==
'\0') {
185 deltaNegative && (*deltaHourIndex = -*deltaHourIndex);
186 return make_pair(DateTime::fromDateAndTime(values[0], values[1], *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds),
187 TimeSpan::fromMinutes(*deltaHourIndex * 60 + values[8]));
198 toString(result, format, noMilliseconds);
209 stringstream s(stringstream::in | stringstream::out);
211 if (format == DateTimeOutputFormat::DateTimeAndWeekday || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
212 s << printDayOfWeek(dayOfWeek(), format == DateTimeOutputFormat::DateTimeAndShortWeekday) <<
' ';
213 if (format == DateTimeOutputFormat::DateOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
214 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
215 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day();
216 if (format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
217 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
219 if (format == DateTimeOutputFormat::TimeOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
220 || format == DateTimeOutputFormat::DateTimeAndShortWeekday) {
221 s << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' << setw(2) << second();
222 int ms = millisecond();
223 if (!noMilliseconds && ms > 0) {
224 s <<
'.' << setw(3) << ms;
234 string DateTime::toIsoString(
TimeSpan timeZoneDelta)
const 236 stringstream s(stringstream::in | stringstream::out);
238 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day() <<
'T' << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' 239 << setw(2) << second();
240 const int milli(millisecond());
241 const int micro(microsecond());
242 const int nano(nanosecond());
243 if (milli || micro || nano) {
244 s <<
'.' << setw(3) << milli;
246 s << setw(3) << micro;
248 s << nano / TimeSpan::nanosecondsPerTick;
252 if (!timeZoneDelta.
isNull()) {
253 s << (timeZoneDelta.
isNegative() ?
'-' :
'+');
254 s << setw(2) << timeZoneDelta.
hours() <<
':' << setw(2) << timeZoneDelta.
minutes();
266 const char *DateTime::printDayOfWeek(
DayOfWeek dayOfWeek,
bool abbreviation)
270 case DayOfWeek::Monday:
272 case DayOfWeek::Tuesday:
274 case DayOfWeek::Wednesday:
276 case DayOfWeek::Thursday:
278 case DayOfWeek::Friday:
280 case DayOfWeek::Saturday:
282 case DayOfWeek::Sunday:
287 case DayOfWeek::Monday:
289 case DayOfWeek::Tuesday:
291 case DayOfWeek::Wednesday:
293 case DayOfWeek::Thursday:
295 case DayOfWeek::Friday:
297 case DayOfWeek::Saturday:
299 case DayOfWeek::Sunday:
306 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_MAC) 314 clock_gettime(CLOCK_REALTIME, &t);
316 DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(t.tv_sec) * TimeSpan::m_ticksPerSecond + static_cast<uint64>(t.tv_nsec) / 100);
323 uint64 DateTime::dateToTicks(
int year,
int month,
int day)
331 const auto *
const daysToMonth =
reinterpret_cast<const int *
>(isLeapYear(year) ? m_daysToMonth366 : m_daysToMonth365);
332 const int passedMonth = month - 1;
333 if (!
inRangeInclMax(day, 1, daysToMonth[month] - daysToMonth[passedMonth])) {
336 const auto passedYears =
static_cast<unsigned int>(year - 1);
337 const auto passedDays =
static_cast<unsigned int>(day - 1);
338 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400
339 + static_cast<unsigned int>(daysToMonth[passedMonth]) + passedDays)
340 * TimeSpan::m_ticksPerDay;
346 uint64 DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
360 return static_cast<uint64>(hour * TimeSpan::m_ticksPerHour) + static_cast<uint64>(minute * TimeSpan::m_ticksPerMinute)
361 +
static_cast<uint64>(second * TimeSpan::m_ticksPerSecond) + static_cast<uint64>(millisecond * TimeSpan::m_ticksPerMillisecond);
368 int DateTime::getDatePart(
DatePart part)
const 370 const int fullDays = m_ticks / TimeSpan::m_ticksPerDay;
371 const int full400YearBlocks = fullDays / m_daysPer400Years;
372 const int daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
373 int full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
374 if (full100YearBlocks == 4) {
375 full100YearBlocks = 3;
377 const int daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
378 const int full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
379 const int daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
380 int full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
381 if (full1YearBlocks == 4) {
384 if (part == DatePart::Year) {
385 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
387 const int restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
388 if (part == DatePart::DayOfYear) {
391 const int *
const daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
393 while (restDays >= daysToMonth[month]) {
396 if (part == DatePart::Month) {
398 }
else if (part == DatePart::Day) {
399 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.
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 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)
DayOfWeek
Specifies the day of the week.