【问题标题】:get_time parsing error for two digits year两位数年份的 get_time 解析错误
【发布时间】:2022-01-12 04:28:15
【问题描述】:

当格​​式包含“%y”或“%Y”时,std::get_time 的行为方式相同,在这两种情况下,它都会尝试读取四位数的年份。我做错了什么还是一个错误?

示例代码:

#include <iostream>
#include <iomanip>

void testDate(const char *format,const char *date)
{
    std::istringstream ds(date);

    std::tm tm = {};
    ds >> std::get_time(&tm,format);
    std::cout<<date<<" parsed using "<<format<<" -> Year: "<<tm.tm_year+1900<<" Month: "<<tm.tm_mon<<" Day: "<<tm.tm_mday<<std::endl;
}

int main()
{
    testDate("%y%m%d","101112");
    testDate("%Y%m%d","101112");
    testDate("%y%m%d","20101112");
    testDate("%Y%m%d","20101112");
    
    
    return 0;
}

输出:

101112 parsed using %y%m%d -> Year: 1011 Month: 11 Day: 0
101112 parsed using %Y%m%d -> Year: 1011 Month: 11 Day: 0
20101112 parsed using %y%m%d -> Year: 2010 Month: 10 Day: 12
20101112 parsed using %Y%m%d -> Year: 2010 Month: 10 Day: 12

测试:

g++ (SUSE Linux) 11.2.1 20210816 [修订版 056e324ce46a7924b5cf10f61010cf9dd2ca10e9]

clang++ 版本 12.0.1

【问题讨论】:

  • 非常有趣的问题。我不知道这是否可能,但您可以尝试创建自己的自定义locale 并覆盖get_time 方面并将其灌输到流中以检查是否正在调用get,或者是否调用get_year ,它不知道前瞻。如果是,那么它肯定似乎偏离了规范。如果您依赖于此,最好使用自己的字符串解析甚至正则表达式。
  • 我实际上依赖于这个,但我有一个解决方法。我将来会需要它,所以找出发生了什么会很棒。我认为这是错误,但我不想和每个人一起检查。我试图查看源代码,但我很难在 gcc 树中找到“实际”实现。
  • 是的,我可以想象这是一个相当大的兔子洞的潜水。如果是我,我会推出自己的解决方法,根本不依赖它。如果不是错误,那绝对是一个怪癖。通过在格式中添加任何非数字字符,它当然可以工作。看起来year 正在被一种贪心算法解析,这向我表明标准库可能会调用get_year 作为后备。也许该代码中某处有// TODO 注释;)

标签: c++ gcc clang libstdc++


【解决方案1】:

测试后发现

  • %y - 只输入两位数
  • %Y - 只输入四位数字

如果在使用%y时使用4位,则直接输出4位,如果是2位,则与文档一致

月份

月份,来自std::tm

tm_mon : months since January – [0, 11]

所以它打印出 11 代表 12 月。您可以使用下面的代码打印出日期。

    std::cout << std::put_time(&tm, "%c") << std::endl;

【讨论】:

  • 你错过了阅读问题和测试场景。最后一个输出是正确的,(唯一一个似乎与文档没有区别的输出)。月份应该是 10,因为在每个输入中月份都是 11 月。
  • 我发现gcc在运行上面代码的时候报错,可以用clang运行。 gcc源代码好像没问题。
猜你喜欢
  • 1970-01-01
  • 2015-07-28
  • 2016-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
  • 1970-01-01
相关资源
最近更新 更多