参看C++20std:chrono
,作为“日期和时间代码”的一组组成部分。 在避免与时间、时间区和日历有关的大多数骗局的同时,你实际上无法轻易摆脱这些基本组成部分。
For example here is a function that is only a couple of dozen lines long that allows you do to exactly what you want, including getting everything on your wish list. Line-by-line explanation follows the code:
#include <chrono>
#include <sstream>
#include <stdexcept>
namespace my
{
std::chrono::system_clock::time_point
datetime(std::string const& s)
{
std::istringstream in{s};
std::chrono::year y;
std::chrono::month_day md;
if (in.peek() == X )
{
in >> std::chrono::parse("XXXX-%m-%d", md);
if (in.fail())
throw std::runtime_error(
"Unable to parse a date of the form XXXX-mm-dd out of "" + s + " );
y = std::chrono::year_month_day{
std::chrono::floor<std::chrono::days>(
std::chrono::system_clock::now())}.year();
}
else
{
in >> std::chrono::parse("%Y-", y) >> std::chrono::parse("%m-%d", md);
if (in.fail())
throw std::runtime_error(
"Unable to parse a date of the form yyyy-mm-dd out of "" + s + " );
}
auto date = y/md;
if (!date.ok())
throw std::runtime_error("Parsed invalid date out of "" + s + " );
return std::chrono::sys_days{date};
}
} // namespace my
第一件事是,看看一下插图是否为<代码>。 iii 这一点很容易地通过表面特征的推测来实现。 如果是<代码>X,则该代码必须是XXXX-d
,否则该编码必须是yyyy-mm-d
,否则就是一种错误,我们用一个附有详细错误信息的例外来表示。
如果舱面像样是XXXX-mm-d
,则打上chrono: 月_day
,其格式为XXXX-%m-%d>
。 如果存在任何平级差错,或者如果按字母顺序排列的<代码>月_日代码>。 不可能有效,教区将失败。
如果该教区失败,就会发出一个有帮助的错误信息。
如果区系成功,则计算本年度(UTC),并将之分配到<代码>y。 如果希望达到当地年,或希望达到亚纳联盟任何时间区的年,这只是一条两条不同的法典。
否则,舱面必须采用<代码>yyyy-mm-d。 Parse into a chrono:year
and a chrono:个月的_day
separate.
如果任何教区都失败,则会发出一个有帮助的错误信息。
最后,将<条码>年代码>和<条码>月_日代码>合并成<条码>年_月_日日>(本标准代码中的“<条码>)。
<代码>年代码>有效,<代码>月_日代码>有效,但两者的结合无效。 这将在2月29日这一非一年的时间里赶上。 如果发现的话,就会发出一个有帮助的错误信息。
更改<代码> 日期:至system_clock:time_point
,先改为sys_days
,然后让默示转换精确到system_clock:time_point
。
这样做可以:
#include <iostream>
int
main()
{
auto xmas = my::datetime("2023-12-25");
std::cout << xmas <<
;
xmas = {};
xmas = my::datetime("XXXX-12-25");
std::cout << xmas <<
;
try
{
xmas = my::datetime("XXXX-25-12");
}
catch (std::exception const& e)
{
std::cout << e.what() <<
;
}
}
哪些产出:
2023-12-25 00:00:00.000000
2023-12-25 00:00:00.000000
Unable to parse a date of the form XXXX-mm-dd out of "XXXX-25-12"
请注意,我们的法典发现了正确的辛迪加错误,但月25日无效。
还指出,如果需要,可以通过更多的检查和分行来支持其他日期格式。