* std::get_time changed
@ 2022-03-07 7:44 Markus Rathgeb
2022-03-07 11:51 ` Jonathan Wakely
0 siblings, 1 reply; 2+ messages in thread
From: Markus Rathgeb @ 2022-03-07 7:44 UTC (permalink / raw)
To: libstdc++
Hello,
I realized a changed behavior of the function "std::get_time" with respect
to tm_wday and tm_yday.
In older versions tm_wday and tm_yday has not been modified. In more recent
version it is modified and set to the correct value (similar to strptime).
IMHO the "new" behavior is more consistent but I wonder what is "correct"
or expected.
Having a look at https://en.cppreference.com/w/cpp/io/manip/get_time the
fields tm_wday and tm_ydas are set by only a few conversion specifiers.
Can you give me some details about the changed behavior and where it is
documented.
== Versions used ==
Fedora 36
rpm -qi glibc
Name : glibc
Version : 2.35
Release : 3.fc36
rpm -qi gcc-c++
Name : gcc-c++
Version : 12.0.1
Release : 0.9.fc36
Ubuntu Focal
apt info libc6
Package: libc6
Version: 2.31-0ubuntu9
apt info g++
Package: g++
Version: 4:9.3.0-1ubuntu2
== Code Exmaple output for Ubuntu Focal and Fedora 36 ==
Initialize struct tm with 0x00
Ubuntu Focal - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 0, yday: 0, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
Ubuntu Focal - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
Fedora 36 - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
Fedora 36 - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
Initialize struct tm with 0x01
Ubuntu Focal - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 16843009, yday: 16843009, isdst: 16843009, tm_gmtoff:
72340172838076673, skipped: tm_zone
Ubuntu Focal - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: 16843009, tm_gmtoff:
72340172838076673, skipped: tm_zone
Fedora 36 - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: 16843009, tm_gmtoff:
72340172838076673, skipped: tm_zone
Fedora 36 - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: 16843009, tm_gmtoff:
72340172838076673, skipped: tm_zone
Initialize struct tm with 0xFF
Ubuntu Focal - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: -1, yday: -1, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
Ubuntu Focal - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
Fedora 36 - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
Fedora 36 - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
year: 121, wday: 3, yday: 166, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
== Code Example ==
#include <iostream>
#include <cstring>
#include <ctime>
#include <iomanip>
#include <list>
#include <sstream>
#include <string>
namespace {
constexpr const char *k_defaultTimeFormat = "%Y-%m-%d %H:%M:%S";
bool parseGetTime(std::tm *tm, std::string time, std::string format) {
std::istringstream iss(time);
iss >> std::get_time(tm, format.c_str());
return !iss.fail();
}
bool parseStrptime(std::tm *tm, const char *time, const char *format) {
const char *rv = strptime(time, format, tm);
if (rv == nullptr) {
return false;
}
return *rv == '\0';
}
void printTm(const std::tm &tm) {
std::printf("sec: %d, min: %d, hour: %d, mday: %d, mon: %d, year:
%d, wday: %d, yday: %d, isdst: %d, tm_gmtoff: %ld, skipped: tm_zone\n",
tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mday,
tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday, tm.tm_isdst, tm.tm_gmtoff
/*, tm.tm_zone*/);
}
}// namespace
int main() {
struct tm tm;
constexpr const char *timestr = "2021-06-16 07:24:58";
for (const int r: std::list<int>{0x00, 0x01, 0xFF}) {
std::memset(&tm, r, sizeof(tm));
if (parseGetTime(&tm, timestr, k_defaultTimeFormat)) {
printTm(tm);
} else {
std::cerr << "parsing failure: get time" << std::endl;
}
std::memset(&tm, r, sizeof(tm));
if (parseStrptime(&tm, timestr, k_defaultTimeFormat)) {
printTm(tm);
} else {
std::cerr << "parsing failure: strptime" << std::endl;
}
}
return 0;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: std::get_time changed
2022-03-07 7:44 std::get_time changed Markus Rathgeb
@ 2022-03-07 11:51 ` Jonathan Wakely
0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Wakely @ 2022-03-07 11:51 UTC (permalink / raw)
To: Markus Rathgeb; +Cc: libstdc++
On Mon, 7 Mar 2022 at 07:45, Markus Rathgeb via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
>
> Hello,
> I realized a changed behavior of the function "std::get_time" with respect
> to tm_wday and tm_yday.
> In older versions tm_wday and tm_yday has not been modified. In more recent
> version it is modified and set to the correct value (similar to strptime).
> IMHO the "new" behavior is more consistent but I wonder what is "correct"
> or expected.
>
> Having a look at https://en.cppreference.com/w/cpp/io/manip/get_time the
> fields tm_wday and tm_ydas are set by only a few conversion specifiers.
> Can you give me some details about the changed behavior and where it is
> documented.
This changed with https://gcc.gnu.org/r12-6410 in order to fix
https://gcc.gnu.org/PR77760 and make std::time_get act more like
strptime.
>
> == Versions used ==
>
> Fedora 36
> rpm -qi glibc
> Name : glibc
> Version : 2.35
> Release : 3.fc36
> rpm -qi gcc-c++
> Name : gcc-c++
> Version : 12.0.1
> Release : 0.9.fc36
>
> Ubuntu Focal
> apt info libc6
> Package: libc6
> Version: 2.31-0ubuntu9
> apt info g++
> Package: g++
> Version: 4:9.3.0-1ubuntu2
>
> == Code Exmaple output for Ubuntu Focal and Fedora 36 ==
>
> Initialize struct tm with 0x00
> Ubuntu Focal - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 0, yday: 0, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
> Ubuntu Focal - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
> Fedora 36 - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
> Fedora 36 - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: 0, tm_gmtoff: 0, skipped: tm_zone
>
>
> Initialize struct tm with 0x01
> Ubuntu Focal - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 16843009, yday: 16843009, isdst: 16843009, tm_gmtoff:
> 72340172838076673, skipped: tm_zone
> Ubuntu Focal - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: 16843009, tm_gmtoff:
> 72340172838076673, skipped: tm_zone
> Fedora 36 - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: 16843009, tm_gmtoff:
> 72340172838076673, skipped: tm_zone
> Fedora 36 - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: 16843009, tm_gmtoff:
> 72340172838076673, skipped: tm_zone
>
> Initialize struct tm with 0xFF
> Ubuntu Focal - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: -1, yday: -1, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
> Ubuntu Focal - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
> Fedora 36 - std::get_time | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
> Fedora 36 - strptime | sec: 58, min: 24, hour: 7, mday: 16, mon: 5,
> year: 121, wday: 3, yday: 166, isdst: -1, tm_gmtoff: -1, skipped: tm_zone
>
>
> == Code Example ==
>
> #include <iostream>
>
> #include <cstring>
> #include <ctime>
> #include <iomanip>
> #include <list>
> #include <sstream>
> #include <string>
>
> namespace {
> constexpr const char *k_defaultTimeFormat = "%Y-%m-%d %H:%M:%S";
>
> bool parseGetTime(std::tm *tm, std::string time, std::string format) {
> std::istringstream iss(time);
> iss >> std::get_time(tm, format.c_str());
> return !iss.fail();
> }
>
> bool parseStrptime(std::tm *tm, const char *time, const char *format) {
> const char *rv = strptime(time, format, tm);
> if (rv == nullptr) {
> return false;
> }
> return *rv == '\0';
> }
>
> void printTm(const std::tm &tm) {
> std::printf("sec: %d, min: %d, hour: %d, mday: %d, mon: %d, year:
> %d, wday: %d, yday: %d, isdst: %d, tm_gmtoff: %ld, skipped: tm_zone\n",
> tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mday,
> tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday, tm.tm_isdst, tm.tm_gmtoff
> /*, tm.tm_zone*/);
> }
> }// namespace
>
> int main() {
> struct tm tm;
> constexpr const char *timestr = "2021-06-16 07:24:58";
>
> for (const int r: std::list<int>{0x00, 0x01, 0xFF}) {
> std::memset(&tm, r, sizeof(tm));
> if (parseGetTime(&tm, timestr, k_defaultTimeFormat)) {
> printTm(tm);
> } else {
> std::cerr << "parsing failure: get time" << std::endl;
> }
> std::memset(&tm, r, sizeof(tm));
> if (parseStrptime(&tm, timestr, k_defaultTimeFormat)) {
> printTm(tm);
> } else {
> std::cerr << "parsing failure: strptime" << std::endl;
> }
> }
> return 0;
> }
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-03-07 11:51 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-07 7:44 std::get_time changed Markus Rathgeb
2022-03-07 11:51 ` Jonathan Wakely
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).