public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* 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).