Skip to content

Commit 0aeab5a

Browse files
committed
[libc++][chrono] Improves date formatting.
The formatting of years has been done manually since the results of %Y outside the "typical" range may produce unexpected values. The same applies to %F which is identical to %Y-%m-%d. Note of these conversion specifiers is affected by the locale used. So it's trivial to manually handle this case. This removes several platform specific ifdefs from the tests.
1 parent 6327aee commit 0aeab5a

File tree

4 files changed

+7
-95
lines changed

4 files changed

+7
-95
lines changed

libcxx/include/__chrono/formatter.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,15 +322,13 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
322322
__formatter::__format_year(__sstr, __t.tm_year + 1900);
323323
break;
324324

325-
case _CharT('F'): {
326-
int __year = __t.tm_year + 1900;
327-
if (__year < 1000) {
328-
__formatter::__format_year(__sstr, __year);
329-
__sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday);
330-
} else
331-
__facet.put(
332-
{__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
333-
} break;
325+
case _CharT('F'):
326+
// Depending on the platform's libc the range of supported years is
327+
// limited. Intead of of testing all conditions use the internal
328+
// implementation unconditionally.
329+
__formatter::__format_year(__sstr, __t.tm_year + 1900);
330+
__sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday);
331+
break;
334332

335333
case _CharT('z'):
336334
__formatter::__format_zone_offset(__sstr, __z.__offset, false);

libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,9 @@ static void test() {
8989
TEST_EQUAL(stream_c_locale<CharT>(
9090
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}),
9191
SV("2000-02-29"));
92-
93-
#if defined(_AIX)
94-
TEST_EQUAL(stream_c_locale<CharT>(
95-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
96-
SV("+32767-12-31"));
97-
#elif defined(_WIN32) // defined(_AIX)
98-
TEST_EQUAL(stream_c_locale<CharT>(
99-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
100-
SV(""));
101-
#else // defined(_AIX)
10292
TEST_EQUAL(stream_c_locale<CharT>(
10393
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
10494
SV("32767-12-31"));
105-
#endif // defined(_AIX)
10695

10796
TEST_EQUAL(stream_fr_FR_locale<CharT>(
10897
std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}),
@@ -122,19 +111,9 @@ static void test() {
122111
TEST_EQUAL(stream_fr_FR_locale<CharT>(
123112
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}),
124113
SV("2000-02-29"));
125-
#if defined(_AIX)
126-
TEST_EQUAL(stream_fr_FR_locale<CharT>(
127-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
128-
SV("+32767-12-31"));
129-
#elif defined(_WIN32) // defined(_AIX)
130-
TEST_EQUAL(stream_fr_FR_locale<CharT>(
131-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
132-
SV(""));
133-
#else // defined(_AIX)
134114
TEST_EQUAL(stream_fr_FR_locale<CharT>(
135115
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
136116
SV("32767-12-31"));
137-
#endif // defined(_AIX)
138117

139118
TEST_EQUAL(stream_ja_JP_locale<CharT>(
140119
std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}),
@@ -154,19 +133,9 @@ static void test() {
154133
TEST_EQUAL(stream_ja_JP_locale<CharT>(
155134
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}),
156135
SV("2000-02-29"));
157-
#if defined(_AIX)
158-
TEST_EQUAL(stream_ja_JP_locale<CharT>(
159-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
160-
SV("+32767-12-31"));
161-
#elif defined(_WIN32) // defined(_AIX)
162-
TEST_EQUAL(stream_ja_JP_locale<CharT>(
163-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
164-
SV(""));
165-
#else // defined(_AIX)
166136
TEST_EQUAL(stream_ja_JP_locale<CharT>(
167137
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
168138
SV("32767-12-31"));
169-
#endif // defined(_AIX)
170139
}
171140

172141
int main(int, char**) {

libcxx/test/std/time/time.clock/time.clock.system/sys_date.ostream.pass.cpp

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,9 @@ static void test() {
8181
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
8282
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
8383
SV("2000-02-29"));
84-
85-
#if defined(_AIX)
86-
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
87-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
88-
SV("+32767-12-31"));
89-
#elif defined(_WIN32) // defined(_AIX)
90-
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
91-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
92-
SV(""));
93-
#else // defined(_AIX)
9484
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
9585
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
9686
SV("32767-12-31"));
97-
#endif // defined(_AIX)
9887

9988
// multiples of days are considered days.
10089
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),
@@ -112,19 +101,9 @@ static void test() {
112101
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
113102
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
114103
SV("2000-02-29"));
115-
#if defined(_AIX)
116-
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
117-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
118-
SV("+32767-12-31"));
119-
#elif defined(_WIN32) // defined(_AIX)
120-
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
121-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
122-
SV(""));
123-
#else // defined(_AIX)
124104
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
125105
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
126106
SV("32767-12-31"));
127-
#endif // defined(_AIX)
128107

129108
// multiples of days are considered days.
130109
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),
@@ -142,19 +121,9 @@ static void test() {
142121
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
143122
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
144123
SV("2000-02-29"));
145-
#if defined(_AIX)
146-
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
147-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
148-
SV("+32767-12-31"));
149-
#elif defined(_WIN32) // defined(_AIX)
150-
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
151-
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
152-
SV(""));
153-
#else // defined(_AIX)
154124
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
155125
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
156126
SV("32767-12-31"));
157-
#endif // defined(_AIX)
158127

159128
// multiples of days are considered days.
160129
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),

libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,6 @@ static void test_no_chrono_specs() {
6262
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{2}, std::chrono::day{31}});
6363

6464
// Valid year, invalid month, valid day
65-
#ifdef _WIN32
66-
check(SV(" is not a valid date"),
67-
SV("{}"),
68-
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}});
69-
check(SV("****** is not a valid date******"),
70-
SV("{:*^32}"),
71-
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}});
72-
check(SV("*********** is not a valid date"),
73-
SV("{:*>31}"),
74-
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}});
75-
#else // _WIN32
7665
check(SV("1970-00-31 is not a valid date"),
7766
SV("{}"),
7867
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}});
@@ -82,20 +71,8 @@ static void test_no_chrono_specs() {
8271
check(SV("*1970-00-31 is not a valid date"),
8372
SV("{:*>31}"),
8473
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{31}});
85-
#endif // _WIN32
8674

8775
// Valid year, invalid month, invalid day
88-
#ifdef _WIN32
89-
check(SV(" is not a valid date"),
90-
SV("{}"),
91-
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}});
92-
check(SV("****** is not a valid date******"),
93-
SV("{:*^32}"),
94-
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}});
95-
check(SV("*********** is not a valid date"),
96-
SV("{:*>31}"),
97-
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}});
98-
#else // _WIN32
9976
check(SV("1970-00-32 is not a valid date"),
10077
SV("{}"),
10178
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}});
@@ -105,7 +82,6 @@ static void test_no_chrono_specs() {
10582
check(SV("*1970-00-32 is not a valid date"),
10683
SV("{:*>31}"),
10784
std::chrono::year_month_day{std::chrono::year{1970}, std::chrono::month{0}, std::chrono::day{32}});
108-
#endif // _WIN32
10985

11086
// Invalid year, valid month, valid day
11187
check(SV("-32768-01-31 is not a valid date"),

0 commit comments

Comments
 (0)