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>
inline bool inRangeInclMax(num1 val, num2 min, num3 max)
32 return (val) >= (min) && (val) <= (max);
35 template <
typename num1,
typename num2,
typename num3>
inline bool inRangeExclMax(num1 val, num2 min, num3 max)
37 return (val) >= (min) && (val) < (max);
56 DateTime DateTime::fromTimeStamp(time_t timeStamp)
59 struct tm *timeinfo = localtime(&timeStamp);
60 return DateTime::fromDateAndTime(timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min,
61 timeinfo->tm_sec < 60 ? timeinfo->tm_sec : 59, 0);
70 DateTime DateTime::fromTimeStampGmt(time_t timeStamp)
72 return DateTime(DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(timeStamp) * TimeSpan::m_ticksPerSecond);
80 int values[6] = { 0 };
81 int *
const dayIndex = values + 2;
82 int *
const secondsIndex = values + 5;
83 int *valueIndex = values;
84 int *
const valuesEnd = values + 7;
85 double miliSecondsFact = 100.0, miliSeconds = 0.0;
86 for (
const char *strIndex = str;; ++strIndex) {
87 const char c = *strIndex;
88 if (c <= '9' && c >=
'0') {
89 if (valueIndex > secondsIndex) {
90 miliSeconds += (c -
'0') * miliSecondsFact;
91 miliSecondsFact /= 10;
94 *valueIndex += c -
'0';
96 }
else if ((c ==
'-' || c ==
':' || c ==
'/') || (c ==
'.' && (valueIndex == secondsIndex)) || (c ==
' ' && (valueIndex == dayIndex))) {
97 if (++valueIndex == valuesEnd) {
100 }
else if (c ==
'\0') {
106 return DateTime::fromDateAndTime(values[0], values[1], *dayIndex, values[3], values[4], *secondsIndex, miliSeconds);
116 std::pair<DateTime, TimeSpan> DateTime::fromIsoString(
const char *str)
118 int values[9] = { 0 };
119 int *
const dayIndex = values + 2;
120 int *
const hourIndex = values + 3;
121 int *
const secondsIndex = values + 5;
122 int *
const miliSecondsIndex = values + 6;
123 int *
const deltaHourIndex = values + 7;
124 int *valueIndex = values;
125 bool deltaNegative =
false;
126 double miliSecondsFact = 100.0, miliSeconds = 0.0;
127 for (
const char *strIndex = str;; ++strIndex) {
128 const char c = *strIndex;
129 if (c <= '9' && c >=
'0') {
130 if (valueIndex == miliSecondsIndex) {
131 miliSeconds += (c -
'0') * miliSecondsFact;
132 miliSecondsFact /= 10;
135 *valueIndex += c -
'0';
137 }
else if (c ==
'T') {
138 if (++valueIndex != hourIndex) {
141 }
else if (c ==
'-') {
142 if (valueIndex < dayIndex) {
147 }
else if (c ==
'.') {
148 if (valueIndex != secondsIndex) {
153 }
else if (c ==
':') {
154 if (valueIndex < hourIndex) {
156 }
else if (valueIndex == secondsIndex) {
161 }
else if ((c ==
'+') && (++valueIndex == deltaHourIndex)) {
162 deltaNegative =
false;
163 }
else if ((c ==
'-') && (++valueIndex == deltaHourIndex)) {
164 deltaNegative =
true;
165 }
else if (c ==
'\0') {
171 deltaNegative && (*deltaHourIndex = -*deltaHourIndex);
172 return make_pair(DateTime::fromDateAndTime(values[0], values[1], *dayIndex, *hourIndex, values[4], *secondsIndex, miliSeconds),
173 TimeSpan::fromMinutes(*deltaHourIndex * 60 + values[8]));
184 toString(result, format, noMilliseconds);
195 stringstream s(stringstream::in | stringstream::out);
197 if (format == DateTimeOutputFormat::DateTimeAndWeekday || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
198 s << printDayOfWeek(dayOfWeek(), format == DateTimeOutputFormat::DateTimeAndShortWeekday) <<
' ';
199 if (format == DateTimeOutputFormat::DateOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
200 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
201 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day();
202 if (format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
203 || format == DateTimeOutputFormat::DateTimeAndShortWeekday)
205 if (format == DateTimeOutputFormat::TimeOnly || format == DateTimeOutputFormat::DateAndTime || format == DateTimeOutputFormat::DateTimeAndWeekday
206 || format == DateTimeOutputFormat::DateTimeAndShortWeekday) {
207 s << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' << setw(2) << second();
208 int ms = millisecond();
209 if (!noMilliseconds && ms > 0) {
210 s <<
'.' << setw(3) << ms;
220 string DateTime::toIsoString(
TimeSpan timeZoneDelta)
const 222 stringstream s(stringstream::in | stringstream::out);
224 s << setw(4) << year() <<
'-' << setw(2) << month() <<
'-' << setw(2) << day() <<
'T' << setw(2) << hour() <<
':' << setw(2) << minute() <<
':' 225 << setw(2) << second();
226 const int milli(millisecond());
227 const int micro(microsecond());
228 const int nano(nanosecond());
229 if (milli || micro || nano) {
230 s <<
'.' << setw(3) << milli;
232 s << setw(3) << micro;
234 s << nano / TimeSpan::nanosecondsPerTick;
238 if (!timeZoneDelta.
isNull()) {
239 s << (timeZoneDelta.
isNegative() ?
'-' :
'+');
240 s << setw(2) << timeZoneDelta.
hours() <<
':' << setw(2) << timeZoneDelta.
minutes();
252 const char *DateTime::printDayOfWeek(
DayOfWeek dayOfWeek,
bool abbreviation)
256 case DayOfWeek::Monday:
258 case DayOfWeek::Tuesday:
260 case DayOfWeek::Wednesday:
262 case DayOfWeek::Thursday:
264 case DayOfWeek::Friday:
266 case DayOfWeek::Saturday:
268 case DayOfWeek::Sunday:
273 case DayOfWeek::Monday:
275 case DayOfWeek::Tuesday:
277 case DayOfWeek::Wednesday:
279 case DayOfWeek::Thursday:
281 case DayOfWeek::Friday:
283 case DayOfWeek::Saturday:
285 case DayOfWeek::Sunday:
292 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_MAC) 300 clock_gettime(CLOCK_REALTIME, &t);
302 DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(t.tv_sec) * TimeSpan::m_ticksPerSecond + static_cast<uint64>(t.tv_nsec) / 100);
309 uint64 DateTime::dateToTicks(
int year,
int month,
int day)
317 const auto *daysToMonth =
reinterpret_cast<const int *
>(isLeapYear(year) ? m_daysToMonth366 : m_daysToMonth365);
318 int passedMonth = month - 1;
319 if (!
inRangeInclMax(day, 1, daysToMonth[month] - daysToMonth[passedMonth])) {
322 const auto passedYears =
static_cast<unsigned int>(year - 1);
323 const auto passedDays =
static_cast<unsigned int>(day - 1);
324 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400
325 + static_cast<unsigned int>(daysToMonth[passedMonth]) + passedDays)
326 * TimeSpan::m_ticksPerDay;
332 uint64 DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
346 return static_cast<uint64>(hour * TimeSpan::m_ticksPerHour) + static_cast<uint64>(minute * TimeSpan::m_ticksPerMinute)
347 +
static_cast<uint64>(second * TimeSpan::m_ticksPerSecond) + static_cast<uint64>(millisecond * TimeSpan::m_ticksPerMillisecond);
354 int DateTime::getDatePart(
DatePart part)
const 356 int fullDays = m_ticks / TimeSpan::m_ticksPerDay;
357 int full400YearBlocks = fullDays / m_daysPer400Years;
358 int daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
359 int full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
360 if (full100YearBlocks == 4) {
361 full100YearBlocks = 3;
363 int daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
364 int full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
365 int daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
366 int full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
367 if (full1YearBlocks == 4) {
370 if (part == DatePart::Year) {
371 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
373 int restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
374 if (part == DatePart::DayOfYear) {
377 const int *daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
379 while (restDays >= daysToMonth[month]) {
382 if (part == DatePart::Month) {
384 }
else if (part == DatePart::Day) {
385 return restDays - daysToMonth[month - 1] + 1;
constexpr bool isNegative() const
Returns ture if the time interval represented by the current TimeSpan class is negative.
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
Gets 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
Gets 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.
bool inRangeExclMax(num1 val, num2 min, num3 max)
bool inRangeInclMax(num1 val, num2 min, num3 max)
DayOfWeek
Specifies the day of the week.