Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit faa72d6

Browse files
Introduce new API from_string_maximum_error so that legitimate 1601 can be distinguished from parse failure.
1 parent 7046d3a commit faa72d6

File tree

3 files changed

+62
-51
lines changed

3 files changed

+62
-51
lines changed

‎Release/include/cpprest/asyncrt_utils.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -603,14 +603,21 @@ class datetime
603603
}
604604
}
605605

606-
datetime() : m_interval(0) {}
606+
datetime() : m_interval(0) {}
607607

608608
/// <summary>
609-
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 format.
609+
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 or ISO 8601 format.
610610
/// </summary>
611611
/// <returns>Returns a <c>datetime</c> of zero if not successful.</returns>
612612
static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123);
613613

614+
/// <summary>
615+
/// Creates <c>datetime</c> from a string representing time in UTC in RFC 1123 or ISO 8601 format.
616+
/// </summary>
617+
/// <returns>Returns <c>datetime::maximum()</c> if not successful.</returns>
618+
static _ASYNCRTIMP datetime __cdecl from_string_maximum_error(const utility::string_t& timestring,
619+
date_format format = RFC_1123);
620+
614621
/// <summary>
615622
/// Returns a string representation of the <c>datetime</c>.
616623
/// </summary>
@@ -628,13 +635,13 @@ class datetime
628635
bool operator==(datetime dt) const { return m_interval == dt.m_interval; }
629636

630637
bool operator!=(const datetime& dt) const { return !(*this == dt); }
631-
638+
632639
bool operator>(const datetime& dt) const { return this->m_interval > dt.m_interval; }
633-
640+
634641
bool operator<(const datetime& dt) const { return this->m_interval < dt.m_interval; }
635-
642+
636643
bool operator>=(const datetime& dt) const { return this->m_interval >= dt.m_interval; }
637-
644+
638645
bool operator<=(const datetime& dt) const { return this->m_interval <= dt.m_interval; }
639646

640647
static interval_type from_milliseconds(unsigned int milliseconds) { return milliseconds * _msTicks; }
@@ -649,6 +656,8 @@ class datetime
649656

650657
bool is_initialized() const { return m_interval != 0; }
651658

659+
static datetime maximum() { return datetime(static_cast<interval_type>(-1)); }
660+
652661
private:
653662
friend int operator-(datetime t1, datetime t2);
654663

@@ -659,7 +668,7 @@ class datetime
659668
static const interval_type _dayTicks = 24 * 60 * 60 * _secondTicks;
660669

661670
// Private constructor. Use static methods to create an instance.
662-
datetime(interval_type interval) : m_interval(interval) {}
671+
datetime(interval_type interval) : m_interval(interval) {}
663672

664673
// Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns.
665674
interval_type m_interval;

‎Release/src/utilities/asyncrt_utils.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -995,10 +995,20 @@ zone = "UT" / "GMT" ; Universal Time
995995
; hours+min. (HHMM)
996996
*/
997997

998-
999998
datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format)
1000999
{
1001-
datetime result;
1000+
auto result = from_string_maximum_error(dateString, format);
1001+
if (result == datetime::maximum())
1002+
{
1003+
return datetime();
1004+
}
1005+
1006+
return result;
1007+
}
1008+
1009+
datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& dateString, date_format format)
1010+
{
1011+
datetime result = datetime::maximum();
10021012
int64_t secondsSince1900;
10031013
uint64_t fracSec = 0;
10041014
auto str = dateString.c_str();

‎Release/tests/functional/utils/datetime.cpp

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
****/
1111

1212
#include "stdafx.h"
13+
1314
#include <stdint.h>
1415
#include <string>
1516

@@ -81,6 +82,10 @@ SUITE(datetime)
8182
auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601);
8283
utility::string_t str2 = dt.to_string(utility::datetime::ISO_8601);
8384
VERIFY_ARE_EQUAL(str2, strExpected);
85+
86+
auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::ISO_8601);
87+
utility::string_t str3 = dt_me.to_string(utility::datetime::ISO_8601);
88+
VERIFY_ARE_EQUAL(str3, strExpected);
8489
}
8590

8691
void TestDateTimeRoundtrip(utility::string_t str) { TestDateTimeRoundtrip(str, str); }
@@ -123,32 +128,18 @@ SUITE(datetime)
123128
TestDateTimeRoundtrip(_XPLATSTR("2013年11月19日T14:30:59.5Z"));
124129
}
125130

126-
TEST(parsing_time_roundtrip_year_1900)
127-
{
128-
TestDateTimeRoundtrip(_XPLATSTR("1900年01月01日T00:00:00Z"));
129-
}
131+
TEST(parsing_time_roundtrip_year_1900) { TestDateTimeRoundtrip(_XPLATSTR("1900年01月01日T00:00:00Z")); }
130132

131-
TEST(parsing_time_roundtrip_year_9999)
132-
{
133-
TestDateTimeRoundtrip(_XPLATSTR("9999年12月31日T23:59:59Z"));
134-
}
133+
TEST(parsing_time_roundtrip_year_9999) { TestDateTimeRoundtrip(_XPLATSTR("9999年12月31日T23:59:59Z")); }
135134

136-
TEST(parsing_time_roundtrip_year_2016)
137-
{
138-
TestDateTimeRoundtrip(_XPLATSTR("2016年12月31日T20:59:59Z"));
139-
}
135+
TEST(parsing_time_roundtrip_year_2016) { TestDateTimeRoundtrip(_XPLATSTR("2016年12月31日T20:59:59Z")); }
140136

141-
TEST(parsing_time_roundtrip_year_2020)
142-
{
143-
TestDateTimeRoundtrip(_XPLATSTR("2020年12月31日T20:59:59Z"));
144-
}
137+
TEST(parsing_time_roundtrip_year_2020) { TestDateTimeRoundtrip(_XPLATSTR("2020年12月31日T20:59:59Z")); }
145138

146-
TEST(parsing_time_roundtrip_year_2021)
147-
{
148-
TestDateTimeRoundtrip(_XPLATSTR("2021年01月01日T20:59:59Z"));
149-
}
139+
TEST(parsing_time_roundtrip_year_2021) { TestDateTimeRoundtrip(_XPLATSTR("2021年01月01日T20:59:59Z")); }
150140

151-
TEST(emitting_time_correct_day) {
141+
TEST(emitting_time_correct_day)
142+
{
152143
const auto test = utility::datetime() + UINT64_C(132004507640000000); // 2019年04月22日T23:52:44 is a Monday
153144
const auto actual = test.to_string(utility::datetime::RFC_1123);
154145
const utility::string_t expected(_XPLATSTR("Mon"));
@@ -296,13 +287,13 @@ SUITE(datetime)
296287
_XPLATSTR("1970年1月01日 00:00:00 G"),
297288
_XPLATSTR("1970年1月01日 00:00:00 GM"),
298289
_XPLATSTR("1970年1月01日 00:00:00 GMT"), // wrong day
299-
_XPLATSTR("01 Jan 1899 00:00:00 GMT"), // year too small
300-
_XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad
301-
_XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small
302-
_XPLATSTR("32 Jan 1971 00:00:00 GMT"), // day too big
303-
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb
304-
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb (non-leap year)
305-
_XPLATSTR("32 Mar 1971 00:00:00 GMT"), // other months
290+
_XPLATSTR("01 Jan 1899 00:00:00 GMT"), // year too small
291+
_XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad
292+
_XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small
293+
_XPLATSTR("32 Jan 1971 00:00:00 GMT"), // day too big
294+
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb
295+
_XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb (non-leap year)
296+
_XPLATSTR("32 Mar 1971 00:00:00 GMT"), // other months
306297
_XPLATSTR("31 Apr 1971 00:00:00 GMT"),
307298
_XPLATSTR("32 May 1971 00:00:00 GMT"),
308299
_XPLATSTR("31 Jun 1971 00:00:00 GMT"),
@@ -317,8 +308,8 @@ SUITE(datetime)
317308
_XPLATSTR("01 Jan 1971 00:60:00 GMT"), // minute too big
318309
_XPLATSTR("01 Jan 1971 00:00:70 GMT"), // second too big
319310
_XPLATSTR("01 Jan 1971 00:00:61 GMT"),
320-
_XPLATSTR("01 Jan 1899 00:00:00 GMT"), // underflow
321-
_XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz
311+
_XPLATSTR("01 Jan 1899 00:00:00 GMT"), // underflow
312+
_XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz
322313
_XPLATSTR("14 Jan 2019 23:16:21 G0100"), // bad tzoffsets
323314
_XPLATSTR("01 Jan 1970 00:00:00 +2400"),
324315
_XPLATSTR("01 Jan 1970 00:00:00 -3000"),
@@ -332,6 +323,8 @@ SUITE(datetime)
332323
{
333324
auto dt = utility::datetime::from_string(str, utility::datetime::RFC_1123);
334325
VERIFY_ARE_EQUAL(0, dt.to_interval());
326+
auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::RFC_1123);
327+
VERIFY_ARE_EQUAL(utility::datetime::maximum(), dt_me);
335328
}
336329
}
337330

@@ -484,7 +477,7 @@ SUITE(datetime)
484477
_XPLATSTR("1971年01月01日T00:60:00Z"), // minute too big
485478
_XPLATSTR("1971年01月01日T00:00:70Z"), // second too big
486479
_XPLATSTR("1971年01月01日T00:00:61Z"),
487-
_XPLATSTR("1899年01月01日T00:00:00Z"), // underflow
480+
_XPLATSTR("1899年01月01日T00:00:00Z"), // underflow
488481
_XPLATSTR("1900年01月01日T00:00:00+00:01"), // time zone underflow
489482
// _XPLATSTR("1970年01月01日T00:00:00.Z"), // accepted as invalid timezone above
490483
_XPLATSTR("1970年01月01日T00:00:00+24:00"), // bad tzoffsets
@@ -499,23 +492,22 @@ SUITE(datetime)
499492
{
500493
auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601);
501494
VERIFY_ARE_EQUAL(dt.to_interval(), 0);
495+
auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::ISO_8601);
496+
VERIFY_ARE_EQUAL(dt_me, utility::datetime::maximum());
502497
}
503498
}
504499

505-
TEST(can_emit_nt_epoch_zero)
500+
TEST(can_emit_nt_epoch_zero_rfc_1123)
506501
{
507-
// ISO 8601
508-
{
509-
auto result = utility::datetime{}.to_string(utility::datetime::RFC_1123);
510-
VERIFY_ARE_EQUAL(_XPLATSTR("1601年1月01日 00:00:00 GMT"), result);
511-
}
512-
// ISO 8601
513-
{
514-
auto result = utility::datetime{}.to_string(utility::datetime::ISO_8601);
515-
VERIFY_ARE_EQUAL(_XPLATSTR("1601年01月01日T00:00:00Z"), result);
516-
}
502+
auto result = utility::datetime {}.to_string(utility::datetime::RFC_1123);
503+
VERIFY_ARE_EQUAL(_XPLATSTR("1601年1月01日 00:00:00 GMT"), result);
517504
}
518505

506+
TEST(can_emit_nt_epoch_zero_iso_8601)
507+
{
508+
auto result = utility::datetime {}.to_string(utility::datetime::ISO_8601);
509+
VERIFY_ARE_EQUAL(_XPLATSTR("1601年01月01日T00:00:00Z"), result);
510+
}
519511
} // SUITE(datetime)
520512

521513
} // namespace utils_tests

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /