Merge branch 'master' of https://github.com/microsoft/cpprestsdk
This commit is contained in:
Коммит
c8bf3357a7
|
@ -603,14 +603,21 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
datetime() : m_interval(0) {}
|
||||
datetime() : m_interval(0) { }
|
||||
|
||||
/// <summary>
|
||||
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 format.
|
||||
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 or ISO 8601 format.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <c>datetime</c> of zero if not successful.</returns>
|
||||
static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123);
|
||||
|
||||
/// <summary>
|
||||
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 or ISO 8601 format.
|
||||
/// </summary>
|
||||
/// <returns>Returns <c>datetime::maximum()</c> if not successful.</returns>
|
||||
static _ASYNCRTIMP datetime __cdecl from_string_maximum_error(const utility::string_t& timestring,
|
||||
date_format format = RFC_1123);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string representation of the <c>datetime</c>.
|
||||
/// </summary>
|
||||
|
@ -621,6 +628,8 @@ public:
|
|||
/// </summary>
|
||||
interval_type to_interval() const { return m_interval; }
|
||||
|
||||
static datetime from_interval(interval_type interval) { return datetime(interval); }
|
||||
|
||||
datetime operator-(interval_type value) const { return datetime(m_interval - value); }
|
||||
|
||||
datetime operator+(interval_type value) const { return datetime(m_interval + value); }
|
||||
|
@ -628,13 +637,13 @@ public:
|
|||
bool operator==(datetime dt) const { return m_interval == dt.m_interval; }
|
||||
|
||||
bool operator!=(const datetime& dt) const { return !(*this == dt); }
|
||||
|
||||
|
||||
bool operator>(const datetime& dt) const { return this->m_interval > dt.m_interval; }
|
||||
|
||||
|
||||
bool operator<(const datetime& dt) const { return this->m_interval < dt.m_interval; }
|
||||
|
||||
|
||||
bool operator>=(const datetime& dt) const { return this->m_interval >= dt.m_interval; }
|
||||
|
||||
|
||||
bool operator<=(const datetime& dt) const { return this->m_interval <= dt.m_interval; }
|
||||
|
||||
static interval_type from_milliseconds(unsigned int milliseconds) { return milliseconds * _msTicks; }
|
||||
|
@ -649,6 +658,8 @@ public:
|
|||
|
||||
bool is_initialized() const { return m_interval != 0; }
|
||||
|
||||
static datetime maximum() { return datetime(static_cast<interval_type>(-1)); }
|
||||
|
||||
private:
|
||||
friend int operator-(datetime t1, datetime t2);
|
||||
|
||||
|
@ -659,7 +670,7 @@ private:
|
|||
static const interval_type _dayTicks = 24 * 60 * 60 * _secondTicks;
|
||||
|
||||
// Private constructor. Use static methods to create an instance.
|
||||
datetime(interval_type interval) : m_interval(interval) {}
|
||||
datetime(interval_type interval) : m_interval(interval) { }
|
||||
|
||||
// Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
|
||||
interval_type m_interval;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "cpprest/astreambuf.h"
|
||||
#include <iosfwd>
|
||||
#include <cstdio>
|
||||
|
||||
namespace Concurrency
|
||||
{
|
||||
|
@ -1434,7 +1435,8 @@ static pplx::task<FloatingPoint> _extract_result(std::shared_ptr<_double_state<F
|
|||
|
||||
if (state->exponent_number >= 0)
|
||||
{
|
||||
result *= pow(FloatingPoint(10.0), state->exponent_number);
|
||||
result *= static_cast<FloatingPoint>(
|
||||
std::pow(static_cast<FloatingPoint>(10.0), static_cast<FloatingPoint>(state->exponent_number)));
|
||||
|
||||
#pragma push_macro("max")
|
||||
#undef max
|
||||
|
@ -1447,7 +1449,8 @@ static pplx::task<FloatingPoint> _extract_result(std::shared_ptr<_double_state<F
|
|||
{
|
||||
bool is_zero = (result == 0);
|
||||
|
||||
result /= pow(FloatingPoint(10.0), -state->exponent_number);
|
||||
result /= static_cast<FloatingPoint>(
|
||||
std::pow(static_cast<FloatingPoint>(10.0), static_cast<FloatingPoint>(-state->exponent_number)));
|
||||
|
||||
if (!is_zero && result > -std::numeric_limits<FloatingPoint>::denorm_min() &&
|
||||
result < std::numeric_limits<FloatingPoint>::denorm_min())
|
||||
|
|
|
@ -177,8 +177,8 @@ scoped_c_thread_locale::~scoped_c_thread_locale()
|
|||
}
|
||||
}
|
||||
#elif (defined(ANDROID) || defined(__ANDROID__))
|
||||
scoped_c_thread_locale::scoped_c_thread_locale() {}
|
||||
scoped_c_thread_locale::~scoped_c_thread_locale() {}
|
||||
scoped_c_thread_locale::scoped_c_thread_locale() { }
|
||||
scoped_c_thread_locale::~scoped_c_thread_locale() { }
|
||||
#else
|
||||
scoped_c_thread_locale::scoped_c_thread_locale() : m_prevLocale(nullptr)
|
||||
{
|
||||
|
@ -620,7 +620,11 @@ utf16string __cdecl conversions::to_utf16string(const std::string& value) { retu
|
|||
|
||||
static const int64_t NtToUnixOffsetSeconds = 11644473600; // diff between windows and unix epochs (seconds)
|
||||
|
||||
static bool year_is_leap_year(int year) { return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); }
|
||||
static bool year_is_leap_year_1601(int yearsSince1601)
|
||||
{
|
||||
int decimalYear = yearsSince1601 + 1601;
|
||||
return (decimalYear % 4 == 0 && (decimalYear % 100 != 0 || decimalYear % 400 == 0));
|
||||
}
|
||||
|
||||
static const int SecondsInMinute = 60;
|
||||
static const int SecondsInHour = SecondsInMinute * 60;
|
||||
|
@ -635,26 +639,18 @@ static const int SecondsInYear = SecondsInDay * DaysInYear;
|
|||
static const int SecondsIn4Years = SecondsInDay * DaysIn4Years;
|
||||
static const int64_t SecondsIn100Years = static_cast<int64_t>(SecondsInDay) * DaysIn100Years;
|
||||
static const int64_t SecondsIn400Years = static_cast<int64_t>(SecondsInDay) * DaysIn400Years;
|
||||
static const int64_t SecondsFrom1900To2001 = INT64_C(3187296000);
|
||||
|
||||
static const int64_t NtTo1900OffsetInterval = INT64_C(0x014F373BFDE04000);
|
||||
|
||||
static int count_leap_years(const int yearsSince1900)
|
||||
static int count_leap_years_1601(int yearsSince1601)
|
||||
{
|
||||
int tmpYears = yearsSince1900 + 299; // shift into 1601, the first 400 year cycle including 1900
|
||||
|
||||
int year400 = tmpYears / 400;
|
||||
tmpYears -= year400 * 400;
|
||||
int year400 = yearsSince1601 / 400;
|
||||
yearsSince1601 -= year400 * 400;
|
||||
int result = year400 * 97;
|
||||
|
||||
int year100 = tmpYears / 100;
|
||||
tmpYears -= year100 * 100;
|
||||
int year100 = yearsSince1601 / 100;
|
||||
yearsSince1601 -= year100 * 100;
|
||||
result += year100 * 24;
|
||||
|
||||
result += tmpYears / 4;
|
||||
|
||||
// subtract off leap years from 1601
|
||||
result -= 72;
|
||||
result += yearsSince1601 / 4;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -720,20 +716,16 @@ struct compute_year_result
|
|||
int secondsLeftThisYear;
|
||||
};
|
||||
|
||||
static const int64_t secondsFrom1601To1900 = INT64_C(9435484800);
|
||||
|
||||
static compute_year_result compute_year(int64_t secondsSince1900)
|
||||
static compute_year_result compute_year_1601(int64_t secondsSince1601)
|
||||
{
|
||||
int64_t secondsLeft = secondsSince1900 + secondsFrom1601To1900; // shift to start of this 400 year cycle
|
||||
int year400 = static_cast<int>(secondsSince1601 / SecondsIn400Years);
|
||||
secondsSince1601 -= year400 * SecondsIn400Years;
|
||||
|
||||
int year400 = static_cast<int>(secondsLeft / SecondsIn400Years);
|
||||
secondsLeft -= year400 * SecondsIn400Years;
|
||||
int year100 = static_cast<int>(secondsSince1601 / SecondsIn100Years);
|
||||
secondsSince1601 -= year100 * SecondsIn100Years;
|
||||
|
||||
int year100 = static_cast<int>(secondsLeft / SecondsIn100Years);
|
||||
secondsLeft -= year100 * SecondsIn100Years;
|
||||
|
||||
int year4 = static_cast<int>(secondsLeft / SecondsIn4Years);
|
||||
int secondsInt = static_cast<int>(secondsLeft - year4 * SecondsIn4Years);
|
||||
int year4 = static_cast<int>(secondsSince1601 / SecondsIn4Years);
|
||||
int secondsInt = static_cast<int>(secondsSince1601 - year4 * SecondsIn4Years);
|
||||
|
||||
int year1 = secondsInt / SecondsInYear;
|
||||
if (year1 == 4)
|
||||
|
@ -743,23 +735,44 @@ static compute_year_result compute_year(int64_t secondsSince1900)
|
|||
}
|
||||
|
||||
secondsInt -= year1 * SecondsInYear;
|
||||
|
||||
// shift back to 1900 base from 1601:
|
||||
return {year400 * 400 + year100 * 100 + year4 * 4 + year1 - 299, secondsInt};
|
||||
return {year400 * 400 + year100 * 100 + year4 * 4 + year1, secondsInt};
|
||||
}
|
||||
|
||||
// The constant below was calculated by running the following test program on a Windows machine:
|
||||
// #include <windows.h>
|
||||
// #include <stdio.h>
|
||||
|
||||
// int main() {
|
||||
// SYSTEMTIME st;
|
||||
// st.wYear = 9999;
|
||||
// st.wMonth = 12;
|
||||
// st.wDayOfWeek = 5;
|
||||
// st.wDay = 31;
|
||||
// st.wHour = 23;
|
||||
// st.wMinute = 59;
|
||||
// st.wSecond = 59;
|
||||
// st.wMilliseconds = 999;
|
||||
|
||||
// unsigned long long ft;
|
||||
// if (SystemTimeToFileTime(&st, reinterpret_cast<FILETIME*>(&ft))) {
|
||||
// printf("0x%016llX\n", ft);
|
||||
// } else {
|
||||
// puts("failed!");
|
||||
// }
|
||||
// }
|
||||
|
||||
utility::string_t datetime::to_string(date_format format) const
|
||||
{
|
||||
if (m_interval > INT64_C(2650467743990000000))
|
||||
const int64_t interval = static_cast<int64_t>(m_interval);
|
||||
if (interval > INT64_C(0x24C85A5ED1C018F0))
|
||||
{
|
||||
throw std::out_of_range("The requested year exceeds the year 9999.");
|
||||
}
|
||||
|
||||
const int64_t epochAdjusted = static_cast<int64_t>(m_interval) - NtTo1900OffsetInterval;
|
||||
const int64_t secondsSince1900 = epochAdjusted / _secondTicks; // convert to seconds
|
||||
const int fracSec = static_cast<int>(epochAdjusted % _secondTicks);
|
||||
const int64_t secondsSince1601 = interval / _secondTicks; // convert to seconds
|
||||
const int fracSec = static_cast<int>(interval % _secondTicks);
|
||||
|
||||
const auto yearData = compute_year(secondsSince1900);
|
||||
const auto yearData = compute_year_1601(secondsSince1601);
|
||||
const int year = yearData.year;
|
||||
const int yearDay = yearData.secondsLeftThisYear / SecondsInDay;
|
||||
int leftover = yearData.secondsLeftThisYear % SecondsInDay;
|
||||
|
@ -768,7 +781,7 @@ utility::string_t datetime::to_string(date_format format) const
|
|||
const int minute = leftover / SecondsInMinute;
|
||||
leftover = leftover % SecondsInMinute;
|
||||
|
||||
const auto& monthTable = year_is_leap_year(year) ? cumulative_days_to_month_leap : cumulative_days_to_month;
|
||||
const auto& monthTable = year_is_leap_year_1601(year) ? cumulative_days_to_month_leap : cumulative_days_to_month;
|
||||
int month = 0;
|
||||
while (month < 11 && monthTable[month + 1] <= yearDay)
|
||||
{
|
||||
|
@ -776,7 +789,7 @@ utility::string_t datetime::to_string(date_format format) const
|
|||
}
|
||||
|
||||
const auto monthDay = yearDay - monthTable[month] + 1;
|
||||
const auto weekday = static_cast<int>((secondsSince1900 / SecondsInDay + 1) % 7);
|
||||
const auto weekday = static_cast<int>((secondsSince1601 / SecondsInDay + 1) % 7);
|
||||
|
||||
char outBuffer[38]; // Thu, 01 Jan 1970 00:00:00 GMT\0
|
||||
// 1970-01-01T00:00:00.1234567Z\0
|
||||
|
@ -791,7 +804,7 @@ utility::string_t datetime::to_string(date_format format) const
|
|||
dayNames + 4 * weekday,
|
||||
monthDay,
|
||||
monthNames + 4 * month,
|
||||
year + 1900,
|
||||
year + 1601,
|
||||
hour,
|
||||
minute,
|
||||
leftover);
|
||||
|
@ -801,7 +814,7 @@ utility::string_t datetime::to_string(date_format format) const
|
|||
dayNames + 4 * weekday,
|
||||
monthDay,
|
||||
monthNames + 4 * month,
|
||||
year + 1900,
|
||||
year + 1601,
|
||||
hour,
|
||||
minute,
|
||||
leftover);
|
||||
|
@ -815,7 +828,7 @@ utility::string_t datetime::to_string(date_format format) const
|
|||
sprintf_s(outCursor,
|
||||
20,
|
||||
"%04d-%02d-%02dT%02d:%02d:%02d",
|
||||
year + 1900,
|
||||
year + 1601,
|
||||
month + 1,
|
||||
monthDay,
|
||||
hour,
|
||||
|
@ -823,7 +836,7 @@ utility::string_t datetime::to_string(date_format format) const
|
|||
leftover);
|
||||
#else // ^^^ _MSC_VER // !_MSC_VER vvv
|
||||
sprintf(
|
||||
outCursor, "%04d-%02d-%02dT%02d:%02d:%02d", year + 1900, month + 1, monthDay, hour, minute, leftover);
|
||||
outCursor, "%04d-%02d-%02dT%02d:%02d:%02d", year + 1601, month + 1, monthDay, hour, minute, leftover);
|
||||
#endif // _MSC_VER
|
||||
outCursor += 19;
|
||||
if (fracSec != 0)
|
||||
|
@ -889,12 +902,12 @@ static const unsigned char max_days_in_month[12] = {
|
|||
31 // Dec
|
||||
};
|
||||
|
||||
static bool validate_day_month(int day, int month, int year)
|
||||
static bool validate_day_month_1601(int day, int month, int year)
|
||||
{
|
||||
int maxDaysThisMonth;
|
||||
if (month == 1)
|
||||
{ // Feb needs leap year testing
|
||||
maxDaysThisMonth = 28 + year_is_leap_year(year);
|
||||
maxDaysThisMonth = 28 + year_is_leap_year_1601(year);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -904,9 +917,9 @@ static bool validate_day_month(int day, int month, int year)
|
|||
return day >= 1 && day <= maxDaysThisMonth;
|
||||
}
|
||||
|
||||
static int get_year_day(int month, int monthDay, int year)
|
||||
static int get_year_day_1601(int month, int monthDay, int year)
|
||||
{
|
||||
return cumulative_days_to_month[month] + monthDay + (year_is_leap_year(year) && month > 1) - 1;
|
||||
return cumulative_days_to_month[month] + monthDay + (year_is_leap_year_1601(year) && month > 1) - 1;
|
||||
}
|
||||
|
||||
template<class CharT>
|
||||
|
@ -985,11 +998,21 @@ zone = "UT" / "GMT" ; Universal Time
|
|||
; hours+min. (HHMM)
|
||||
*/
|
||||
|
||||
|
||||
datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format)
|
||||
{
|
||||
datetime result;
|
||||
int64_t secondsSince1900;
|
||||
auto result = from_string_maximum_error(dateString, format);
|
||||
if (result == datetime::maximum())
|
||||
{
|
||||
return datetime();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& dateString, date_format format)
|
||||
{
|
||||
datetime result = datetime::maximum();
|
||||
int64_t secondsSince1601;
|
||||
uint64_t fracSec = 0;
|
||||
auto str = dateString.c_str();
|
||||
if (format == RFC_1123)
|
||||
|
@ -1056,19 +1079,21 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
|
||||
int year = (str[0] - _XPLATSTR('0')) * 1000 + (str[1] - _XPLATSTR('0')) * 100 + (str[2] - _XPLATSTR('0')) * 10 +
|
||||
(str[3] - _XPLATSTR('0'));
|
||||
if (year < 1900)
|
||||
if (year < 1601)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
year -= 1601;
|
||||
|
||||
// days in month validity check
|
||||
if (!validate_day_month(monthDay, month, year))
|
||||
if (!validate_day_month_1601(monthDay, month, year))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
str += 5; // parsed year
|
||||
const int yearDay = get_year_day(month, monthDay, year);
|
||||
const int yearDay = get_year_day_1601(month, monthDay, year);
|
||||
|
||||
if (!ascii_isdigit2(str[0]) || !ascii_isdigit(str[1]) || str[2] != _XPLATSTR(':') || !ascii_isdigit5(str[3]) ||
|
||||
!ascii_isdigit(str[4]))
|
||||
|
@ -1112,12 +1137,11 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
return result;
|
||||
}
|
||||
|
||||
year -= 1900;
|
||||
int daysSince1900 = year * DaysInYear + count_leap_years(year) + yearDay;
|
||||
int daysSince1601 = year * DaysInYear + count_leap_years_1601(year) + yearDay;
|
||||
|
||||
if (parsedWeekday != 7)
|
||||
{
|
||||
const int actualWeekday = (daysSince1900 + 1) % 7;
|
||||
const int actualWeekday = (daysSince1601 + 1) % 7;
|
||||
|
||||
if (parsedWeekday != actualWeekday)
|
||||
{
|
||||
|
@ -1125,8 +1149,8 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
}
|
||||
}
|
||||
|
||||
secondsSince1900 =
|
||||
static_cast<int64_t>(daysSince1900) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec;
|
||||
secondsSince1601 =
|
||||
static_cast<int64_t>(daysSince1601) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec;
|
||||
|
||||
if (!string_starts_with(str, "GMT") && !string_starts_with(str, "UT"))
|
||||
{
|
||||
|
@ -1166,8 +1190,8 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
return result;
|
||||
}
|
||||
|
||||
secondsSince1900 = timezone_adjust(secondsSince1900, static_cast<unsigned char>(tzCh), tzHours, tzMinutes);
|
||||
if (secondsSince1900 < 0)
|
||||
secondsSince1601 = timezone_adjust(secondsSince1601, static_cast<unsigned char>(tzCh), tzHours, tzMinutes);
|
||||
if (secondsSince1601 < 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
@ -1183,11 +1207,13 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
|
||||
int year = (str[0] - _XPLATSTR('0')) * 1000 + (str[1] - _XPLATSTR('0')) * 100 + (str[2] - _XPLATSTR('0')) * 10 +
|
||||
(str[3] - _XPLATSTR('0'));
|
||||
if (year < 1900)
|
||||
if (year < 1601)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
year -= 1601;
|
||||
|
||||
str += 4;
|
||||
if (*str == _XPLATSTR('-'))
|
||||
{
|
||||
|
@ -1221,24 +1247,22 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
}
|
||||
|
||||
int monthDay = atoi2(str);
|
||||
if (!validate_day_month(monthDay, month, year))
|
||||
if (!validate_day_month_1601(monthDay, month, year))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
const int yearDay = get_year_day(month, monthDay, year);
|
||||
const int yearDay = get_year_day_1601(month, monthDay, year);
|
||||
|
||||
str += 2;
|
||||
year -= 1900;
|
||||
int daysSince1900 = year * DaysInYear + count_leap_years(year) + yearDay;
|
||||
int daysSince1601 = year * DaysInYear + count_leap_years_1601(year) + yearDay;
|
||||
|
||||
if (str[0] != _XPLATSTR('T') && str[0] != _XPLATSTR('t'))
|
||||
{
|
||||
// No time
|
||||
secondsSince1900 = static_cast<int64_t>(daysSince1900) * SecondsInDay;
|
||||
secondsSince1601 = static_cast<int64_t>(daysSince1601) * SecondsInDay;
|
||||
|
||||
result.m_interval =
|
||||
static_cast<interval_type>(secondsSince1900 * _secondTicks + fracSec + NtTo1900OffsetInterval);
|
||||
result.m_interval = static_cast<interval_type>(secondsSince1601 * _secondTicks + fracSec);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1327,8 +1351,8 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
}
|
||||
}
|
||||
|
||||
secondsSince1900 =
|
||||
static_cast<int64_t>(daysSince1900) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec;
|
||||
secondsSince1601 =
|
||||
static_cast<int64_t>(daysSince1601) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec;
|
||||
|
||||
if (str[0] == _XPLATSTR('Z') || str[0] == _XPLATSTR('z'))
|
||||
{
|
||||
|
@ -1343,8 +1367,8 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
return result;
|
||||
}
|
||||
|
||||
secondsSince1900 = timezone_adjust(secondsSince1900, offsetDirection, atoi2(str + 1), atoi2(str + 4));
|
||||
if (secondsSince1900 < 0)
|
||||
secondsSince1601 = timezone_adjust(secondsSince1601, offsetDirection, atoi2(str + 1), atoi2(str + 4));
|
||||
if (secondsSince1601 < 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
@ -1359,7 +1383,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date
|
|||
throw std::invalid_argument("unrecognized date format");
|
||||
}
|
||||
|
||||
result.m_interval = static_cast<interval_type>(secondsSince1900 * _secondTicks + fracSec + NtTo1900OffsetInterval);
|
||||
result.m_interval = static_cast<interval_type>(secondsSince1601 * _secondTicks + fracSec);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
****/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
|
@ -81,6 +82,10 @@ SUITE(datetime)
|
|||
auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601);
|
||||
utility::string_t str2 = dt.to_string(utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(str2, strExpected);
|
||||
|
||||
auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::ISO_8601);
|
||||
utility::string_t str3 = dt_me.to_string(utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(str3, strExpected);
|
||||
}
|
||||
|
||||
void TestDateTimeRoundtrip(utility::string_t str) { TestDateTimeRoundtrip(str, str); }
|
||||
|
@ -123,32 +128,26 @@ SUITE(datetime)
|
|||
TestDateTimeRoundtrip(_XPLATSTR("2013-11-19T14:30:59.5Z"));
|
||||
}
|
||||
|
||||
TEST(parsing_time_roundtrip_year_1900)
|
||||
{
|
||||
TestDateTimeRoundtrip(_XPLATSTR("1900-01-01T00:00:00Z"));
|
||||
}
|
||||
TEST(parsing_time_roundtrip_year_1900) { TestDateTimeRoundtrip(_XPLATSTR("1900-01-01T00:00:00Z")); }
|
||||
|
||||
TEST(parsing_time_roundtrip_year_9999)
|
||||
{
|
||||
TestDateTimeRoundtrip(_XPLATSTR("9999-12-31T23:59:59Z"));
|
||||
}
|
||||
TEST(parsing_time_roundtrip_year_9999) { TestDateTimeRoundtrip(_XPLATSTR("9999-12-31T23:59:59Z")); }
|
||||
|
||||
TEST(parsing_time_roundtrip_year_2016)
|
||||
{
|
||||
TestDateTimeRoundtrip(_XPLATSTR("2016-12-31T20:59:59Z"));
|
||||
}
|
||||
TEST(parsing_time_roundtrip_year_2016) { TestDateTimeRoundtrip(_XPLATSTR("2016-12-31T20:59:59Z")); }
|
||||
|
||||
TEST(parsing_time_roundtrip_year_2020)
|
||||
{
|
||||
TestDateTimeRoundtrip(_XPLATSTR("2020-12-31T20:59:59Z"));
|
||||
}
|
||||
TEST(parsing_time_roundtrip_year_2020) { TestDateTimeRoundtrip(_XPLATSTR("2020-12-31T20:59:59Z")); }
|
||||
|
||||
TEST(parsing_time_roundtrip_year_2021)
|
||||
{
|
||||
TestDateTimeRoundtrip(_XPLATSTR("2021-01-01T20:59:59Z"));
|
||||
}
|
||||
TEST(parsing_time_roundtrip_year_2021) { TestDateTimeRoundtrip(_XPLATSTR("2021-01-01T20:59:59Z")); }
|
||||
|
||||
TEST(emitting_time_correct_day) {
|
||||
TEST(parsing_time_roundtrip_year_1601) { TestDateTimeRoundtrip(_XPLATSTR("1601-01-01T00:00:00Z")); }
|
||||
|
||||
TEST(parsing_time_roundtrip_year_1602) { TestDateTimeRoundtrip(_XPLATSTR("1602-01-01T00:00:00Z")); }
|
||||
|
||||
TEST(parsing_time_roundtrip_year_1603) { TestDateTimeRoundtrip(_XPLATSTR("1603-01-01T00:00:00Z")); }
|
||||
|
||||
TEST(parsing_time_roundtrip_year_1604) { TestDateTimeRoundtrip(_XPLATSTR("1604-01-01T00:00:00Z")); }
|
||||
|
||||
TEST(emitting_time_correct_day)
|
||||
{
|
||||
const auto test = utility::datetime() + UINT64_C(132004507640000000); // 2019-04-22T23:52:44 is a Monday
|
||||
const auto actual = test.to_string(utility::datetime::RFC_1123);
|
||||
const utility::string_t expected(_XPLATSTR("Mon"));
|
||||
|
@ -296,13 +295,13 @@ SUITE(datetime)
|
|||
_XPLATSTR("Thu, 01 Jan 1970 00:00:00 G"),
|
||||
_XPLATSTR("Thu, 01 Jan 1970 00:00:00 GM"),
|
||||
_XPLATSTR("Fri, 01 Jan 1970 00:00:00 GMT"), // wrong day
|
||||
_XPLATSTR("01 Jan 1899 00:00:00 GMT"), // year too small
|
||||
_XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad
|
||||
_XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small
|
||||
_XPLATSTR("32 Jan 1971 00:00:00 GMT"), // day too big
|
||||
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb
|
||||
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb (non-leap year)
|
||||
_XPLATSTR("32 Mar 1971 00:00:00 GMT"), // other months
|
||||
_XPLATSTR("01 Jan 1600 00:00:00 GMT"), // year too small
|
||||
_XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad
|
||||
_XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small
|
||||
_XPLATSTR("32 Jan 1971 00:00:00 GMT"), // day too big
|
||||
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb
|
||||
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb (non-leap year)
|
||||
_XPLATSTR("32 Mar 1971 00:00:00 GMT"), // other months
|
||||
_XPLATSTR("31 Apr 1971 00:00:00 GMT"),
|
||||
_XPLATSTR("32 May 1971 00:00:00 GMT"),
|
||||
_XPLATSTR("31 Jun 1971 00:00:00 GMT"),
|
||||
|
@ -317,8 +316,8 @@ SUITE(datetime)
|
|||
_XPLATSTR("01 Jan 1971 00:60:00 GMT"), // minute too big
|
||||
_XPLATSTR("01 Jan 1971 00:00:70 GMT"), // second too big
|
||||
_XPLATSTR("01 Jan 1971 00:00:61 GMT"),
|
||||
_XPLATSTR("01 Jan 1899 00:00:00 GMT"), // underflow
|
||||
_XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz
|
||||
_XPLATSTR("01 Jan 1600 00:00:00 GMT"), // underflow
|
||||
_XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz
|
||||
_XPLATSTR("14 Jan 2019 23:16:21 G0100"), // bad tzoffsets
|
||||
_XPLATSTR("01 Jan 1970 00:00:00 +2400"),
|
||||
_XPLATSTR("01 Jan 1970 00:00:00 -3000"),
|
||||
|
@ -332,6 +331,8 @@ SUITE(datetime)
|
|||
{
|
||||
auto dt = utility::datetime::from_string(str, utility::datetime::RFC_1123);
|
||||
VERIFY_ARE_EQUAL(0, dt.to_interval());
|
||||
auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::RFC_1123);
|
||||
VERIFY_ARE_EQUAL(utility::datetime::maximum(), dt_me);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,7 +462,7 @@ SUITE(datetime)
|
|||
_XPLATSTR("1970-01-01T00:00:"),
|
||||
_XPLATSTR("1970-01-01T00:00:0"),
|
||||
// _XPLATSTR("1970-01-01T00:00:00"), // accepted as invalid timezone above
|
||||
_XPLATSTR("1899-01-01T00:00:00Z"), // year too small
|
||||
_XPLATSTR("1600-01-01T00:00:00Z"), // year too small
|
||||
_XPLATSTR("1971-00-01T00:00:00Z"), // month too small
|
||||
_XPLATSTR("1971-20-01T00:00:00Z"), // month too big
|
||||
_XPLATSTR("1971-13-01T00:00:00Z"),
|
||||
|
@ -484,8 +485,8 @@ SUITE(datetime)
|
|||
_XPLATSTR("1971-01-01T00:60:00Z"), // minute too big
|
||||
_XPLATSTR("1971-01-01T00:00:70Z"), // second too big
|
||||
_XPLATSTR("1971-01-01T00:00:61Z"),
|
||||
_XPLATSTR("1899-01-01T00:00:00Z"), // underflow
|
||||
_XPLATSTR("1900-01-01T00:00:00+00:01"), // time zone underflow
|
||||
_XPLATSTR("1600-01-01T00:00:00Z"), // underflow
|
||||
_XPLATSTR("1601-01-01T00:00:00+00:01"), // time zone underflow
|
||||
// _XPLATSTR("1970-01-01T00:00:00.Z"), // accepted as invalid timezone above
|
||||
_XPLATSTR("1970-01-01T00:00:00+24:00"), // bad tzoffsets
|
||||
_XPLATSTR("1970-01-01T00:00:00-30:00"),
|
||||
|
@ -499,9 +500,55 @@ SUITE(datetime)
|
|||
{
|
||||
auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(dt.to_interval(), 0);
|
||||
auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(dt_me, utility::datetime::maximum());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(can_emit_nt_epoch_zero_rfc_1123)
|
||||
{
|
||||
auto result = utility::datetime {}.to_string(utility::datetime::RFC_1123);
|
||||
VERIFY_ARE_EQUAL(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"), result);
|
||||
}
|
||||
|
||||
TEST(can_emit_nt_epoch_zero_iso_8601)
|
||||
{
|
||||
auto result = utility::datetime {}.to_string(utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(_XPLATSTR("1601-01-01T00:00:00Z"), result);
|
||||
}
|
||||
|
||||
TEST(can_emit_year_9999_rfc_1123)
|
||||
{
|
||||
auto result =
|
||||
utility::datetime::from_interval(INT64_C(0x24C85A5ED1C018F0)).to_string(utility::datetime::RFC_1123);
|
||||
VERIFY_ARE_EQUAL(_XPLATSTR("Fri, 31 Dec 9999 23:59:59 GMT"), result);
|
||||
}
|
||||
|
||||
TEST(can_emit_year_9999_iso_8601)
|
||||
{
|
||||
auto result =
|
||||
utility::datetime::from_interval(INT64_C(0x24C85A5ED1C018F0)).to_string(utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(_XPLATSTR("9999-12-31T23:59:59.999Z"), result);
|
||||
}
|
||||
|
||||
TEST(can_parse_nt_epoch_zero_rfc_1123)
|
||||
{
|
||||
auto dt =
|
||||
utility::datetime::from_string(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"), utility::datetime::RFC_1123);
|
||||
VERIFY_ARE_EQUAL(0U, dt.to_interval());
|
||||
auto dt_me = utility::datetime::from_string_maximum_error(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"),
|
||||
utility::datetime::RFC_1123);
|
||||
VERIFY_ARE_EQUAL(0U, dt_me.to_interval());
|
||||
}
|
||||
|
||||
TEST(can_parse_nt_epoch_zero_iso_8601)
|
||||
{
|
||||
auto dt = utility::datetime::from_string(_XPLATSTR("1601-01-01T00:00:00Z"), utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(0U, dt.to_interval());
|
||||
auto dt_me = utility::datetime::from_string_maximum_error(_XPLATSTR("1601-01-01T00:00:00Z"),
|
||||
utility::datetime::ISO_8601);
|
||||
VERIFY_ARE_EQUAL(0U, dt_me.to_interval());
|
||||
}
|
||||
} // SUITE(datetime)
|
||||
|
||||
} // namespace utils_tests
|
||||
|
|
2
vcpkg
2
vcpkg
|
@ -1 +1 @@
|
|||
Subproject commit 6709d3d7d0cba96508ba3606f810ab562ea32556
|
||||
Subproject commit b759049a36728d18260963799a56e6b19cb4a2ef
|
Загрузка…
Ссылка в новой задаче