C++ hinnant date lib - not parsing string to date under Linux, works on Windows
10:32 09 Jan 2026

If I do:

#include 
#include "./Utils/3rdParty/date/date.h"
#include "./Utils/3rdParty/date/tz.h"

using UtcTime = std::chrono::time_point;

UtcTime xParseRfc822(const char* strTime)
{
    std::string s = (strTime ? std::string(strTime) : std::string());

    if (s.empty())
    {
        return UtcTime();
    }

    // Common timezone abbreviations -> minutes offset (RFC 822/1123 + a few practical ones)
    static const std::unordered_map tz_abbr = {
        {"UT",0},{"UTC",0},{"GMT",0},{"Z",0},
        {"WET",0},{"WEST",60},{"CET",60},{"CEST",120},{"EET",120},{"EEST",180},
        {"MSK",180},{"MSD",240},
        {"AST",-240},{"ADT",-180},{"EST",-300},{"EDT",-240},{"CST",-360},{"CDT",-300},
        {"MST",-420},{"MDT",-360},{"PST",-480},{"PDT",-420},
        {"AKST",-540},{"AKDT",-480},{"HST",-600},{"HDT",-540},
        {"AEST",600},{"AEDT",660},{"ACST",570},{"ACDT",630},{"AWST",480},
        {"IST",330},{"JST",540},{"KST",540},{"CST-PRC",480}
    };

    auto to_upper = [](std::string v) {
        std::transform(v.begin(), v.end(), v.begin(), [](unsigned char c) { return std::toupper(c); });
        return v;
        };

    auto replace_range_with_offset = [&](size_t from, size_t to_exclusive, int mins) {
        char buf[16];
        std::snprintf(buf, sizeof(buf), "%+03d%02d", mins / 60, std::abs(mins % 60));
        s.replace(from, to_exclusive - from, buf);
        };

    // Case 1: trailing "(TZ)" block -> convert to numeric offset
    if (!s.empty() && s.back() == ')')
    {
        size_t lp = s.find_last_of('(');
        if (lp != std::string::npos && lp + 2 < s.size() && s[s.size() - 1] == ')')
        {
            std::string inside = s.substr(lp + 1, s.size() - lp - 2);
            auto it = tz_abbr.find(to_upper(inside));
            if (it != tz_abbr.end())
            {
                // Remove the whole " (TZ)" or "(TZ)" block and append space + offset
                std::string prefix = s.substr(0, lp);
                char buf[8];
                std::snprintf(buf, sizeof(buf), " %+03d%02d", it->second / 60, std::abs(it->second % 60));
                s = prefix + buf;
            }
        }
    }
    else
    {
        // Case 2: trailing token "TZ" -> convert in place without trimming
        const char* ws = " \t\r\n";
        size_t end = s.find_last_not_of(ws);
        if (end != std::string::npos)
        {
            size_t start_ws = s.find_last_of(ws, end);
            size_t tok_start = (start_ws == std::string::npos) ? 0 : start_ws + 1;
            std::string last = s.substr(tok_start, end - tok_start + 1);
            auto it = tz_abbr.find(to_upper(last));
            if (it != tz_abbr.end())
            {
                replace_range_with_offset(tok_start, end + 1, it->second);
            }
        }
    }

    auto try_parse = [&](const char* fmt, chronoExt::sys_time& tp) -> bool {
        std::istringstream is(s);
        is >> date::parse(fmt, tp);
        return !is.fail();
        };

    date::sys_time tp;
    bool parsed = false;

    // RFC 1123 / 2822 variants (numeric offset)
    if (!parsed && try_parse("%a, %d %b %Y %T %z", tp)) parsed = true;
    if (!parsed && try_parse("%a, %e %b %Y %T %z", tp)) parsed = true;
    if (!parsed && try_parse("%d %b %Y %T %z", tp))     parsed = true;

    // RFC 1123 with %Z (works if tzdb is available)
    if (!parsed && try_parse("%a, %d %b %Y %T %Z", tp)) parsed = true;
    if (!parsed && try_parse("%a, %e %b %Y %T %Z", tp)) parsed = true;

    // RFC 850
    if (!parsed && try_parse("%A, %d-%b-%y %T %z", tp)) parsed = true;
    if (!parsed && try_parse("%A, %d-%b-%y %T %Z", tp)) parsed = true;

    // asctime()
    if (!parsed && try_parse("%a %b %e %T %Y", tp))     parsed = true;

    // Fallbacks (no seconds)
    if (!parsed && try_parse("%a, %d %b %Y %R %z", tp)) parsed = true;
    if (!parsed && try_parse("%a, %e %b %Y %R %z", tp)) parsed = true;

    // Date-only / ISO-like fallbacks
    if (!parsed && try_parse("%d %b %Y %z", tp))        parsed = true;
    if (!parsed && try_parse("%F %z", tp))              parsed = true;
    if (!parsed && try_parse("%F", tp))                 parsed = true;

    if (!parsed)
    {
        return UtcTime();
    }

    UtcTime tUtc = std::chrono::time_point_cast(tp);

    return tUtc;    
}

int main(int argc, char** argv) 
{
    auto t = "Thu, 08 Jan 2026 16:08:00 GMT";
    auto utc = xParseRfc822(t);;
    std::cout << ut << std::endl;

    return 0;   
}

It works under Visual Studio 2022 (C++20). However, when I build the same code on Linux with g++ (GCC) 15.1.1 20250521, I got incorrect output.

Windows: 2026-01-08 16:08:00.0000000
Linux: 1970-01-01 00:00:00.000000000
c++ datetime c++20 c++-chrono