@@ -2939,8 +2939,9 @@ namespace __detail
__is.setstate(ios_base::failbit);
else
{
- auto __st = __p._M_sys_days + __p._M_time - *__offset;
- auto __tt = tai_clock::from_utc(utc_clock::from_sys(__st));
+ constexpr sys_days __epoch(-days(4383)); // 1958y/1/1
+ auto __d = __p._M_sys_days - __epoch + __p._M_time - *__offset;
+ tai_time<common_type_t<_Duration, seconds>> __tt(__d);
__tp = chrono::time_point_cast<_Duration>(__tt);
}
}
@@ -2977,9 +2978,10 @@ namespace __detail
__is.setstate(ios_base::failbit);
else
{
- auto __st = __p._M_sys_days + __p._M_time - *__offset;
- auto __tt = gps_clock::from_utc(utc_clock::from_sys(__st));
- __tp = chrono::time_point_cast<_Duration>(__tt);
+ constexpr sys_days __epoch(days(3657)); // 1980y/1/Sunday[1]
+ auto __d = __p._M_sys_days - __epoch + __p._M_time - *__offset;
+ gps_time<common_type_t<_Duration, seconds>> __gt(__d);
+ __tp = chrono::time_point_cast<_Duration>(__gt);
}
}
return __is;
@@ -32,6 +32,14 @@ test_format()
auto ft = clock_cast<file_clock>(sys_days(2024y/January/21)) + 0ms + 2.5s;
s = std::format("{}", ft);
VERIFY( s == "2024-01-21 00:00:02.500");
+
+ const std::chrono::file_time<std::chrono::seconds> t0{};
+ s = std::format("{:%Z %z %Ez %Oz}", t0);
+ VERIFY( s == "UTC +0000 +00:00 +00:00" );
+
+ s = std::format("{}", t0);
+ // chrono::file_clock epoch is unspecified, so this is libstdc++-specific.
+ VERIFY( s == "2174-01-01 00:00:00" );
}
void
@@ -49,6 +57,21 @@ test_parse()
VERIFY( tp == clock_cast<file_clock>(expected) );
VERIFY( abbrev == "BST" );
VERIFY( offset == 60min );
+
+ // Test round trip
+ std::stringstream ss;
+ ss << clock_cast<file_clock>(expected) << " 0123456";
+ VERIFY( ss >> parse("%F %T %z%Z", tp, abbrev, offset) );
+ VERIFY( ss.eof() );
+ VERIFY( (tp + offset) == clock_cast<file_clock>(expected) );
+ VERIFY( abbrev == "456" );
+ VERIFY( offset == (1h + 23min) );
+
+ ss.str("");
+ ss.clear();
+ ss << file_time<seconds>{};
+ VERIFY( ss >> parse("%F %T", tp) );
+ VERIFY( tp.time_since_epoch() == 0s );
}
int main()
@@ -42,13 +42,19 @@ test_format()
// PR libstdc++/113500
s = std::format("{}", gt + 150ms + 10.5s);
VERIFY( s == "2000-01-01 00:00:23.650" );
+
+ s = std::format("{:%Z %z %Ez %Oz}", gt);
+ VERIFY( s == "GPS +0000 +00:00 +00:00" );
+
+ s = std::format("{}", gps_seconds{});
+ VERIFY( s == "1980-01-06 00:00:00" );
}
void
test_parse()
{
using namespace std::chrono;
- const sys_seconds expected = sys_days(2023y/August/9) + 20h + 44min + 3s;
+ const sys_seconds expected = sys_days(2023y/August/9) + 20h + 43min + 45s;
gps_seconds tp;
minutes offset;
@@ -59,6 +65,20 @@ test_parse()
VERIFY( tp == clock_cast<gps_clock>(expected) );
VERIFY( abbrev == "BST" );
VERIFY( offset == 60min );
+
+ // Test round trip
+ std::stringstream ss;
+ ss << clock_cast<gps_clock>(expected) << " GPS -1234";
+ VERIFY( ss >> parse("%F %T %Z %z", tp, abbrev, offset) );
+ VERIFY( ! ss.eof() );
+ VERIFY( (tp + offset) == clock_cast<gps_clock>(expected) );
+ VERIFY( abbrev == "GPS" );
+ VERIFY( offset == -(12h + 34min) );
+
+ ss.str("");
+ ss << gps_seconds{};
+ VERIFY( ss >> parse("%F %T", tp) );
+ VERIFY( tp.time_since_epoch() == 0s );
}
int main()
@@ -86,6 +86,9 @@ test_format()
s = std::format("{:%Z %T %F %z %Ez}", ltf);
__builtin_puts(s.c_str());
VERIFY( s == "FOO 20:22:02 2024-07-28 -0100 -01:00" );
+
+ s = std::format("{}", local_seconds{});
+ VERIFY( s == "1970-01-01 00:00:00" );
}
void
@@ -103,6 +106,20 @@ test_parse()
VERIFY( tp == local_seconds(expected.time_since_epoch()) );
VERIFY( abbrev == "BST" );
VERIFY( offset == 60min );
+
+ // Test round trip
+ std::stringstream ss;
+ ss << local_seconds{expected.time_since_epoch()} << " X 0123";
+ VERIFY( ss >> parse("%F %T %Z %z", tp, abbrev, offset) );
+ VERIFY( ! ss.eof() );
+ VERIFY( tp == local_seconds{expected.time_since_epoch()} );
+ VERIFY( abbrev == "X" );
+ VERIFY( offset == (1h + 23min) );
+
+ ss.str("");
+ ss << local_seconds{};
+ VERIFY( ss >> parse("%F %T", tp) );
+ VERIFY( tp.time_since_epoch() == 0s );
}
int main()
@@ -21,6 +21,28 @@ test_ostream()
VERIFY( s == "==2000-01-01 00:00:32" );
}
+void
+test_format()
+{
+ using std::format;
+ using namespace std::chrono;
+
+ auto st = sys_days{2000y/January/1};
+ auto tt = clock_cast<tai_clock>(st);
+ auto s = std::format("{}", tt);
+ VERIFY( s == "2000-01-01 00:00:32" );
+
+ // PR libstdc++/113500
+ s = std::format("{}", tt + 150ms);
+ VERIFY( s == "2000-01-01 00:00:32.150" );
+
+ s = std::format("{:%Z %z %Ez %Oz}", tt);
+ VERIFY( s == "TAI +0000 +00:00 +00:00" );
+
+ s = std::format("{}", tai_seconds{});
+ VERIFY( s == "1958-01-01 00:00:00" );
+}
+
void
test_parse()
{
@@ -30,16 +52,31 @@ test_parse()
minutes offset;
std::string abbrev;
- std::istringstream is("8/9/23 214403 +1 BST#");
+ std::istringstream is("8/9/23 214440 +1 BST#");
VERIFY( is >> parse("%D %2H%2M%2S %Oz %Z", tp, abbrev, offset) );
VERIFY( ! is.eof() );
VERIFY( tp == clock_cast<tai_clock>(expected) );
VERIFY( abbrev == "BST" );
VERIFY( offset == 60min );
+
+ // Test round trip
+ std::stringstream ss;
+ ss << clock_cast<tai_clock>(expected) << " TAI 0123";
+ VERIFY( ss >> parse("%F %T %Z %z", tp, abbrev, offset) );
+ VERIFY( ! ss.eof() );
+ VERIFY( (tp + offset) == clock_cast<tai_clock>(expected) );
+ VERIFY( abbrev == "TAI" );
+ VERIFY( offset == (1h + 23min) );
+
+ ss.str("");
+ ss << tai_seconds{};
+ VERIFY( ss >> parse("%F %T", tp) );
+ VERIFY( tp.time_since_epoch() == 0s );
}
int main()
{
test_ostream();
+ test_format();
test_parse();
}
@@ -116,6 +116,13 @@ test_format()
// PR libstdc++/113500
s = std::format("{}", leap + 100ms + 2.5s);
VERIFY( s == "2017-01-01 00:00:01.600");
+
+ std::chrono::utc_seconds t0{};
+ s = std::format("{:%Z %z %Ez %Oz}", t0);
+ VERIFY( s == "UTC +0000 +00:00 +00:00" );
+
+ s = std::format("{}", t0);
+ VERIFY( s == "1970-01-01 00:00:00" );
}
void
@@ -146,6 +153,21 @@ test_parse()
VERIFY( is >> parse("%G-W%V-%u %T", tp) );
VERIFY( ! is.eof() );
VERIFY( tp == clock_cast<utc_clock>(expected) );
+
+ // Test round trip
+ std::stringstream ss;
+ ss << clock_cast<utc_clock>(expected) << " 0012 UTC";
+ VERIFY( ss >> parse("%F %T %z %Z", tp, abbrev, offset) );
+ VERIFY( ss.eof() );
+ VERIFY( (tp + offset) == clock_cast<utc_clock>(expected) );
+ VERIFY( abbrev == "UTC" );
+ VERIFY( offset == 12min );
+
+ ss.str("");
+ ss.clear();
+ ss << utc_seconds{};
+ VERIFY( ss >> parse("%F %T", tp) );
+ VERIFY( tp.time_since_epoch() == 0s );
}
int main()