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() <<
'.' << setw(3) << millisecond();
226 if (!timeZoneDelta.
isNull()) {
227 s << (timeZoneDelta.
isNegative() ?
'-' :
'+');
228 s << setw(2) << timeZoneDelta.
hours() <<
':' << setw(2) << timeZoneDelta.
minutes();
240 const char *DateTime::printDayOfWeek(
DayOfWeek dayOfWeek,
bool abbreviation)
244 case DayOfWeek::Monday:
246 case DayOfWeek::Tuesday:
248 case DayOfWeek::Wednesday:
250 case DayOfWeek::Thursday:
252 case DayOfWeek::Friday:
254 case DayOfWeek::Saturday:
256 case DayOfWeek::Sunday:
261 case DayOfWeek::Monday:
263 case DayOfWeek::Tuesday:
265 case DayOfWeek::Wednesday:
267 case DayOfWeek::Thursday:
269 case DayOfWeek::Friday:
271 case DayOfWeek::Saturday:
273 case DayOfWeek::Sunday:
280 #if defined(PLATFORM_UNIX) && !defined(PLATFORM_MAC) 288 clock_gettime(CLOCK_REALTIME, &t);
290 DateTime::unixEpochStart().totalTicks() + static_cast<uint64>(t.tv_sec) * TimeSpan::m_ticksPerSecond + static_cast<uint64>(t.tv_nsec) / 100);
297 uint64 DateTime::dateToTicks(
int year,
int month,
int day)
305 const int *daysToMonth = isLeapYear(year) ? m_daysToMonth366 : m_daysToMonth365;
306 int passedMonth = month - 1;
307 if (!
inRangeInclMax(day, 1, daysToMonth[month] - daysToMonth[passedMonth])) {
310 int passedYears = year - 1;
311 int passedDays = day - 1;
312 return (passedYears * m_daysPerYear + passedYears / 4 - passedYears / 100 + passedYears / 400 + daysToMonth[passedMonth] + passedDays)
313 * TimeSpan::m_ticksPerDay;
319 uint64 DateTime::timeToTicks(
int hour,
int minute,
int second,
double millisecond)
333 return (hour * TimeSpan::m_ticksPerHour) + (minute * TimeSpan::m_ticksPerMinute) + (second * TimeSpan::m_ticksPerSecond)
334 + (
uint64)(millisecond * (
double)TimeSpan::m_ticksPerMillisecond);
341 int DateTime::getDatePart(
DatePart part)
const 343 int fullDays = m_ticks / TimeSpan::m_ticksPerDay;
344 int full400YearBlocks = fullDays / m_daysPer400Years;
345 int daysMinusFull400YearBlocks = fullDays - full400YearBlocks * m_daysPer400Years;
346 int full100YearBlocks = daysMinusFull400YearBlocks / m_daysPer100Years;
347 if (full100YearBlocks == 4) {
348 full100YearBlocks = 3;
350 int daysMinusFull100YearBlocks = daysMinusFull400YearBlocks - full100YearBlocks * m_daysPer100Years;
351 int full4YearBlocks = daysMinusFull100YearBlocks / m_daysPer4Years;
352 int daysMinusFull4YearBlocks = daysMinusFull100YearBlocks - full4YearBlocks * m_daysPer4Years;
353 int full1YearBlocks = daysMinusFull4YearBlocks / m_daysPerYear;
354 if (full1YearBlocks == 4) {
357 if (part == DatePart::Year) {
358 return full400YearBlocks * 400 + full100YearBlocks * 100 + full4YearBlocks * 4 + full1YearBlocks + 1;
360 int restDays = daysMinusFull4YearBlocks - full1YearBlocks * m_daysPerYear;
361 if (part == DatePart::DayOfYear) {
364 const int *daysToMonth = (full1YearBlocks == 3 && (full4YearBlocks != 24 || full100YearBlocks == 3)) ? m_daysToMonth366 : m_daysToMonth365;
366 while (restDays >= daysToMonth[month]) {
369 if (part == DatePart::Month) {
371 }
else if (part == DatePart::Day) {
372 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.