如何在 C++ 中解析 8 位日期?

How to parse 8-digit date in C++?

我使用 std::get_time 从文本中解析日期。在大多数情况下这就足够了,但是当读取没有分隔符的日期时(例如 31122021,格式为 "%d%m%Y"),我总是会失败。我使用它是因为我看到它被描述为等同于 python 的 strptime () which does manage this use case ().

这是我的代码(经过 MRE 测试):

#include <cassert>
#include <ctime>
#include <iomanip>
#include <sstream>

#define MAKEDATE(d,m,y) (((y&0xFFFF)<<16)|((m&0xFF)<<8)|(d&0xFF))
uint32_t Get_Date(const char *str_date, const char **out, const char *format)
{
    std::tm dt = {};
    std::istringstream stream(str_date);
    stream >> std::get_time(&dt, format);
    if (stream.fail())
    {
        if (out) *out = NULL;
        return MAKEDATE(1, 1, 1900);
    }
    else
    {
        if (out) *out = str_date + (int)stream.tellg();
        return MAKEDATE(dt.tm_mday, 1 + dt.tm_mon, 1900 + dt.tm_year);
    }
}

int main(void)
{
    assert(Get_Date("31122021", NULL, "%d%m%Y") == MAKEDATE(31, 12, 2021));
}

我使用 MSVC 19.10.25027 使用 VS2017 的默认编译器设置使用 MFC 和 CLI 编译它。

我弄错了吗?我可以使用另一个标志或一组标志吗?还有其他简单的解析方法吗?

这是一个特定于编译器的问题。如果这个特定的方法需要处理这个特定的输入,那么你必须使用不同的编译器。

引用此 link ;

It appears that std::get_time in MSVC 14.0 does not parse undelimited date and time values, such as those found in the ISO-8601 basic format. The following code fails with MSVC, but works properly with GCC 5.2. <code example>

Seems that it is known: <defunct, very old link>

可以得出结论,MSVC 编译的 std::get_time 从未能够解析非分隔输入。据报道,GCC 可以工作,而 CLang 肯定可以,所以 MSVC 是一个奇怪的人。

如果切换编译器不值得麻烦,更具体的解析方法就可以了。

// Assuming str_date is guaranteed to be 8 digits
uint32_t Get_Date_YMD(const char *str_date)
{
    return
        (((str_date[0] - '0') * 1000 +
        (  str_date[1] - '0') * 100 +
        (  str_date[2] - '0') * 10 +
        (  str_date[3] - '0')) << 16) |
        (((str_date[4] - '0') * 10 +
        (  str_date[5] - '0')) << 8) |
        (( str_date[6] - '0') * 10 +
        (  str_date[7] - '0'));
}