如何在 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'));
}
我使用 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'));
}