C++ 如何正确使用localtime()?
在我的一个实用程序中,localtime()用于将unix时间戳转换为人类可读的日期时间 以下代码用于在VS2010中工作,但在VS2019中无法工作:C++ 如何正确使用localtime()?,c++,C++,在我的一个实用程序中,localtime()用于将unix时间戳转换为人类可读的日期时间 以下代码用于在VS2010中工作,但在VS2019中无法工作: std::string sec = "1234123456"; int nsec = atoi(sec.c_str()); tm* t = localtime((time_t*)&nsec); // return null pointer std::string sec = "1234123456"; int nsec = atoi(
std::string sec = "1234123456";
int nsec = atoi(sec.c_str());
tm* t = localtime((time_t*)&nsec); // return null pointer
std::string sec = "1234123456";
int nsec = atoi(sec.c_str());
time_t tt = nsec;
tm* t = localtime(&tt); // works
如果我以以下方式更改代码,它也将在VS2019中工作:
std::string sec = "1234123456";
int nsec = atoi(sec.c_str());
tm* t = localtime((time_t*)&nsec); // return null pointer
std::string sec = "1234123456";
int nsec = atoi(sec.c_str());
time_t tt = nsec;
tm* t = localtime(&tt); // works
我不知道为什么需要额外的int-to-time转换,如果您有任何建议,我将不胜感激。在大多数(如果不是所有)现代编译器上时间现在是64位整数<因此,当您从一种指针类型转换到另一种指针类型时,code>(time_t*)&nsec
是未定义的行为
您的固定版本定义得很好,但您会遇到这样的原因,即time\u t
现在是64位的,因为32位数字只适用于2038年之前的时间(假设time\u t
使用Unix纪元)
<> P>不幸的是,C++没有提供一个简单的方法来转换<代码>字符串 >代码> TimeTyt,要正确地处理它,你需要这样的东西:
#include <iostream>
#include <charconv>
time_t str_to_time_t(const std::string& str)
{
auto begin = str.c_str();
auto end = begin + str.size();
time_t time;
auto result = std::from_chars(begin, end, time);
if (result.ec != std::errc())
{
throw std::system_error(std::make_error_code(result.ec));
}
if (result.ptr != end)
{
throw std::invalid_argument("invalid time_t string");
}
return time;
}
int main()
{
std::string sec = "1234123456";
auto nsec = str_to_time_t(sec);
tm* t = localtime((time_t*)&nsec);
if (t)
{
std::cout << "parsed OK\n";
}
}
#包括
#包括
时间长度到时间长度(常数标准::字符串和长度)
{
自动开始=str.c_str();
自动结束=开始+长度大小();
时间;
自动结果=std::from_chars(开始、结束、时间);
如果(result.ec!=std::errc())
{
抛出std::系统错误(std::生成错误代码(result.ec));
}
如果(result.ptr!=结束)
{
抛出std::无效的参数(“无效的时间字符串”);
}
返回时间;
}
int main()
{
std::string sec=“1234123456”;
自动nsec=str到时间(秒);
tm*t=localtime((time_t*)和nsec);
if(t)
{
std::cout可能time\u t
现在是64位类型,因此使用int
将不起作用。原始代码在不考虑实际类型的情况下使用直接强制转换是危险的。可能是因为time\u t
实际上大于int
,因此第一次强制转换将调用未定义的行为。也就是说,如果time\t
是64位类型,那么在第一个示例中,您(不正确地)告诉C 4字节int
就是其中之一。请注意,由于使用32位时间戳,您的代码在2038年后将失败。您读取了吗?稍后,您可以正确使用它。在Linux系统上读取并启用编译器中的所有警告