Skip to content

Commit f3e7b58

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 f3e7b58

File tree

4 files changed

+7
-101
lines changed

4 files changed

+7
-101
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 & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
// TODO FMT This test should not require std::to_chars(floating-point)
1414
// XFAIL: availability-fp_to_chars-missing
1515

16-
// TODO FMT Investigate Windows issues.
17-
// XFAIL: msvc
18-
1916
// REQUIRES: locale.fr_FR.UTF-8
2017
// REQUIRES: locale.ja_JP.UTF-8
2118

@@ -89,20 +86,9 @@ static void test() {
8986
TEST_EQUAL(stream_c_locale<CharT>(
9087
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}),
9188
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)
10289
TEST_EQUAL(stream_c_locale<CharT>(
10390
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
10491
SV("32767-12-31"));
105-
#endif // defined(_AIX)
10692

10793
TEST_EQUAL(stream_fr_FR_locale<CharT>(
10894
std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}),
@@ -122,19 +108,9 @@ static void test() {
122108
TEST_EQUAL(stream_fr_FR_locale<CharT>(
123109
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}),
124110
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)
134111
TEST_EQUAL(stream_fr_FR_locale<CharT>(
135112
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
136113
SV("32767-12-31"));
137-
#endif // defined(_AIX)
138114

139115
TEST_EQUAL(stream_ja_JP_locale<CharT>(
140116
std::chrono::year_month_day{std::chrono::year{-32'768}, std::chrono::month{1}, std::chrono::day{1}}),
@@ -154,19 +130,9 @@ static void test() {
154130
TEST_EQUAL(stream_ja_JP_locale<CharT>(
155131
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}),
156132
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)
166133
TEST_EQUAL(stream_ja_JP_locale<CharT>(
167134
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}),
168135
SV("32767-12-31"));
169-
#endif // defined(_AIX)
170136
}
171137

172138
int main(int, char**) {

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

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
// TODO FMT This test should not require std::to_chars(floating-point)
1414
// XFAIL: availability-fp_to_chars-missing
1515

16-
// TODO FMT Investigate Windows issues.
17-
// XFAIL: msvc
18-
1916
// REQUIRES: locale.fr_FR.UTF-8
2017
// REQUIRES: locale.ja_JP.UTF-8
2118

@@ -81,20 +78,9 @@ static void test() {
8178
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
8279
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
8380
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)
9481
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_days{
9582
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
9683
SV("32767-12-31"));
97-
#endif // defined(_AIX)
9884

9985
// multiples of days are considered days.
10086
TEST_EQUAL(stream_c_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),
@@ -112,19 +98,9 @@ static void test() {
11298
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
11399
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
114100
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)
124101
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_days{
125102
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
126103
SV("32767-12-31"));
127-
#endif // defined(_AIX)
128104

129105
// multiples of days are considered days.
130106
TEST_EQUAL(stream_fr_FR_locale<CharT>(std::chrono::sys_time<std::chrono::weeks>{std::chrono::weeks{3}}),
@@ -142,19 +118,9 @@ static void test() {
142118
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
143119
std::chrono::year_month_day{std::chrono::year{2000}, std::chrono::month{2}, std::chrono::day{29}}}),
144120
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)
154121
TEST_EQUAL(stream_ja_JP_locale<CharT>(std::chrono::sys_days{
155122
std::chrono::year_month_day{std::chrono::year{32'767}, std::chrono::month{12}, std::chrono::day{31}}}),
156123
SV("32767-12-31"));
157-
#endif // defined(_AIX)
158124

159125
// multiples of days are considered days.
160126
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)