如何判断我的 struct tm 是否处于无效状态?

How Can I Tell if My struct tm Has Been Left in an Invalid State?

这是一个关于无效输入的问题,不是无效格式。例如给定以下代码:

tm bar;

foo >> get_time(&bar, "%Y-%m-%d");

cout >> bar.tm_year >> bar.tm_mon >> bar.tm_mday >> endl;

如果我定义这样就没问题:stringstream foo("2001-02-28 non-leap year"); 如果我的格式无效,则会出现明显的错误,例如:stringstream foo("bad format 2001-02-28 non-leap year");

但我不知道如何检测我的输入是否无效,例如:

stringstream foo("2001-02-30 non-leap year");

在这种情况下 bar 可以读起来好像没有任何问题。有什么我可以听的东西会提醒我输入无效吗?

由于 mktime 也尝试解释超出范围的值(即 2001-02-30 将被解释为 2001-03-01),您可以执行 mktime 之后通过 localtime,如果您返回不同的值,则表示原始值无效。

Matteo Italia's answer, apart from writing your own Gregorian validator, your only reliable double check is mktime 所述。使用 get_time 获得的 tms 无法验证,因为可能会填写也可能不会填写字段。考虑以下 2 个无效示例:

这样做:istringstream("2001-02-30") >> get_time(&bar, "%Y-%m-%d"); 导致 改变 运行 彻底 mktime:

bar.tm_mday : 30
bar.tm_mon : 1
bar.tm_year : 100

执行此操作时:istringstream("2001-13-30") >> get_time(&bar, "%Y-%m-%d"); 导致 在 运行 到 mktime 不会改变的结果:

bar.tm_mday : 13
bar.tm_mon : 0
bar.tm_year : 100

为了让 mktime 更改所有无效日期,我们需要在不使用 get_time 的情况下读取日期:

int year;
int month;
int day;
istringstream foo("2000-13-30");

foo >> year >> ws;
foo.ignore();
foo >> month >> ws;
foo.ignore();
foo >> day;

tm bar = { 0, 0, 0, day, month - 1, year - 1900 };

此时 bar 中的任何错误都可以由 mktime 纠正,因此我们的实际验证步骤将是检查非 time_t(-1) return 并进行比较修改后的 bar 返回 到原始值: if(time_t(-1) != mktime(&bar) && bar.tm_mday == day && bar.tm_mon == month - 1 && bar.tm_year == year - 1900) 如果此条件为真,则 bar 的输入有效。

总而言之,可以在不编写公历验证程序的情况下验证 tm,但是不可能验证具有以下特征的 tm get_time.

阅读了