Skip to content

<xloctime>: time_get::do_get uses the wrong format for %c and %x #6129

@cpplearner

Description

@cpplearner

Describe the bug

MSVC STL's time_get::do_get hardcodes %c as equivalent to %b %d %H : %M : %S %Y, and %x as equivalent to %d / %m / %y.

STL/stl/inc/xloctime

Lines 455 to 457 in 117ca96

case 'c':
_First = _Getfmt(_First, _Last, _Iosbase, _State, _Pt, "%b %d %H : %M : %S %Y");
break;

STL/stl/inc/xloctime

Lines 549 to 551 in 117ca96

case 'x':
_First = _Getfmt(_First, _Last, _Iosbase, _State, _Pt, "%d / %m / %y");
break;

This doesn't match what strftime produces:

  • In the "C" locale, %c is equivalent to %a %b %e %T %Y, and %x is equivalent to %m/%d/%y. MSVC notably doesn't parse %a for the former, and has the wrong order for the latter.
  • Other locales might have very different formats.

Fixing this would be a behavior change (even if ABI-preserving). I don't know if it's worth the trouble.

This affects libcxx test std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_one.pass.cpp.

Command-line test case

D:\test>type test-time-get-do-get.cpp
#include <cassert>
#include <ctime>
#include <iostream>
#include <locale>

using I = const char*;

class my_facet : public std::time_get<char, I>
{
public:
    explicit my_facet(std::size_t refs = 0)
        : time_get(refs) {}
};

int main() {
    const my_facet f(1);
    std::ios str(nullptr);
    std::ios_base::iostate err;
    std::tm t;

    {
        const char in[] = "Thu Jun  6 09:49:10 2009";
        err = std::ios_base::goodbit;
        t = std::tm();
        I i = f.get(I(in), I(in+sizeof(in)-1), str, err, &t, 'c');
        assert(i == in+sizeof(in)-1);
    }
}
D:\test>cl /EHsc test-time-get-do-get.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.50.35725 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

test-time-get-do-get.cpp
Microsoft (R) Incremental Linker Version 14.50.35725.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test-time-get-do-get.exe
test-time-get-do-get.obj
D:\test>test-time-get-do-get.exe
Assertion failed: i == in+sizeof(in)-1, file test-time-get-do-get.cpp, line 26

Expected behavior

Assertion passed.

STL version

117ca96

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions