[oe] [meta-oe][PATCH] cpprest: fix build failure on 32bit systems, with upstream merged patch

Paul Barker paul at betafive.co.uk
Tue Apr 2 08:51:08 UTC 2019


On 01/04/2019 14:25, Gianfranco Costamagna wrote:
> ---

You're missing a Signed-off-by tag here.

>   .../cpprest/cpprest/1094.patch                |  307 ++++
>   ...0e5b33dfdbd501d618cd7e7498148ffbd559.patch |   26 -
>   ...9f8e214516d2c19aa6ef831ee874a58c0479.patch | 1557 -----------------
>   .../cpprest/cpprest_2.10.12.bb                |    4 +-
>   4 files changed, 308 insertions(+), 1586 deletions(-)
>   create mode 100644 meta-oe/recipes-support/cpprest/cpprest/1094.patch
>   delete mode 100644 meta-oe/recipes-support/cpprest/cpprest/revert-9b670e5b33dfdbd501d618cd7e7498148ffbd559.patch
>   delete mode 100644 meta-oe/recipes-support/cpprest/cpprest/revert-f10d9f8e214516d2c19aa6ef831ee874a58c0479.patch
> 
> diff --git a/meta-oe/recipes-support/cpprest/cpprest/1094.patch b/meta-oe/recipes-support/cpprest/cpprest/1094.patch
> new file mode 100644
> index 000000000..3daad97f0
> --- /dev/null
> +++ b/meta-oe/recipes-support/cpprest/cpprest/1094.patch
> @@ -0,0 +1,307 @@
> +From d672de675a16e5ab9efcf783705cbd171f38188e Mon Sep 17 00:00:00 2001
> +From: "Billy O'Neal (VC LIBS)" <bion at microsoft.com>
> +Date: Thu, 28 Mar 2019 15:17:12 -0700
> +Subject: [PATCH] Avoid tripping over 32 bit time_t mistakes.
> +
> +Resolves https://github.com/Microsoft/cpprestsdk/issues/1090

Please add an Upstream-status tag to this patch [1].

[1]: 
https://www.openembedded.org/wiki/Commit_Patch_Message_Guidelines#Patch_Header_Recommendations:_Upstream-Status

> +---
> + Release/src/utilities/asyncrt_utils.cpp     |  30 ++---
> + Release/tests/functional/utils/datetime.cpp | 140 ++++++++++----------
> + 2 files changed, 84 insertions(+), 86 deletions(-)
> +
> +diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp
> +index 4a692e5fa..986b64bb7 100644
> +--- a/Release/src/utilities/asyncrt_utils.cpp
> ++++ b/Release/src/utilities/asyncrt_utils.cpp
> +@@ -618,7 +618,7 @@ std::string __cdecl conversions::to_utf8string(const utf16string& value) { retur
> +
> + utf16string __cdecl conversions::to_utf16string(const std::string& value) { return utf8_to_utf16(value); }
> +
> +-static const uint64_t ntToUnixOffsetSeconds = 11644473600U; // diff between windows and unix epochs (seconds)
> ++static const int64_t ntToUnixOffsetSeconds = 11644473600; // diff between windows and unix epochs (seconds)
> +
> + datetime __cdecl datetime::utc_now()
> + {
> +@@ -634,10 +634,10 @@ datetime __cdecl datetime::utc_now()
> + #else // LINUX
> +     struct timeval time;
> +     gettimeofday(&time, nullptr);
> +-    uint64_t result = ntToUnixOffsetSeconds + time.tv_sec;
> ++    int64_t result = ntToUnixOffsetSeconds + time.tv_sec;
> +     result *= _secondTicks;      // convert to 10e-7
> +     result += time.tv_usec * 10; // convert and add microseconds, 10e-6 to 10e-7
> +-    return datetime(result);
> ++    return datetime(static_cast<interval_type>(result));
> + #endif
> + }
> +
> +@@ -646,7 +646,7 @@ static const char monthNames[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0O
> +
> + utility::string_t datetime::to_string(date_format format) const
> + {
> +-    const uint64_t input = m_interval / _secondTicks; // convert to seconds
> ++    const int64_t input = static_cast<int64_t>(m_interval / _secondTicks); // convert to seconds
> +     const int frac_sec = static_cast<int>(m_interval % _secondTicks);
> +     const time_t time = static_cast<time_t>(input - ntToUnixOffsetSeconds);
> +     struct tm t;
> +@@ -797,22 +797,20 @@ static int atoi2(const CharT* str)
> +     return (static_cast<unsigned char>(str[0]) - '0') * 10 + (static_cast<unsigned char>(str[1]) - '0');
> + }
> +
> +-static const time_t maxTimeT = sizeof(time_t) == 4 ? (time_t)INT_MAX : (time_t)LLONG_MAX;
> +-
> +-static time_t timezone_adjust(time_t result, unsigned char chSign, int adjustHours, int adjustMinutes)
> ++static int64_t timezone_adjust(int64_t result, unsigned char chSign, int adjustHours, int adjustMinutes)
> + {
> +     if (adjustHours > 23)
> +     {
> +-        return (time_t)-1;
> ++        return -1;
> +     }
> +
> +     // adjustMinutes > 59 is impossible due to digit 5 check
> +     const int tzAdjust = adjustMinutes * 60 + adjustHours * 60 * 60;
> +     if (chSign == '-')
> +     {
> +-        if (maxTimeT - result < tzAdjust)
> ++        if (INT64_MAX - result < tzAdjust)
> +         {
> +-            return (time_t)-1;
> ++            return -1;
> +         }
> +
> +         result += tzAdjust;
> +@@ -821,7 +819,7 @@ static time_t timezone_adjust(time_t result, unsigned char chSign, int adjustHou
> +     {
> +         if (tzAdjust > result)
> +         {
> +-            return (time_t)-1;
> ++            return -1;
> +         }
> +
> +         result -= tzAdjust;
> +@@ -830,10 +828,10 @@ static time_t timezone_adjust(time_t result, unsigned char chSign, int adjustHou
> +     return result;
> + }
> +
> +-static time_t make_gm_time(struct tm* t)
> ++static int64_t make_gm_time(struct tm* t)
> + {
> + #ifdef _MSC_VER
> +-    return _mkgmtime(t);
> ++    return static_cast<int64_t>(_mkgmtime(t));
> + #elif (defined(ANDROID) || defined(__ANDROID__))
> +     // HACK: The (nonportable?) POSIX function timegm is not available in
> +     //       bionic. As a workaround[1][2], we set the C library timezone to
> +@@ -867,9 +865,9 @@ static time_t make_gm_time(struct tm* t)
> +             unsetenv("TZ");
> +         }
> +     }
> +-    return time;
> ++    return static_cast<int64_t>(time);
> + #else  // ^^^ ANDROID // Other POSIX platforms vvv
> +-    return timegm(t);
> ++    return static_cast<int64_t>(timegm(t));
> + #endif // _MSC_VER
> + }
> +
> +@@ -916,7 +914,7 @@ zone        =  "UT"  / "GMT"                ; Universal Time
> + datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format)
> + {
> +     datetime result;
> +-    time_t seconds;
> ++    int64_t seconds;
> +     uint64_t frac_sec = 0;
> +     struct tm t{};
> +     auto str = dateString.c_str();
> +diff --git a/Release/tests/functional/utils/datetime.cpp b/Release/tests/functional/utils/datetime.cpp
> +index ae7f7a5e4..acd6fddb0 100644
> +--- a/Release/tests/functional/utils/datetime.cpp
> ++++ b/Release/tests/functional/utils/datetime.cpp
> +@@ -133,75 +133,77 @@ SUITE(datetime)
> +
> +     TEST(parsing_time_rfc1123_accepts_each_day)
> +     {
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:00 GMT"), (time_t) 0);
> +-        TestRfc1123IsTimeT(_XPLATSTR("Fri, 02 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 1);
> +-        TestRfc1123IsTimeT(_XPLATSTR("Sat, 03 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 2);
> +-        TestRfc1123IsTimeT(_XPLATSTR("Sun, 04 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 3);
> +-        TestRfc1123IsTimeT(_XPLATSTR("Mon, 05 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 4);
> +-        TestRfc1123IsTimeT(_XPLATSTR("Tue, 06 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 5);
> +-        TestRfc1123IsTimeT(_XPLATSTR("Wed, 07 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 6);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:00 GMT"), (time_t)0);
> ++        TestRfc1123IsTimeT(_XPLATSTR("Fri, 02 Jan 1970 00:00:00 GMT"), (time_t)86400 * 1);
> ++        TestRfc1123IsTimeT(_XPLATSTR("Sat, 03 Jan 1970 00:00:00 GMT"), (time_t)86400 * 2);
> ++        TestRfc1123IsTimeT(_XPLATSTR("Sun, 04 Jan 1970 00:00:00 GMT"), (time_t)86400 * 3);
> ++        TestRfc1123IsTimeT(_XPLATSTR("Mon, 05 Jan 1970 00:00:00 GMT"), (time_t)86400 * 4);
> ++        TestRfc1123IsTimeT(_XPLATSTR("Tue, 06 Jan 1970 00:00:00 GMT"), (time_t)86400 * 5);
> ++        TestRfc1123IsTimeT(_XPLATSTR("Wed, 07 Jan 1970 00:00:00 GMT"), (time_t)86400 * 6);
> +     }
> +
> +     TEST(parsing_time_rfc1123_boundary_cases)
> +     {
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:00 GMT"), (time_t) 0);
> +-        TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:14:06 GMT"), (time_t) INT_MAX - 1);
> +-#ifndef _USE_32BIT_TIME_T
> +-        TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:13:07 -0001"), (time_t) INT_MAX);
> +-        TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:14:07 -0000"), (time_t) INT_MAX);
> +-#endif // _USE_32BIT_TIME_T
> +-        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0000"), (time_t) 1547507781);
> +-        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 -0001"), (time_t) 1547507841);
> +-        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0001"), (time_t) 1547507721);
> +-        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 -0100"), (time_t) 1547511381);
> +-        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0100"), (time_t) 1547504181);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:00 GMT"), (time_t)0);
> ++        TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:14:06 GMT"), (time_t)INT_MAX - 1);
> ++        if (sizeof(time_t) == 8)
> ++        {
> ++            TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:13:07 -0001"), (time_t)INT_MAX);
> ++            TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:14:07 -0000"), (time_t)INT_MAX);
> ++        }
> ++        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0000"), (time_t)1547507781);
> ++        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 -0001"), (time_t)1547507841);
> ++        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0001"), (time_t)1547507721);
> ++        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 -0100"), (time_t)1547511381);
> ++        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0100"), (time_t)1547504181);
> +     }
> +
> +     TEST(parsing_time_rfc1123_uses_each_field)
> +     {
> +-        TestRfc1123IsTimeT(_XPLATSTR("02 Jan 1970 00:00:00 GMT"), (time_t) 86400);
> +-        TestRfc1123IsTimeT(_XPLATSTR("12 Jan 1970 00:00:00 GMT"), (time_t) 950400);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Feb 1970 00:00:00 GMT"), (time_t) 2678400);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 2000 00:00:00 GMT"), (time_t) 946684800);
> +-#ifndef _USE_32BIT_TIME_T
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 2100 00:00:00 GMT"), (time_t) 4102444800);
> +-#endif // _USE_32BIT_TIME_T
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1990 00:00:00 GMT"), (time_t) 631152000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1971 00:00:00 GMT"), (time_t) 31536000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 10:00:00 GMT"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 01:00:00 GMT"), (time_t) 3600);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:10:00 GMT"), (time_t) 600);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:01:00 GMT"), (time_t) 60);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:10 GMT"), (time_t) 10);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:01 GMT"), (time_t) 1);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 10:00:00 GMT"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 02:00:00 PST"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 03:00:00 PDT"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 03:00:00 MST"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 04:00:00 MDT"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 04:00:00 CST"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:00:00 CDT"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:00:00 EST"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 06:00:00 EDT"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 06:00:00 -0400"), (time_t) 36000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:59:00 -0401"), (time_t) 36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("02 Jan 1970 00:00:00 GMT"), (time_t)86400);
> ++        TestRfc1123IsTimeT(_XPLATSTR("12 Jan 1970 00:00:00 GMT"), (time_t)950400);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Feb 1970 00:00:00 GMT"), (time_t)2678400);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 2000 00:00:00 GMT"), (time_t)946684800);
> ++        if (sizeof(time_t) == 8)
> ++        {
> ++            TestRfc1123IsTimeT(_XPLATSTR("01 Jan 2100 00:00:00 GMT"), (time_t)4102444800);
> ++        }
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1990 00:00:00 GMT"), (time_t)631152000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1971 00:00:00 GMT"), (time_t)31536000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 10:00:00 GMT"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 01:00:00 GMT"), (time_t)3600);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:10:00 GMT"), (time_t)600);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:01:00 GMT"), (time_t)60);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:10 GMT"), (time_t)10);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:01 GMT"), (time_t)1);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 10:00:00 GMT"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 02:00:00 PST"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 03:00:00 PDT"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 03:00:00 MST"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 04:00:00 MDT"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 04:00:00 CST"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:00:00 CDT"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:00:00 EST"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 06:00:00 EDT"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 06:00:00 -0400"), (time_t)36000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:59:00 -0401"), (time_t)36000);
> +     }
> +
> +     TEST(parsing_time_rfc1123_max_days)
> +     {
> +-        TestRfc1123IsTimeT(_XPLATSTR("31 Jan 1970 00:00:00 GMT"), (time_t) 2592000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("28 Feb 2019 00:00:00 GMT"), (time_t) 1551312000); // non leap year allows feb 28
> +-        TestRfc1123IsTimeT(_XPLATSTR("29 Feb 2020 00:00:00 GMT"), (time_t) 1582934400); // leap year allows feb 29
> +-        TestRfc1123IsTimeT(_XPLATSTR("31 Mar 1970 00:00:00 GMT"), (time_t) 7689600);
> +-        TestRfc1123IsTimeT(_XPLATSTR("30 Apr 1970 00:00:00 GMT"), (time_t) 10281600);
> +-        TestRfc1123IsTimeT(_XPLATSTR("31 May 1970 00:00:00 GMT"), (time_t) 12960000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("30 Jun 1970 00:00:00 GMT"), (time_t) 15552000);
> +-        TestRfc1123IsTimeT(_XPLATSTR("31 Jul 1970 00:00:00 GMT"), (time_t) 18230400);
> +-        TestRfc1123IsTimeT(_XPLATSTR("31 Aug 1970 00:00:00 GMT"), (time_t) 20908800);
> +-        TestRfc1123IsTimeT(_XPLATSTR("30 Sep 1970 00:00:00 GMT"), (time_t) 23500800);
> +-        TestRfc1123IsTimeT(_XPLATSTR("31 Oct 1970 00:00:00 GMT"), (time_t) 26179200);
> +-        TestRfc1123IsTimeT(_XPLATSTR("30 Nov 1970 00:00:00 GMT"), (time_t) 28771200);
> +-        TestRfc1123IsTimeT(_XPLATSTR("31 Dec 1970 00:00:00 GMT"), (time_t) 31449600);
> ++        TestRfc1123IsTimeT(_XPLATSTR("31 Jan 1970 00:00:00 GMT"), (time_t)2592000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("28 Feb 2019 00:00:00 GMT"), (time_t)1551312000); // non leap year allows feb 28
> ++        TestRfc1123IsTimeT(_XPLATSTR("29 Feb 2020 00:00:00 GMT"), (time_t)1582934400); // leap year allows feb 29
> ++        TestRfc1123IsTimeT(_XPLATSTR("31 Mar 1970 00:00:00 GMT"), (time_t)7689600);
> ++        TestRfc1123IsTimeT(_XPLATSTR("30 Apr 1970 00:00:00 GMT"), (time_t)10281600);
> ++        TestRfc1123IsTimeT(_XPLATSTR("31 May 1970 00:00:00 GMT"), (time_t)12960000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("30 Jun 1970 00:00:00 GMT"), (time_t)15552000);
> ++        TestRfc1123IsTimeT(_XPLATSTR("31 Jul 1970 00:00:00 GMT"), (time_t)18230400);
> ++        TestRfc1123IsTimeT(_XPLATSTR("31 Aug 1970 00:00:00 GMT"), (time_t)20908800);
> ++        TestRfc1123IsTimeT(_XPLATSTR("30 Sep 1970 00:00:00 GMT"), (time_t)23500800);
> ++        TestRfc1123IsTimeT(_XPLATSTR("31 Oct 1970 00:00:00 GMT"), (time_t)26179200);
> ++        TestRfc1123IsTimeT(_XPLATSTR("30 Nov 1970 00:00:00 GMT"), (time_t)28771200);
> ++        TestRfc1123IsTimeT(_XPLATSTR("31 Dec 1970 00:00:00 GMT"), (time_t)31449600);
> +     }
> +
> +     TEST(parsing_time_rfc1123_invalid_cases)
> +@@ -266,7 +268,7 @@ 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 4970 00:00:00 GMT"), // year too big
> ++            _XPLATSTR("01 Jan 4970 00:00:00 GMT"),      // year too big
> +             _XPLATSTR("01 Jan 3001 00:00:00 GMT"),
> +             _XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad
> +             _XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small
> +@@ -288,8 +290,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 1969 00:00:00 GMT"), // underflow
> +-            _XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz
> ++            _XPLATSTR("01 Jan 1969 00:00:00 GMT"),   // underflow
> ++            _XPLATSTR("01 Jan 1969 00:00:00 CEST"),  // bad tz
> +             _XPLATSTR("01 Jan 1970 00:00:00 +2400"), // bad tzoffsets
> +             _XPLATSTR("01 Jan 1970 00:00:00 -3000"),
> +             _XPLATSTR("01 Jan 1970 00:00:00 +2160"),
> +@@ -309,11 +311,12 @@ SUITE(datetime)
> +         // boundary cases:
> +         TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:00:00Z"));                                         // epoch
> +         TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:14:06+00:00"), _XPLATSTR("2038-01-19T03:14:06Z")); // INT_MAX - 1
> +-#ifndef _USE_32BIT_TIME_T
> +-        TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:13:07-00:01"),
> +-                              _XPLATSTR("2038-01-19T03:14:07Z")); // INT_MAX after subtacting 1
> +-        TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:14:07-00:00"), _XPLATSTR("2038-01-19T03:14:07Z"));
> +-#endif // _USE_32BIT_TIME_T
> ++        if (sizeof(time_t) == 8)
> ++        {
> ++            TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:13:07-00:01"),
> ++                                  _XPLATSTR("2038-01-19T03:14:07Z")); // INT_MAX after subtacting 1
> ++            TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:14:07-00:00"), _XPLATSTR("2038-01-19T03:14:07Z"));
> ++        }
> +     }
> +
> +     TEST(parsing_time_iso8601_uses_each_timezone_digit)
> +@@ -456,11 +459,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("1969-01-01T00:00:00Z"), // underflow
> +-#ifdef _USE_32BIT_TIME_T
> +-            _XPLATSTR("3000-01-01T00:00:01Z"), // overflow
> +-#endif
> +-            _XPLATSTR("3001-01-01T00:00:00Z"),
> ++            _XPLATSTR("1969-01-01T00:00:00Z"),      // underflow
> ++            _XPLATSTR("3001-01-01T00:00:00Z"),      // overflow
> +             _XPLATSTR("1970-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
> diff --git a/meta-oe/recipes-support/cpprest/cpprest/revert-9b670e5b33dfdbd501d618cd7e7498148ffbd559.patch b/meta-oe/recipes-support/cpprest/cpprest/revert-9b670e5b33dfdbd501d618cd7e7498148ffbd559.patch
> deleted file mode 100644
> index 9af2cbf36..000000000
> --- a/meta-oe/recipes-support/cpprest/cpprest/revert-9b670e5b33dfdbd501d618cd7e7498148ffbd559.patch
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -Description: revert upstream bugfix (see:https://github.com/Microsoft/cpprestsdk/issues/1090)
> -Last-Update: 2019-03-28
> -
> ---- cpprest-2.10.12.orig/Release/src/utilities/asyncrt_utils.cpp
> -+++ cpprest-2.10.12/Release/src/utilities/asyncrt_utils.cpp
> -@@ -1393,16 +1393,15 @@ utility::seconds __cdecl timespan::xml_d
> -     return utility::seconds(numSecs);
> - }
> -
> --static const char c_allowed_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
> --static const int chars_count = static_cast<int>(sizeof(c_allowed_chars) - 1);
> -+static const utility::char_t c_allowed_chars[] =
> -+    _XPLATSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
> -
> - utility::string_t nonce_generator::generate()
> - {
> --    std::uniform_int_distribution<> distr(0, chars_count - 1);
> -+    std::uniform_int_distribution<> distr(0, static_cast<int>(sizeof(c_allowed_chars) / sizeof(utility::char_t)) - 1);
> -     utility::string_t result;
> -     result.reserve(length());
> --    std::generate_n(std::back_inserter(result), length(),
> --		[&] { return static_cast<utility::char_t>(c_allowed_chars[distr(m_random)]); });
> -+    std::generate_n(std::back_inserter(result), length(), [&]() { return c_allowed_chars[distr(m_random)]; });
> -     return result;
> - }
> -
> diff --git a/meta-oe/recipes-support/cpprest/cpprest/revert-f10d9f8e214516d2c19aa6ef831ee874a58c0479.patch b/meta-oe/recipes-support/cpprest/cpprest/revert-f10d9f8e214516d2c19aa6ef831ee874a58c0479.patch
> deleted file mode 100644
> index 01e463113..000000000
> --- a/meta-oe/recipes-support/cpprest/cpprest/revert-f10d9f8e214516d2c19aa6ef831ee874a58c0479.patch
> +++ /dev/null
> @@ -1,1557 +0,0 @@
> -Description: revert upstream bugfix (see:https://github.com/Microsoft/cpprestsdk/issues/1090)
> -Last-Update: 2019-03-28
> -
> ---- cpprest-2.10.12.orig/Release/include/cpprest/asyncrt_utils.h
> -+++ cpprest-2.10.12/Release/include/cpprest/asyncrt_utils.h
> -@@ -630,6 +630,15 @@ private:
> -     static const interval_type _hourTicks = 60 * 60 * _secondTicks;
> -     static const interval_type _dayTicks = 24 * 60 * 60 * _secondTicks;
> -
> -+#ifdef _WIN32
> -+    // void* to avoid pulling in windows.h
> -+    static _ASYNCRTIMP bool __cdecl system_type_to_datetime(/*SYSTEMTIME*/ void* psysTime,
> -+                                                            uint64_t seconds,
> -+                                                            datetime* pdt);
> -+#else
> -+    static datetime timeval_to_datetime(const timeval& time);
> -+#endif
> -+
> -     // Private constructor. Use static methods to create an instance.
> -     datetime(interval_type interval) : m_interval(interval) {}
> -
> -@@ -690,6 +699,7 @@ public:
> -     void set_length(int length) { m_length = length; }
> -
> - private:
> -+    static const utility::string_t c_allowed_chars;
> -     std::mt19937 m_random;
> -     int m_length;
> - };
> ---- cpprest-2.10.12.orig/Release/src/pch/stdafx.h
> -+++ cpprest-2.10.12/Release/src/pch/stdafx.h
> -@@ -61,6 +61,7 @@
> - #undef BOOST_NO_CXX11_NULLPTR
> - #endif
> - #include "boost/bind/bind.hpp"
> -+#include "boost/date_time/posix_time/posix_time_types.hpp"
> - #include "boost/thread/condition_variable.hpp"
> - #include "boost/thread/mutex.hpp"
> - #include <fcntl.h>
> ---- cpprest-2.10.12.orig/Release/src/utilities/asyncrt_utils.cpp
> -+++ cpprest-2.10.12/Release/src/utilities/asyncrt_utils.cpp
> -@@ -15,9 +15,20 @@
> -
> - #include <algorithm>
> - #include <cpprest/asyncrt_utils.h>
> --#include <stdexcept>
> -+#include <sstream>
> - #include <string>
> --#include <time.h>
> -+
> -+#ifndef _WIN32
> -+#if defined(__clang__)
> -+#pragma clang diagnostic push
> -+#pragma clang diagnostic ignored "-Wunused-local-typedef"
> -+#endif
> -+#include <boost/date_time/posix_time/posix_time.hpp>
> -+#include <boost/date_time/posix_time/posix_time_io.hpp>
> -+#if defined(__clang__)
> -+#pragma clang diagnostic pop
> -+#endif
> -+#endif
> -
> - using namespace web;
> - using namespace utility;
> -@@ -618,7 +629,18 @@ std::string __cdecl conversions::to_utf8
> -
> - utf16string __cdecl conversions::to_utf16string(const std::string& value) { return utf8_to_utf16(value); }
> -
> --static const uint64_t ntToUnixOffsetSeconds = 11644473600U; // diff between windows and unix epochs (seconds)
> -+#ifndef WIN32
> -+datetime datetime::timeval_to_datetime(const timeval& time)
> -+{
> -+    const uint64_t epoch_offset = 11644473600LL; // diff between windows and unix epochs (seconds)
> -+    uint64_t result = epoch_offset + time.tv_sec;
> -+    result *= _secondTicks;      // convert to 10e-7
> -+    result += time.tv_usec * 10; // convert and add microseconds, 10e-6 to 10e-7
> -+    return datetime(result);
> -+}
> -+#endif
> -+
> -+static bool is_digit(utility::char_t c) { return c >= _XPLATSTR('0') && c <= _XPLATSTR('9'); }
> -
> - datetime __cdecl datetime::utc_now()
> - {
> -@@ -634,649 +656,450 @@ datetime __cdecl datetime::utc_now()
> - #else // LINUX
> -     struct timeval time;
> -     gettimeofday(&time, nullptr);
> --    uint64_t result = ntToUnixOffsetSeconds + time.tv_sec;
> --    result *= _secondTicks;      // convert to 10e-7
> --    result += time.tv_usec * 10; // convert and add microseconds, 10e-6 to 10e-7
> --    return datetime(result);
> -+    return timeval_to_datetime(time);
> - #endif
> - }
> -
> --static const char dayNames[] = "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat";
> --static const char monthNames[] = "Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec";
> --
> - utility::string_t datetime::to_string(date_format format) const
> - {
> --    const uint64_t input = m_interval / _secondTicks; // convert to seconds
> --    const int frac_sec = static_cast<int>(m_interval % _secondTicks);
> --    const time_t time = static_cast<time_t>(input - ntToUnixOffsetSeconds);
> --    struct tm t;
> --#ifdef _MSC_VER
> --    if (gmtime_s(&t, &time) != 0)
> --#else  // ^^^ _MSC_VER ^^^ // vvv !_MSC_VER vvv
> --    if (gmtime_r(&time, &t) == 0)
> --#endif // _MSC_VER
> --    {
> --        throw std::invalid_argument("gmtime_r/s failed on the time supplied");
> --    }
> --
> --    char outBuffer[38]; // Thu, 01 Jan 1970 00:00:00 GMT\0
> --                        // 1970-01-01T00:00:00.1234567Z\0
> --    char* outCursor = outBuffer;
> --    switch (format)
> --    {
> --        case RFC_1123:
> --#ifdef _MSC_VER
> --            sprintf_s(outCursor,
> --                      26,
> --                      "%s, %02d %s %04d %02d:%02d:%02d",
> --                      dayNames + 4 * t.tm_wday,
> --                      t.tm_mday,
> --                      monthNames + 4 * t.tm_mon,
> --                      t.tm_year + 1900,
> --                      t.tm_hour,
> --                      t.tm_min,
> --                      t.tm_sec);
> --#else  // ^^^ _MSC_VER // !_MSC_VER vvv
> --            sprintf(outCursor,
> --                    "%s, %02d %s %04d %02d:%02d:%02d",
> --                    dayNames + 4 * t.tm_wday,
> --                    t.tm_mday,
> --                    monthNames + 4 * t.tm_mon,
> --                    t.tm_year + 1900,
> --                    t.tm_hour,
> --                    t.tm_min,
> --                    t.tm_sec);
> --#endif // _MSC_VER
> --            outCursor += 25;
> --            memcpy(outCursor, " GMT", 4);
> --            outCursor += 4;
> --            return utility::string_t(outBuffer, outCursor);
> --        case ISO_8601:
> --#ifdef _MSC_VER
> --            sprintf_s(outCursor,
> --                      20,
> --                      "%04d-%02d-%02dT%02d:%02d:%02d",
> --                      t.tm_year + 1900,
> --                      t.tm_mon + 1,
> --                      t.tm_mday,
> --                      t.tm_hour,
> --                      t.tm_min,
> --                      t.tm_sec);
> --#else  // ^^^ _MSC_VER // !_MSC_VER vvv
> --            sprintf(outCursor,
> --                    "%04d-%02d-%02dT%02d:%02d:%02d",
> --                    t.tm_year + 1900,
> --                    t.tm_mon + 1,
> --                    t.tm_mday,
> --                    t.tm_hour,
> --                    t.tm_min,
> --                    t.tm_sec);
> --#endif // _MSC_VER
> --            outCursor += 19;
> --            if (frac_sec != 0)
> --            {
> --                // Append fractional second, which is a 7-digit value with no trailing zeros
> --                // This way, '1200' becomes '00012'
> --#ifdef _MSC_VER
> --                size_t appended = sprintf_s(outCursor, 9, ".%07d", frac_sec);
> --#else  // ^^^ _MSC_VER // !_MSC_VER vvv
> --                size_t appended = sprintf(outCursor, ".%07d", frac_sec);
> --#endif // _MSC_VER
> --                while (outCursor[appended - 1] == '0')
> --                {
> --                    --appended; // trim trailing zeros
> --                }
> --
> --                outCursor += appended;
> --            }
> --
> --            *outCursor = 'Z';
> --            ++outCursor;
> --            return utility::string_t(outBuffer, outCursor);
> --        default: throw std::invalid_argument("Unrecognized date format.");
> --    }
> --}
> --
> --template<class CharT>
> --static bool string_starts_with(const CharT* haystack, const char* needle)
> --{
> --    while (*needle)
> --    {
> --        if (*haystack != static_cast<CharT>(*needle))
> --        {
> --            return false;
> --        }
> --
> --        ++haystack;
> --        ++needle;
> --    }
> --
> --    return true;
> --}
> --
> --#define ascii_isdigit(c) ((unsigned char)((unsigned char)(c) - '0') <= 9)
> --#define ascii_isdigit6(c) ((unsigned char)((unsigned char)(c) - '0') <= 6)
> --#define ascii_isdigit5(c) ((unsigned char)((unsigned char)(c) - '0') <= 5)
> --#define ascii_isdigit3(c) ((unsigned char)((unsigned char)(c) - '0') <= 3)
> --#define ascii_isdigit2(c) ((unsigned char)((unsigned char)(c) - '0') <= 2)
> --#define ascii_isdigit1(c) ((unsigned char)((unsigned char)(c) - '0') <= 1)
> --
> --static const unsigned char max_days_in_month[12] = {
> --    31, // Jan
> --    00, // Feb, special handling for leap years
> --    31, // Mar
> --    30, // Apr
> --    31, // May
> --    30, // Jun
> --    31, // Jul
> --    31, // Aug
> --    30, // Sep
> --    31, // Oct
> --    30, // Nov
> --    31  // Dec
> --};
> --
> --static bool validate_day_month(int day, int month, int year)
> --{
> --    int maxDaysThisMonth;
> --    if (month == 1)
> --    { // Feb needs leap year testing
> --        maxDaysThisMonth = 28 + (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
> --    }
> --    else
> --    {
> --        maxDaysThisMonth = max_days_in_month[month];
> --    }
> --
> --    return day >= 1 && day <= maxDaysThisMonth;
> --}
> -+#ifdef _WIN32
> -+    int status;
> -
> --template<class CharT>
> --static int atoi2(const CharT* str)
> --{
> --    return (static_cast<unsigned char>(str[0]) - '0') * 10 + (static_cast<unsigned char>(str[1]) - '0');
> --}
> -+    ULARGE_INTEGER largeInt;
> -+    largeInt.QuadPart = m_interval;
> -
> --static const time_t maxTimeT = sizeof(time_t) == 4 ? (time_t)INT_MAX : (time_t)LLONG_MAX;
> -+    FILETIME ft;
> -+    ft.dwHighDateTime = largeInt.HighPart;
> -+    ft.dwLowDateTime = largeInt.LowPart;
> -
> --static time_t timezone_adjust(time_t result, unsigned char chSign, int adjustHours, int adjustMinutes)
> --{
> --    if (adjustHours > 23)
> -+    SYSTEMTIME systemTime;
> -+    if (!FileTimeToSystemTime((const FILETIME*)&ft, &systemTime))
> -     {
> --        return (time_t)-1;
> -+        throw utility::details::create_system_error(GetLastError());
> -     }
> -
> --    // adjustMinutes > 59 is impossible due to digit 5 check
> --    const int tzAdjust = adjustMinutes * 60 + adjustHours * 60 * 60;
> --    if (chSign == '-')
> -+    std::wstring result;
> -+    if (format == RFC_1123)
> -     {
> --        if (maxTimeT - result < tzAdjust)
> -         {
> --            return (time_t)-1;
> -+            wchar_t dateStr[18] = {0};
> -+#if _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            status = GetDateFormatW(
> -+                LOCALE_INVARIANT, 0, &systemTime, L"ddd',' dd MMM yyyy", dateStr, sizeof(dateStr) / sizeof(wchar_t));
> -+#else
> -+            status = GetDateFormatEx(LOCALE_NAME_INVARIANT,
> -+                                     0,
> -+                                     &systemTime,
> -+                                     L"ddd',' dd MMM yyyy",
> -+                                     dateStr,
> -+                                     sizeof(dateStr) / sizeof(wchar_t),
> -+                                     NULL);
> -+#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            if (status == 0)
> -+            {
> -+                throw utility::details::create_system_error(GetLastError());
> -+            }
> -+
> -+            result += dateStr;
> -+            result += L' ';
> -         }
> -
> --        result += tzAdjust;
> --    }
> --    else
> --    {
> --        if (tzAdjust > result)
> -         {
> --            return (time_t)-1;
> --        }
> --
> --        result -= tzAdjust;
> --    }
> --
> --    return result;
> --}
> --
> --static time_t make_gm_time(struct tm* t)
> --{
> --#ifdef _MSC_VER
> --    return _mkgmtime(t);
> --#elif (defined(ANDROID) || defined(__ANDROID__))
> --    // HACK: The (nonportable?) POSIX function timegm is not available in
> --    //       bionic. As a workaround[1][2], we set the C library timezone to
> --    //       UTC, call mktime, then set the timezone back. However, the C
> --    //       environment is fundamentally a shared global resource and thread-
> --    //       unsafe. We can protect our usage here, however any other code might
> --    //       manipulate the environment at the same time.
> --    //
> --    // [1] http://linux.die.net/man/3/timegm
> --    // [2] http://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html
> --    time_t time;
> --    static boost::mutex env_var_lock;
> --    {
> --        boost::lock_guard<boost::mutex> lock(env_var_lock);
> --        std::string prev_env;
> --        auto prev_env_cstr = getenv("TZ");
> --        if (prev_env_cstr != nullptr)
> --        {
> --            prev_env = prev_env_cstr;
> --        }
> --        setenv("TZ", "UTC", 1);
> --
> --        time = mktime(t);
> -+            wchar_t timeStr[10] = {0};
> -+#if _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            status = GetTimeFormatW(LOCALE_INVARIANT,
> -+                                    TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
> -+                                    &systemTime,
> -+                                    L"HH':'mm':'ss",
> -+                                    timeStr,
> -+                                    sizeof(timeStr) / sizeof(wchar_t));
> -+#else
> -+            status = GetTimeFormatEx(LOCALE_NAME_INVARIANT,
> -+                                     TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
> -+                                     &systemTime,
> -+                                     L"HH':'mm':'ss",
> -+                                     timeStr,
> -+                                     sizeof(timeStr) / sizeof(wchar_t));
> -+#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            if (status == 0)
> -+            {
> -+                throw utility::details::create_system_error(GetLastError());
> -+            }
> -
> --        if (prev_env_cstr)
> --        {
> --            setenv("TZ", prev_env.c_str(), 1);
> --        }
> --        else
> --        {
> --            unsetenv("TZ");
> -+            result += timeStr;
> -+            result += L" GMT";
> -         }
> -     }
> --    return time;
> --#else  // ^^^ ANDROID // Other POSIX platforms vvv
> --    return timegm(t);
> --#endif // _MSC_VER
> --}
> --
> --/*
> --https://tools.ietf.org/html/rfc822
> --https://tools.ietf.org/html/rfc1123
> --
> --date-time   =  [ day "," ] date time        ; dd mm yy
> --                                            ;  hh:mm:ss zzz
> --
> --day         =  "Mon"  / "Tue" /  "Wed"  / "Thu"
> --            /  "Fri"  / "Sat" /  "Sun"
> --
> --date        =  1*2DIGIT month 2DIGIT        ; day month year
> --                                            ;  e.g. 20 Jun 82
> --RFC1123 changes this to:
> --date        =  1*2DIGIT month 2*4DIGIT        ; day month year
> --                                              ;  e.g. 20 Jun 1982
> --This implementation only accepts 4 digit years.
> --
> --month       =  "Jan"  /  "Feb" /  "Mar"  /  "Apr"
> --            /  "May"  /  "Jun" /  "Jul"  /  "Aug"
> --            /  "Sep"  /  "Oct" /  "Nov"  /  "Dec"
> --
> --time        =  hour zone                    ; ANSI and Military
> --
> --hour        =  2DIGIT ":" 2DIGIT [":" 2DIGIT]
> --                                            ; 00:00:00 - 23:59:59
> --
> --zone        =  "UT"  / "GMT"                ; Universal Time
> --                                            ; North American : UT
> --            /  "EST" / "EDT"                ;  Eastern:  - 5/ - 4
> --            /  "CST" / "CDT"                ;  Central:  - 6/ - 5
> --            /  "MST" / "MDT"                ;  Mountain: - 7/ - 6
> --            /  "PST" / "PDT"                ;  Pacific:  - 8/ - 7
> --
> --// military time deleted by RFC 1123
> --
> --            / ( ("+" / "-") 4DIGIT )        ; Local differential
> --                                            ;  hours+min. (HHMM)
> --*/
> --
> --
> --datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format)
> --{
> --    datetime result;
> --    time_t seconds;
> --    uint64_t frac_sec = 0;
> --    struct tm t{};
> --    auto str = dateString.c_str();
> --    if (format == RFC_1123)
> -+    else if (format == ISO_8601)
> -     {
> --        int parsedWeekday = -1;
> --        for (int day = 0; day < 7; ++day)
> -+        const size_t buffSize = 64;
> -         {
> --            if (string_starts_with(str, dayNames + day * 4) && str[3] == _XPLATSTR(',') && str[4] == _XPLATSTR(' '))
> -+            wchar_t dateStr[buffSize] = {0};
> -+#if _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            status = GetDateFormatW(LOCALE_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize);
> -+#else
> -+            status = GetDateFormatEx(LOCALE_NAME_INVARIANT, 0, &systemTime, L"yyyy-MM-dd", dateStr, buffSize, NULL);
> -+#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            if (status == 0)
> -             {
> --                parsedWeekday = day;
> --                str += 5; // parsed day of week
> --                break;
> -+                throw utility::details::create_system_error(GetLastError());
> -             }
> --        }
> -
> --        if (ascii_isdigit3(str[0]) && ascii_isdigit(str[1]) && str[2] == _XPLATSTR(' '))
> --        {
> --            t.tm_mday = atoi2(str); // validity checked later
> --            str += 3;               // parsed day
> --        }
> --        else if (ascii_isdigit(str[0]) && str[1] == _XPLATSTR(' '))
> --        {
> --            t.tm_mday = str[0] - _XPLATSTR('0');
> --            str += 2; // parsed day
> --        }
> --        else
> --        {
> --            return result;
> -+            result += dateStr;
> -+            result += L'T';
> -         }
> -
> --        t.tm_mon = -1;
> --        for (int month = 0; month < 12; ++month)
> -         {
> --            if (string_starts_with(str, monthNames + month * 4))
> -+            wchar_t timeStr[buffSize] = {0};
> -+#if _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            status = GetTimeFormatW(LOCALE_INVARIANT,
> -+                                    TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
> -+                                    &systemTime,
> -+                                    L"HH':'mm':'ss",
> -+                                    timeStr,
> -+                                    buffSize);
> -+#else
> -+            status = GetTimeFormatEx(LOCALE_NAME_INVARIANT,
> -+                                     TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
> -+                                     &systemTime,
> -+                                     L"HH':'mm':'ss",
> -+                                     timeStr,
> -+                                     buffSize);
> -+#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA
> -+            if (status == 0)
> -             {
> --                t.tm_mon = month;
> --                break;
> -+                throw utility::details::create_system_error(GetLastError());
> -             }
> --        }
> -
> --        if (t.tm_mon == -1 || str[3] != _XPLATSTR(' '))
> --        {
> --            return result;
> -+            result += timeStr;
> -         }
> -
> --        str += 4; // parsed month
> --
> --        if (!ascii_isdigit3(str[0]) || !ascii_isdigit(str[1]) || !ascii_isdigit(str[2]) || !ascii_isdigit(str[3]) ||
> --            str[4] != ' ')
> -+        uint64_t frac_sec = largeInt.QuadPart % _secondTicks;
> -+        if (frac_sec > 0)
> -         {
> --            return result;
> -+            // Append fractional second, which is a 7-digit value with no trailing zeros
> -+            // This way, '1200' becomes '00012'
> -+            wchar_t buf[9] = {0};
> -+            size_t appended = swprintf_s(buf, 9, L".%07ld", static_cast<long>(frac_sec));
> -+            while (buf[appended - 1] == L'0')
> -+                --appended; // trim trailing zeros
> -+            result.append(buf, appended);
> -         }
> -
> --        t.tm_year = (str[0] - _XPLATSTR('0')) * 1000 + (str[1] - _XPLATSTR('0')) * 100 +
> --                    (str[2] - _XPLATSTR('0')) * 10 + (str[3] - _XPLATSTR('0'));
> --        if (t.tm_year < 1970 || t.tm_year > 3000)
> --        {
> --            return result;
> --        }
> -+        result += L'Z';
> -+    }
> -
> --        // days in month validity check
> --        if (!validate_day_month(t.tm_mday, t.tm_mon, t.tm_year))
> --        {
> --            return result;
> --        }
> -+    return result;
> -+#else // LINUX
> -+    uint64_t input = m_interval;
> -+    uint64_t frac_sec = input % _secondTicks;
> -+    input /= _secondTicks;                               // convert to seconds
> -+    time_t time = (time_t)input - (time_t)11644473600LL; // diff between windows and unix epochs (seconds)
> -+
> -+    struct tm datetime;
> -+    gmtime_r(&time, &datetime);
> -+
> -+    const int max_dt_length = 64;
> -+    char output[max_dt_length + 1] = {0};
> -+
> -+    if (format != RFC_1123 && frac_sec > 0)
> -+    {
> -+        // Append fractional second, which is a 7-digit value with no trailing zeros
> -+        // This way, '1200' becomes '00012'
> -+        const int max_frac_length = 8;
> -+        char buf[max_frac_length + 1] = {0};
> -+        snprintf(buf, sizeof(buf), ".%07ld", (long int)frac_sec);
> -+        // trim trailing zeros
> -+        for (int i = max_frac_length - 1; buf[i] == '0'; i--)
> -+            buf[i] = '\0';
> -+        // format the datetime into a separate buffer
> -+        char datetime_str[max_dt_length - max_frac_length - 1 + 1] = {0};
> -+        strftime(datetime_str, sizeof(datetime_str), "%Y-%m-%dT%H:%M:%S", &datetime);
> -+        // now print this buffer into the output buffer
> -+        snprintf(output, sizeof(output), "%s%sZ", datetime_str, buf);
> -+    }
> -+    else
> -+    {
> -+        strftime(
> -+            output, sizeof(output), format == RFC_1123 ? "%a, %d %b %Y %H:%M:%S GMT" : "%Y-%m-%dT%H:%M:%SZ", &datetime);
> -+    }
> -
> --        t.tm_year -= 1900;
> --        str += 5; // parsed year
> -+    return std::string(output);
> -+#endif
> -+}
> -
> --        if (!ascii_isdigit2(str[0]) || !ascii_isdigit(str[1]) || str[2] != _XPLATSTR(':') || !ascii_isdigit5(str[3]) ||
> --            !ascii_isdigit(str[4]))
> --        {
> --            return result;
> --        }
> -+#ifdef _WIN32
> -+bool __cdecl datetime::system_type_to_datetime(void* pvsysTime, uint64_t seconds, datetime* pdt)
> -+{
> -+    SYSTEMTIME* psysTime = (SYSTEMTIME*)pvsysTime;
> -+    FILETIME fileTime;
> -
> --        t.tm_hour = atoi2(str);
> --        if (t.tm_hour > 23)
> --        {
> --            return result;
> --        }
> -+    if (SystemTimeToFileTime(psysTime, &fileTime))
> -+    {
> -+        ULARGE_INTEGER largeInt;
> -+        largeInt.LowPart = fileTime.dwLowDateTime;
> -+        largeInt.HighPart = fileTime.dwHighDateTime;
> -
> --        str += 3; // parsed hour
> --        t.tm_min = atoi2(str);
> --        str += 2; // parsed mins
> -+        // Add hundredths of nanoseconds
> -+        largeInt.QuadPart += seconds;
> -
> --        if (str[0] == ':')
> --        {
> --            if (!ascii_isdigit6(str[1]) || !ascii_isdigit(str[2]) || str[3] != _XPLATSTR(' '))
> --            {
> --                return result;
> --            }
> -+        *pdt = datetime(largeInt.QuadPart);
> -+        return true;
> -+    }
> -+    return false;
> -+}
> -+#endif
> -
> --            t.tm_sec = atoi2(str + 1);
> --            str += 4; // parsed seconds
> --        }
> --        else if (str[0] == _XPLATSTR(' '))
> --        {
> --            t.tm_sec = 0;
> --            str += 1; // parsed seconds
> --        }
> --        else
> --        {
> --            return result;
> -+// Take a string that represents a fractional second and return the number of ticks
> -+// This is equivalent to doing atof on the string and multiplying by 10000000,
> -+// but does not lose precision
> -+template<typename StringIterator>
> -+uint64_t timeticks_from_second(StringIterator begin, StringIterator end)
> -+{
> -+    int size = (int)(end - begin);
> -+    _ASSERTE(begin[0] == U('.'));
> -+    uint64_t ufrac_second = 0;
> -+    for (int i = 1; i <= 7; ++i)
> -+    {
> -+        ufrac_second *= 10;
> -+        int add = i < size ? begin[i] - U('0') : 0;
> -+        ufrac_second += add;
> -+    }
> -+    return ufrac_second;
> -+}
> -+
> -+void extract_fractional_second(const utility::string_t& dateString,
> -+                               utility::string_t& resultString,
> -+                               uint64_t& ufrac_second)
> -+{
> -+    resultString = dateString;
> -+    // First, the string must be strictly longer than 2 characters, and the trailing character must be 'Z'
> -+    if (resultString.size() > 2 && resultString[resultString.size() - 1] == U('Z'))
> -+    {
> -+        // Second, find the last non-digit by scanning the string backwards
> -+        auto last_non_digit = std::find_if_not(resultString.rbegin() + 1, resultString.rend(), is_digit);
> -+        if (last_non_digit < resultString.rend() - 1)
> -+        {
> -+            // Finally, make sure the last non-digit is a dot:
> -+            auto last_dot = last_non_digit.base() - 1;
> -+            if (*last_dot == U('.'))
> -+            {
> -+                // Got it! Now extract the fractional second
> -+                auto last_before_Z = std::end(resultString) - 1;
> -+                ufrac_second = timeticks_from_second(last_dot, last_before_Z);
> -+                // And erase it from the string
> -+                resultString.erase(last_dot, last_before_Z);
> -+            }
> -         }
> -+    }
> -+}
> -
> --        if (t.tm_sec > 60)
> --        { // 60 to allow leap seconds
> --            return result;
> --        }
> -+datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format)
> -+{
> -+    // avoid floating point math to preserve precision
> -+    uint64_t ufrac_second = 0;
> -
> --        t.tm_isdst = 0;
> --        seconds = make_gm_time(&t);
> --        if (seconds < 0)
> --        {
> --            return result;
> --        }
> -+#ifdef _WIN32
> -+    datetime result;
> -+    if (format == RFC_1123)
> -+    {
> -+        SYSTEMTIME sysTime = {0};
> -
> --        if (parsedWeekday >= 0 && parsedWeekday != t.tm_wday)
> --        {
> --            return result;
> --        }
> -+        std::wstring month(3, L'\0');
> -+        std::wstring unused(3, L'\0');
> -
> --        if (!string_starts_with(str, "GMT") && !string_starts_with(str, "UT"))
> --        {
> --            // some timezone adjustment necessary
> --            auto tzCh = _XPLATSTR('-');
> --            int tzHours;
> --            int tzMinutes = 0;
> --            if (string_starts_with(str, "EDT"))
> --            {
> --                tzHours = 4;
> --            }
> --            else if (string_starts_with(str, "EST") || string_starts_with(str, "CDT"))
> --            {
> --                tzHours = 5;
> --            }
> --            else if (string_starts_with(str, "CST") || string_starts_with(str, "MDT"))
> --            {
> --                tzHours = 6;
> --            }
> --            else if (string_starts_with(str, "MST") || string_starts_with(str, "PDT"))
> --            {
> --                tzHours = 7;
> --            }
> --            else if (string_starts_with(str, "PST"))
> --            {
> --                tzHours = 8;
> --            }
> --            else if ((tzCh == _XPLATSTR('+') || tzCh == _XPLATSTR('-')) && ascii_isdigit2(str[1]) &&
> --                     ascii_isdigit(str[2]) && ascii_isdigit5(str[3]) && ascii_isdigit(str[4]))
> --            {
> --                tzCh = str[0];
> --                tzHours = atoi2(str + 1);
> --                tzMinutes = atoi2(str + 3);
> --            }
> --            else
> --            {
> --                return result;
> --            }
> -+        const wchar_t* formatString = L"%3c, %2d %3c %4d %2d:%2d:%2d %3c";
> -+        auto n = swscanf_s(dateString.c_str(),
> -+                           formatString,
> -+                           unused.data(),
> -+                           unused.size(),
> -+                           &sysTime.wDay,
> -+                           month.data(),
> -+                           month.size(),
> -+                           &sysTime.wYear,
> -+                           &sysTime.wHour,
> -+                           &sysTime.wMinute,
> -+                           &sysTime.wSecond,
> -+                           unused.data(),
> -+                           unused.size());
> -+
> -+        if (n == 8)
> -+        {
> -+            std::wstring monthnames[12] = {
> -+                L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec"};
> -+            auto loc =
> -+                std::find_if(monthnames, monthnames + 12, [&month](const std::wstring& m) { return m == month; });
> -
> --            seconds = timezone_adjust(seconds, static_cast<unsigned char>(tzCh), tzHours, tzMinutes);
> --            if (seconds < 0)
> -+            if (loc != monthnames + 12)
> -             {
> --                return result;
> -+                sysTime.wMonth = (short)((loc - monthnames) + 1);
> -+                if (system_type_to_datetime(&sysTime, ufrac_second, &result))
> -+                {
> -+                    return result;
> -+                }
> -             }
> -         }
> -     }
> -     else if (format == ISO_8601)
> -     {
> --        // parse year
> --        if (!ascii_isdigit3(str[0]) || !ascii_isdigit(str[1]) || !ascii_isdigit(str[2]) || !ascii_isdigit(str[3]))
> --        {
> --            return result;
> --        }
> -+        // Unlike FILETIME, SYSTEMTIME does not have enough precision to hold seconds in 100 nanosecond
> -+        // increments. Therefore, start with seconds and milliseconds set to 0, then add them separately
> -
> --        t.tm_year = (str[0] - _XPLATSTR('0')) * 1000 + (str[1] - _XPLATSTR('0')) * 100 +
> --                    (str[2] - _XPLATSTR('0')) * 10 + (str[3] - _XPLATSTR('0'));
> --        if (t.tm_year < 1970 || t.tm_year > 3000)
> --        {
> --            return result;
> --        }
> -+        // Try to extract the fractional second from the timestamp
> -+        utility::string_t input;
> -+        extract_fractional_second(dateString, input, ufrac_second);
> -+        {
> -+            SYSTEMTIME sysTime = {0};
> -+            const wchar_t* formatString = L"%4d-%2d-%2dT%2d:%2d:%2dZ";
> -+            auto n = swscanf_s(input.c_str(),
> -+                               formatString,
> -+                               &sysTime.wYear,
> -+                               &sysTime.wMonth,
> -+                               &sysTime.wDay,
> -+                               &sysTime.wHour,
> -+                               &sysTime.wMinute,
> -+                               &sysTime.wSecond);
> -
> --        str += 4;
> --        if (*str == _XPLATSTR('-'))
> --        {
> --            ++str;
> -+            if (n == 3 || n == 6)
> -+            {
> -+                if (system_type_to_datetime(&sysTime, ufrac_second, &result))
> -+                {
> -+                    return result;
> -+                }
> -+            }
> -         }
> --
> --        // parse month
> --        if (!ascii_isdigit1(str[0]) || !ascii_isdigit(str[1]))
> -         {
> --            return result;
> --        }
> -+            SYSTEMTIME sysTime = {0};
> -+            DWORD date = 0;
> -
> --        t.tm_mon = atoi2(str);
> --        if (t.tm_mon < 1 || t.tm_mon > 12)
> --        {
> --            return result;
> --        }
> --
> --        t.tm_mon -= 1;
> --        str += 2;
> -+            const wchar_t* formatString = L"%8dT%2d:%2d:%2dZ";
> -+            auto n = swscanf_s(input.c_str(), formatString, &date, &sysTime.wHour, &sysTime.wMinute, &sysTime.wSecond);
> -
> --        if (*str == _XPLATSTR('-'))
> --        {
> --            ++str;
> --        }
> -+            if (n == 1 || n == 4)
> -+            {
> -+                sysTime.wDay = date % 100;
> -+                date /= 100;
> -+                sysTime.wMonth = date % 100;
> -+                date /= 100;
> -+                sysTime.wYear = (WORD)date;
> -
> --        // parse day
> --        if (!ascii_isdigit3(str[0]) || !ascii_isdigit(str[1]))
> --        {
> --            return result;
> -+                if (system_type_to_datetime(&sysTime, ufrac_second, &result))
> -+                {
> -+                    return result;
> -+                }
> -+            }
> -         }
> --
> --        t.tm_mday = atoi2(str);
> --        if (!validate_day_month(t.tm_mday, t.tm_mon, t.tm_year))
> -         {
> --            return result;
> --        }
> -+            SYSTEMTIME sysTime = {0};
> -+            GetSystemTime(&sysTime); // Fill date portion with today's information
> -+            sysTime.wSecond = 0;
> -+            sysTime.wMilliseconds = 0;
> -
> --        t.tm_year -= 1900;
> --        str += 2;
> -+            const wchar_t* formatString = L"%2d:%2d:%2dZ";
> -+            auto n = swscanf_s(input.c_str(), formatString, &sysTime.wHour, &sysTime.wMinute, &sysTime.wSecond);
> -
> --        if (str[0] != _XPLATSTR('T') && str[0] != _XPLATSTR('t'))
> --        {
> --            // No time
> --            seconds = make_gm_time(&t);
> --            if (seconds < 0)
> -+            if (n == 3)
> -             {
> --                return result;
> -+                if (system_type_to_datetime(&sysTime, ufrac_second, &result))
> -+                {
> -+                    return result;
> -+                }
> -             }
> --
> --            seconds += ntToUnixOffsetSeconds;
> --            result.m_interval = static_cast<interval_type>(seconds) * _secondTicks;
> --            return result;
> -         }
> -+    }
> -
> --        ++str; // skip 'T'
> -+    return datetime();
> -+#else
> -+    std::string input(dateString);
> -
> --        // parse hour
> --        if (!ascii_isdigit2(str[0]) || !ascii_isdigit(str[1]))
> --        {
> --            return result;
> --        }
> -+    struct tm output = tm();
> -
> --        t.tm_hour = atoi2(str);
> --        str += 2;
> --        if (t.tm_hour > 23)
> --        {
> --            return result;
> --        }
> -+    if (format == RFC_1123)
> -+    {
> -+        strptime(input.data(), "%a, %d %b %Y %H:%M:%S GMT", &output);
> -+    }
> -+    else
> -+    {
> -+        // Try to extract the fractional second from the timestamp
> -+        utility::string_t input;
> -+        extract_fractional_second(dateString, input, ufrac_second);
> -
> --        if (*str == _XPLATSTR(':'))
> --        {
> --            ++str;
> --        }
> -+        auto result = strptime(input.data(), "%Y-%m-%dT%H:%M:%SZ", &output);
> -
> --        // parse minute
> --        if (!ascii_isdigit5(str[0]) || !ascii_isdigit(str[1]))
> -+        if (result == nullptr)
> -         {
> --            return result;
> -+            result = strptime(input.data(), "%Y%m%dT%H:%M:%SZ", &output);
> -         }
> --        t.tm_min = atoi2(str);
> --        // t.tm_min > 59 is impossible because we checked that the first digit is <= 5 in the basic format
> --        // check above
> --
> --        str += 2;
> --
> --        if (*str == _XPLATSTR(':'))
> -+        if (result == nullptr)
> -         {
> --            ++str;
> -+            // Fill the date portion with the epoch,
> -+            // strptime will do the rest
> -+            memset(&output, 0, sizeof(struct tm));
> -+            output.tm_year = 70;
> -+            output.tm_mon = 1;
> -+            output.tm_mday = 1;
> -+            result = strptime(input.data(), "%H:%M:%SZ", &output);
> -         }
> --
> --        // parse seconds
> --        if (!ascii_isdigit6(str[0]) || !ascii_isdigit(str[1]))
> -+        if (result == nullptr)
> -         {
> --            return result;
> -+            result = strptime(input.data(), "%Y-%m-%d", &output);
> -         }
> --
> --        t.tm_sec = atoi2(str);
> --        // We allow 60 to account for leap seconds
> --        if (t.tm_sec > 60)
> -+        if (result == nullptr)
> -         {
> --            return result;
> -+            result = strptime(input.data(), "%Y%m%d", &output);
> -         }
> --
> --        str += 2;
> --        if (str[0] == _XPLATSTR('.') && ascii_isdigit(str[1]))
> -+        if (result == nullptr)
> -         {
> --            ++str;
> --            int digits = 7;
> --            for (;;)
> --            {
> --                frac_sec *= 10;
> --                frac_sec += *str - _XPLATSTR('0');
> --                --digits;
> --                ++str;
> --                if (digits == 0)
> --                {
> --                    while (ascii_isdigit(*str))
> --                    {
> --                        // consume remaining fractional second digits we can't use
> --                        ++str;
> --                    }
> --
> --                    break;
> --                }
> --
> --                if (!ascii_isdigit(*str))
> --                {
> --                    // no more digits in the input, do the remaining multiplies we need
> --                    for (; digits != 0; --digits)
> --                    {
> --                        frac_sec *= 10;
> --                    }
> --
> --                    break;
> --                }
> --            }
> -+            return datetime();
> -         }
> -+    }
> -
> --        seconds = make_gm_time(&t);
> --        if (seconds < 0)
> --        {
> --            return result;
> --        }
> -+#if (defined(ANDROID) || defined(__ANDROID__))
> -+    // HACK: The (nonportable?) POSIX function timegm is not available in
> -+    //       bionic. As a workaround[1][2], we set the C library timezone to
> -+    //       UTC, call mktime, then set the timezone back. However, the C
> -+    //       environment is fundamentally a shared global resource and thread-
> -+    //       unsafe. We can protect our usage here, however any other code might
> -+    //       manipulate the environment at the same time.
> -+    //
> -+    // [1] http://linux.die.net/man/3/timegm
> -+    // [2] http://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html
> -+    time_t time;
> -
> --        if (str[0] == _XPLATSTR('Z') || str[0] == _XPLATSTR('z'))
> -+    static boost::mutex env_var_lock;
> -+    {
> -+        boost::lock_guard<boost::mutex> lock(env_var_lock);
> -+        std::string prev_env;
> -+        auto prev_env_cstr = getenv("TZ");
> -+        if (prev_env_cstr != nullptr)
> -         {
> --            // no adjustment needed for zulu time
> -+            prev_env = prev_env_cstr;
> -         }
> --        else if (str[0] == _XPLATSTR('+') || str[0] == _XPLATSTR('-'))
> --        {
> --            const unsigned char offsetDirection = static_cast<unsigned char>(str[0]);
> --            if (!ascii_isdigit2(str[1]) || !ascii_isdigit(str[2]) || str[3] != _XPLATSTR(':') ||
> --                !ascii_isdigit5(str[4]) || !ascii_isdigit(str[5]))
> --            {
> --                return result;
> --            }
> -+        setenv("TZ", "UTC", 1);
> -
> --            seconds = timezone_adjust(seconds, offsetDirection, atoi2(str + 1), atoi2(str + 4));
> --            if (seconds < 0)
> --            {
> --                return result;
> --            }
> -+        time = mktime(&output);
> -+
> -+        if (prev_env_cstr)
> -+        {
> -+            setenv("TZ", prev_env.c_str(), 1);
> -         }
> -         else
> -         {
> --            // the timezone is malformed, but cpprestsdk currently accepts this as no timezone
> -+            unsetenv("TZ");
> -         }
> -     }
> --    else
> --    {
> --        throw std::invalid_argument("unrecognized date format");
> --    }
> -+#else
> -+    time_t time = timegm(&output);
> -+#endif
> -+
> -+    struct timeval tv = timeval();
> -+    tv.tv_sec = time;
> -+    auto result = timeval_to_datetime(tv);
> -
> --    seconds += ntToUnixOffsetSeconds;
> --    result.m_interval = static_cast<interval_type>(seconds) * _secondTicks + frac_sec;
> -+    // fractional seconds are already in correct format so just add them.
> -+    result = result + ufrac_second;
> -     return result;
> -+#endif
> - }
> -
> - /// <summary>
> -@@ -1358,32 +1181,38 @@ utility::seconds __cdecl timespan::xml_d
> -     // The final S could be omitted
> -
> -     int64_t numSecs = 0;
> --    auto cursor = timespanString.c_str();
> --    auto c = *cursor++; // skip 'P'
> --    while (c)
> -+
> -+    utility::istringstream_t is(timespanString);
> -+    is.imbue(std::locale::classic());
> -+    auto eof = std::char_traits<utility::char_t>::eof();
> -+
> -+    std::basic_istream<utility::char_t>::int_type c;
> -+    c = is.get(); // P
> -+
> -+    while (c != eof)
> -     {
> -         int val = 0;
> --        c = *cursor++;
> -+        c = is.get();
> -
> --        while (ascii_isdigit(c))
> -+        while (is_digit((utility::char_t)c))
> -         {
> --            val = val * 10 + (c - _XPLATSTR('0'));
> --            c = *cursor++;
> -+            val = val * 10 + (c - L'0');
> -+            c = is.get();
> -
> --            if (c == _XPLATSTR('.'))
> -+            if (c == '.')
> -             {
> -                 // decimal point is not handled
> -                 do
> -                 {
> --                    c = *cursor++;
> --                } while (ascii_isdigit(c));
> -+                    c = is.get();
> -+                } while (is_digit((utility::char_t)c));
> -             }
> -         }
> -
> --        if (c == _XPLATSTR('D')) numSecs += val * 24 * 3600; // days
> --        if (c == _XPLATSTR('H')) numSecs += val * 3600;      // Hours
> --        if (c == _XPLATSTR('M')) numSecs += val * 60;        // Minutes
> --        if (c == _XPLATSTR('S') || c == _XPLATSTR('\0'))
> -+        if (c == L'D') numSecs += val * 24 * 3600; // days
> -+        if (c == L'H') numSecs += val * 3600;      // Hours
> -+        if (c == L'M') numSecs += val * 60;        // Minutes
> -+        if (c == L'S' || c == eof)
> -         {
> -             numSecs += val; // seconds
> -             break;
> -@@ -1393,12 +1222,12 @@ utility::seconds __cdecl timespan::xml_d
> -     return utility::seconds(numSecs);
> - }
> -
> --static const utility::char_t c_allowed_chars[] =
> --    _XPLATSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
> -+const utility::string_t nonce_generator::c_allowed_chars(
> -+    _XPLATSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"));
> -
> - utility::string_t nonce_generator::generate()
> - {
> --    std::uniform_int_distribution<> distr(0, static_cast<int>(sizeof(c_allowed_chars) / sizeof(utility::char_t)) - 1);
> -+    std::uniform_int_distribution<> distr(0, static_cast<int>(c_allowed_chars.length() - 1));
> -     utility::string_t result;
> -     result.reserve(length());
> -     std::generate_n(std::back_inserter(result), length(), [&]() { return c_allowed_chars[distr(m_random)]; });
> ---- cpprest-2.10.12.orig/Release/tests/functional/utils/datetime.cpp
> -+++ cpprest-2.10.12/Release/tests/functional/utils/datetime.cpp
> -@@ -74,6 +74,16 @@ SUITE(datetime)
> -         }
> -     }
> -
> -+    TEST(parsing_time_extended)
> -+    {
> -+        // ISO 8601
> -+        {
> -+            auto dt = utility::datetime::from_string(_XPLATSTR("14:30:01Z"), utility::datetime::ISO_8601);
> -+
> -+            VERIFY_ARE_NOT_EQUAL(0u, dt.to_interval());
> -+        }
> -+    }
> -+
> -     void TestDateTimeRoundtrip(utility::string_t str, utility::string_t strExpected)
> -     {
> -         auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601);
> -@@ -91,8 +101,6 @@ SUITE(datetime)
> -
> -     TEST(parsing_time_roundtrip_datetime2)
> -     {
> --        // lose the last '000'
> --        TestDateTimeRoundtrip(_XPLATSTR("2013-11-19T14:30:59.1234567000Z"), _XPLATSTR("2013-11-19T14:30:59.1234567Z"));
> -         // lose the last '999' without rounding up
> -         TestDateTimeRoundtrip(_XPLATSTR("2013-11-19T14:30:59.1234567999Z"), _XPLATSTR("2013-11-19T14:30:59.1234567Z"));
> -     }
> -@@ -121,260 +129,16 @@ SUITE(datetime)
> -         TestDateTimeRoundtrip(_XPLATSTR("2013-11-19T14:30:59.5Z"));
> -     }
> -
> --    void TestRfc1123IsTimeT(const utility::char_t* str, time_t t)
> --    {
> --        datetime dt = datetime::from_string(str, utility::datetime::RFC_1123);
> --        uint64_t interval = dt.to_interval();
> --        VERIFY_ARE_EQUAL(0, interval % 10000000);
> --        interval /= 10000000;
> --        interval -= 11644473600; // NT epoch adjustment
> --        VERIFY_ARE_EQUAL(static_cast<uint64_t>(t), interval);
> --    }
> --
> --    TEST(parsing_time_rfc1123_accepts_each_day)
> --    {
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:00 GMT"), (time_t) 0);
> --        TestRfc1123IsTimeT(_XPLATSTR("Fri, 02 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 1);
> --        TestRfc1123IsTimeT(_XPLATSTR("Sat, 03 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 2);
> --        TestRfc1123IsTimeT(_XPLATSTR("Sun, 04 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 3);
> --        TestRfc1123IsTimeT(_XPLATSTR("Mon, 05 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 4);
> --        TestRfc1123IsTimeT(_XPLATSTR("Tue, 06 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 5);
> --        TestRfc1123IsTimeT(_XPLATSTR("Wed, 07 Jan 1970 00:00:00 GMT"), (time_t) 86400 * 6);
> --    }
> --
> --    TEST(parsing_time_rfc1123_boundary_cases)
> --    {
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:00 GMT"), (time_t) 0);
> --        TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:14:06 GMT"), (time_t) INT_MAX - 1);
> --#ifndef _USE_32BIT_TIME_T
> --        TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:13:07 -0001"), (time_t) INT_MAX);
> --        TestRfc1123IsTimeT(_XPLATSTR("19 Jan 2038 03:14:07 -0000"), (time_t) INT_MAX);
> --#endif // _USE_32BIT_TIME_T
> --        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0000"), (time_t) 1547507781);
> --        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 -0001"), (time_t) 1547507841);
> --        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0001"), (time_t) 1547507721);
> --        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 -0100"), (time_t) 1547511381);
> --        TestRfc1123IsTimeT(_XPLATSTR("14 Jan 2019 23:16:21 +0100"), (time_t) 1547504181);
> --    }
> --
> --    TEST(parsing_time_rfc1123_uses_each_field)
> --    {
> --        TestRfc1123IsTimeT(_XPLATSTR("02 Jan 1970 00:00:00 GMT"), (time_t) 86400);
> --        TestRfc1123IsTimeT(_XPLATSTR("12 Jan 1970 00:00:00 GMT"), (time_t) 950400);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Feb 1970 00:00:00 GMT"), (time_t) 2678400);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 2000 00:00:00 GMT"), (time_t) 946684800);
> --#ifndef _USE_32BIT_TIME_T
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 2100 00:00:00 GMT"), (time_t) 4102444800);
> --#endif // _USE_32BIT_TIME_T
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1990 00:00:00 GMT"), (time_t) 631152000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1971 00:00:00 GMT"), (time_t) 31536000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 10:00:00 GMT"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 01:00:00 GMT"), (time_t) 3600);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:10:00 GMT"), (time_t) 600);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:01:00 GMT"), (time_t) 60);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:10 GMT"), (time_t) 10);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 00:00:01 GMT"), (time_t) 1);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 10:00:00 GMT"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 02:00:00 PST"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 03:00:00 PDT"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 03:00:00 MST"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 04:00:00 MDT"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 04:00:00 CST"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:00:00 CDT"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:00:00 EST"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 06:00:00 EDT"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 06:00:00 -0400"), (time_t) 36000);
> --        TestRfc1123IsTimeT(_XPLATSTR("01 Jan 1970 05:59:00 -0401"), (time_t) 36000);
> --    }
> --
> --    TEST(parsing_time_rfc1123_max_days)
> --    {
> --        TestRfc1123IsTimeT(_XPLATSTR("31 Jan 1970 00:00:00 GMT"), (time_t) 2592000);
> --        TestRfc1123IsTimeT(_XPLATSTR("28 Feb 2019 00:00:00 GMT"), (time_t) 1551312000); // non leap year allows feb 28
> --        TestRfc1123IsTimeT(_XPLATSTR("29 Feb 2020 00:00:00 GMT"), (time_t) 1582934400); // leap year allows feb 29
> --        TestRfc1123IsTimeT(_XPLATSTR("31 Mar 1970 00:00:00 GMT"), (time_t) 7689600);
> --        TestRfc1123IsTimeT(_XPLATSTR("30 Apr 1970 00:00:00 GMT"), (time_t) 10281600);
> --        TestRfc1123IsTimeT(_XPLATSTR("31 May 1970 00:00:00 GMT"), (time_t) 12960000);
> --        TestRfc1123IsTimeT(_XPLATSTR("30 Jun 1970 00:00:00 GMT"), (time_t) 15552000);
> --        TestRfc1123IsTimeT(_XPLATSTR("31 Jul 1970 00:00:00 GMT"), (time_t) 18230400);
> --        TestRfc1123IsTimeT(_XPLATSTR("31 Aug 1970 00:00:00 GMT"), (time_t) 20908800);
> --        TestRfc1123IsTimeT(_XPLATSTR("30 Sep 1970 00:00:00 GMT"), (time_t) 23500800);
> --        TestRfc1123IsTimeT(_XPLATSTR("31 Oct 1970 00:00:00 GMT"), (time_t) 26179200);
> --        TestRfc1123IsTimeT(_XPLATSTR("30 Nov 1970 00:00:00 GMT"), (time_t) 28771200);
> --        TestRfc1123IsTimeT(_XPLATSTR("31 Dec 1970 00:00:00 GMT"), (time_t) 31449600);
> --    }
> --
> --    TEST(parsing_time_rfc1123_invalid_cases)
> --    {
> --        const utility::string_t bad_strings[] = {
> --            _XPLATSTR("Ahu, 01 Jan 1970 00:00:00 GMT"), // bad letters in each place
> --            _XPLATSTR("TAu, 01 Jan 1970 00:00:00 GMT"),
> --            _XPLATSTR("ThA, 01 Jan 1970 00:00:00 GMT"),
> --            _XPLATSTR("ThuA 01 Jan 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu,A01 Jan 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, A1 Jan 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 0A Jan 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01AJan 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Aan 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 JAn 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 JaA 1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 JanA1970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan A970 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1A70 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 19A0 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 197A 00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970A00:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 A0:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 0A:00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00A00:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:A0:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:0A:00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00A00 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:A0 GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:0A GMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:00AGMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:00 AMT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:00 GAT"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:00 GMA"),
> --            _XPLATSTR(""), // truncation
> --            _XPLATSTR("T"),
> --            _XPLATSTR("Th"),
> --            _XPLATSTR("Thu"),
> --            _XPLATSTR("Thu,"),
> --            _XPLATSTR("Thu, "),
> --            _XPLATSTR("Thu, 0"),
> --            _XPLATSTR("Thu, 01"),
> --            _XPLATSTR("Thu, 01 "),
> --            _XPLATSTR("Thu, 01 J"),
> --            _XPLATSTR("Thu, 01 Ja"),
> --            _XPLATSTR("Thu, 01 Jan"),
> --            _XPLATSTR("Thu, 01 Jan "),
> --            _XPLATSTR("Thu, 01 Jan 1"),
> --            _XPLATSTR("Thu, 01 Jan 19"),
> --            _XPLATSTR("Thu, 01 Jan 197"),
> --            _XPLATSTR("Thu, 01 Jan 1970"),
> --            _XPLATSTR("Thu, 01 Jan 1970 "),
> --            _XPLATSTR("Thu, 01 Jan 1970 0"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:0"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:0"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:00"),
> --            _XPLATSTR("Thu, 01 Jan 1970 00:00:00 "),
> --            _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 4970 00:00:00 GMT"), // year too big
> --            _XPLATSTR("01 Jan 3001 00:00:00 GMT"),
> --            _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"),
> --            _XPLATSTR("32 Jul 1971 00:00:00 GMT"),
> --            _XPLATSTR("32 Aug 1971 00:00:00 GMT"),
> --            _XPLATSTR("31 Sep 1971 00:00:00 GMT"),
> --            _XPLATSTR("32 Oct 1971 00:00:00 GMT"),
> --            _XPLATSTR("31 Nov 1971 00:00:00 GMT"),
> --            _XPLATSTR("32 Dec 1971 00:00:00 GMT"),
> --            _XPLATSTR("01 Jan 1971 70:00:00 GMT"), // hour too big
> --            _XPLATSTR("01 Jan 1971 24:00:00 GMT"),
> --            _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 1969 00:00:00 GMT"), // underflow
> --            _XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz
> --            _XPLATSTR("01 Jan 1970 00:00:00 +2400"), // bad tzoffsets
> --            _XPLATSTR("01 Jan 1970 00:00:00 -3000"),
> --            _XPLATSTR("01 Jan 1970 00:00:00 +2160"),
> --            _XPLATSTR("01 Jan 1970 00:00:00 -2400"),
> --            _XPLATSTR("01 Jan 1970 00:00:00 -2160"),
> --        };
> --
> --        for (const auto& str : bad_strings)
> --        {
> --            auto dt = utility::datetime::from_string(str, utility::datetime::RFC_1123);
> --            VERIFY_ARE_EQUAL(0, dt.to_interval());
> --        }
> --    }
> --
> --    TEST(parsing_time_iso8601_boundary_cases)
> --    {
> --        // boundary cases:
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:00:00Z"));                                         // epoch
> --        TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:14:06+00:00"), _XPLATSTR("2038-01-19T03:14:06Z")); // INT_MAX - 1
> --#ifndef _USE_32BIT_TIME_T
> --        TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:13:07-00:01"),
> --                              _XPLATSTR("2038-01-19T03:14:07Z")); // INT_MAX after subtacting 1
> --        TestDateTimeRoundtrip(_XPLATSTR("2038-01-19T03:14:07-00:00"), _XPLATSTR("2038-01-19T03:14:07Z"));
> --#endif // _USE_32BIT_TIME_T
> --    }
> --
> --    TEST(parsing_time_iso8601_uses_each_timezone_digit)
> --    {
> --        TestDateTimeRoundtrip(_XPLATSTR("2019-01-14T23:16:21+00:00"), _XPLATSTR("2019-01-14T23:16:21Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("2019-01-14T23:16:21-00:01"), _XPLATSTR("2019-01-14T23:17:21Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("2019-01-14T23:16:21+00:01"), _XPLATSTR("2019-01-14T23:15:21Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("2019-01-14T23:16:21-01:00"), _XPLATSTR("2019-01-15T00:16:21Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("2019-01-14T23:16:21+01:00"), _XPLATSTR("2019-01-14T22:16:21Z"));
> --    }
> --
> --    TEST(parsing_time_iso8601_uses_each_digit)
> --    {
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:00:01Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:01:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T01:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-02T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-02-01T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1971-01-01T00:00:00Z"));
> --
> --        TestDateTimeRoundtrip(_XPLATSTR("1999-01-01T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-12-01T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-09-01T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-30T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-31T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T23:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T19:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:59:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:00:59Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:00:60Z"), _XPLATSTR("1970-01-01T00:01:00Z")); // leap seconds
> --    }
> --
> --    TEST(parsing_time_iso8601_accepts_month_max_days)
> --    {
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-31T00:00:00Z")); // jan
> --        TestDateTimeRoundtrip(_XPLATSTR("2019-02-28T00:00:00Z")); // non leap year allows feb 28
> --        TestDateTimeRoundtrip(_XPLATSTR("2020-02-29T00:00:00Z")); // leap year allows feb 29
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-03-31T00:00:00Z")); // mar
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-04-30T00:00:00Z")); // apr
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-05-31T00:00:00Z")); // may
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-06-30T00:00:00Z")); // jun
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-07-31T00:00:00Z")); // jul
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-08-31T00:00:00Z")); // aug
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-09-30T00:00:00Z")); // sep
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-10-31T00:00:00Z")); // oct
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-11-30T00:00:00Z")); // nov
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-12-31T00:00:00Z")); // dec
> --    }
> --
> --    TEST(parsing_time_iso8601_accepts_lowercase_t_z)
> --    {
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01t00:00:00Z"), _XPLATSTR("1970-01-01T00:00:00Z"));
> --        TestDateTimeRoundtrip(_XPLATSTR("1970-01-01T00:00:00z"), _XPLATSTR("1970-01-01T00:00:00Z"));
> --    }
> --
> --    TEST(parsing_time_roundtrip_datetime_accepts_invalid_no_trailing_timezone)
> -+    TEST(parsing_time_roundtrip_datetime_invalid1,
> -+         "Ignore:Linux",
> -+         "Codeplex issue #115",
> -+         "Ignore:Apple",
> -+         "Codeplex issue #115")
> -     {
> -         // No digits after the dot, or non-digits. This is not a valid input, but we should not choke on it,
> -         // Simply ignore the bad fraction
> -         const utility::string_t bad_strings[] = {_XPLATSTR("2013-11-19T14:30:59.Z"),
> --                                                 _XPLATSTR("2013-11-19T14:30:59.a12Z")};
> -+                                                 _XPLATSTR("2013-11-19T14:30:59.1a2Z")};
> -         utility::string_t str_corrected = _XPLATSTR("2013-11-19T14:30:59Z");
> -
> -         for (const auto& str : bad_strings)
> -@@ -387,87 +151,12 @@ SUITE(datetime)
> -
> -     TEST(parsing_time_roundtrip_datetime_invalid2)
> -     {
> --        // Various unsupported cases. In all cases, we have produce an empty date time
> -+        // Variouls unsupported cases. In all cases, we have produce an empty date time
> -         const utility::string_t bad_strings[] = {
> --            _XPLATSTR(""),                     // empty
> --            _XPLATSTR(".Z"),                   // too short
> --            _XPLATSTR(".Zx"),                  // no trailing Z
> --            _XPLATSTR("3.14Z")                 // not a valid date
> --            _XPLATSTR("a971-01-01T00:00:00Z"), // any non digits or valid separators
> --            _XPLATSTR("1a71-01-01T00:00:00Z"),
> --            _XPLATSTR("19a1-01-01T00:00:00Z"),
> --            _XPLATSTR("197a-01-01T00:00:00Z"),
> --            _XPLATSTR("1971a01-01T00:00:00Z"),
> --            _XPLATSTR("1971-a1-01T00:00:00Z"),
> --            _XPLATSTR("1971-0a-01T00:00:00Z"),
> --            _XPLATSTR("1971-01a01T00:00:00Z"),
> --            _XPLATSTR("1971-01-a1T00:00:00Z"),
> --            _XPLATSTR("1971-01-0aT00:00:00Z"),
> --            // _XPLATSTR("1971-01-01a00:00:00Z"), parsed as complete date
> --            _XPLATSTR("1971-01-01Ta0:00:00Z"),
> --            _XPLATSTR("1971-01-01T0a:00:00Z"),
> --            _XPLATSTR("1971-01-01T00a00:00Z"),
> --            _XPLATSTR("1971-01-01T00:a0:00Z"),
> --            _XPLATSTR("1971-01-01T00:0a:00Z"),
> --            _XPLATSTR("1971-01-01T00:00a00Z"),
> --            _XPLATSTR("1971-01-01T00:00:a0Z"),
> --            _XPLATSTR("1971-01-01T00:00:0aZ"),
> --            // "1971-01-01T00:00:00a", accepted as per invalid_no_trailing_timezone above
> --            _XPLATSTR("1"), // truncation
> --            _XPLATSTR("19"),
> --            _XPLATSTR("197"),
> --            _XPLATSTR("1970"),
> --            _XPLATSTR("1970-"),
> --            _XPLATSTR("1970-0"),
> --            _XPLATSTR("1970-01"),
> --            _XPLATSTR("1970-01-"),
> --            _XPLATSTR("1970-01-0"),
> --            // _XPLATSTR("1970-01-01"), complete date
> --            _XPLATSTR("1970-01-01T"),
> --            _XPLATSTR("1970-01-01T0"),
> --            _XPLATSTR("1970-01-01T00"),
> --            _XPLATSTR("1970-01-01T00:"),
> --            _XPLATSTR("1970-01-01T00:0"),
> --            _XPLATSTR("1970-01-01T00:00"),
> --            _XPLATSTR("1970-01-01T00:00:"),
> --            _XPLATSTR("1970-01-01T00:00:0"),
> --            // _XPLATSTR("1970-01-01T00:00:00"), // accepted as invalid timezone above
> --            _XPLATSTR("4970-01-01T00:00:00Z"), // year too big
> --            _XPLATSTR("3001-01-01T00:00:00Z"),
> --            _XPLATSTR("1971-00-01T00:00:00Z"), // month too small
> --            _XPLATSTR("1971-20-01T00:00:00Z"), // month too big
> --            _XPLATSTR("1971-13-01T00:00:00Z"),
> --            _XPLATSTR("1971-01-00T00:00:00Z"), // day too small
> --            _XPLATSTR("1971-01-32T00:00:00Z"), // day too big
> --            _XPLATSTR("1971-02-30T00:00:00Z"), // day too big for feb
> --            _XPLATSTR("1971-02-30T00:00:00Z"), // day too big for feb (non-leap year)
> --            _XPLATSTR("1971-03-32T00:00:00Z"), // other months
> --            _XPLATSTR("1971-04-31T00:00:00Z"),
> --            _XPLATSTR("1971-05-32T00:00:00Z"),
> --            _XPLATSTR("1971-06-31T00:00:00Z"),
> --            _XPLATSTR("1971-07-32T00:00:00Z"),
> --            _XPLATSTR("1971-08-32T00:00:00Z"),
> --            _XPLATSTR("1971-09-31T00:00:00Z"),
> --            _XPLATSTR("1971-10-32T00:00:00Z"),
> --            _XPLATSTR("1971-11-31T00:00:00Z"),
> --            _XPLATSTR("1971-12-32T00:00:00Z"),
> --            _XPLATSTR("1971-01-01T70:00:00Z"), // hour too big
> --            _XPLATSTR("1971-01-01T24:00:00Z"),
> --            _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("1969-01-01T00:00:00Z"), // underflow
> --#ifdef _USE_32BIT_TIME_T
> --            _XPLATSTR("3000-01-01T00:00:01Z"), // overflow
> --#endif
> --            _XPLATSTR("3001-01-01T00:00:00Z"),
> --            _XPLATSTR("1970-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"),
> --            _XPLATSTR("1970-01-01T00:00:00+21:60"),
> --            _XPLATSTR("1970-01-01T00:00:00-24:00"),
> --            _XPLATSTR("1970-01-01T00:00:00-21:60"),
> -+            _XPLATSTR(""),     // empty
> -+            _XPLATSTR(".Z"),   // too short
> -+            _XPLATSTR(".Zx"),  // no trailing Z
> -+            _XPLATSTR("3.14Z") // not a valid date
> -         };
> -
> -         for (const auto& str : bad_strings)
> -@@ -477,6 +166,16 @@ SUITE(datetime)
> -         }
> -     }
> -
> -+    TEST(parsing_time_roundtrip_time)
> -+    {
> -+        // time only without date
> -+        utility::string_t str = _XPLATSTR("14:30:59.1234567Z");
> -+        auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601);
> -+        utility::string_t str2 = dt.to_string(utility::datetime::ISO_8601);
> -+        // Must look for a substring now, since the date part is filled with today's date
> -+        VERIFY_IS_TRUE(str2.find(str) != std::string::npos);
> -+    }
> -+
> - } // SUITE(datetime)
> -
> - } // namespace utils_tests
> diff --git a/meta-oe/recipes-support/cpprest/cpprest_2.10.12.bb b/meta-oe/recipes-support/cpprest/cpprest_2.10.12.bb
> index 92c04535d..67edf5691 100644
> --- a/meta-oe/recipes-support/cpprest/cpprest_2.10.12.bb
> +++ b/meta-oe/recipes-support/cpprest/cpprest_2.10.12.bb
> @@ -8,9 +8,7 @@ DEPENDS = "openssl websocketpp zlib boost brotli"
>   EXTRA_OECMAKE = "-DCPPREST_EXPORT_DIR=cmake -DCPPREST_EXCLUDE_BROTLI=OFF"
>   
>   SRC_URI = "git://github.com/Microsoft/cpprestsdk.git;protocol=https;branch=master \
> -           file://revert-9b670e5b33dfdbd501d618cd7e7498148ffbd559.patch \
> -           file://revert-f10d9f8e214516d2c19aa6ef831ee874a58c0479.patch \
> -           "
> +           file://1094.patch "
>   
>   # tag 2.10.12
>   SRCREV= "d4fb1cf7f7d22c12e2e442ba5a5e98d09b0a28ab"
> 

-- 
Paul Barker
Managing Director & Principal Engineer
Beta Five Ltd


More information about the Openembedded-devel mailing list