localtime_s和strftime用法构建ISO时间字符串
localtime_s and strftime usage building ISO time string
我编写了以下函数,该函数接收时间点并返回以毫秒为单位的ISO字符串:
std::string TimePointToISOString(const std::chrono::time_point<std::chrono::system_clock>& time)
{
std::time_t rawTime = std::chrono::system_clock::to_time_t(time);
struct tm timeinfo;
localtime_s(&timeinfo, &rawTime);
std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(time.time_since_epoch());
std::size_t frac_seconds = ms.count() % 1000;
char buffer[32];
std::strftime(buffer, 32, "%FT%TZ", &timeinfo);
std::string bufferStr(buffer);
std::stringstream ss;
ss << bufferStr.substr(0, 19) << "." << std::setw(3) << std::setfill ('0') << frac_seconds << bufferStr.substr(20);
return ss.str();
}
我曾经用localtime()
函数在Linux上运行过,没有任何问题。现在我正在迁移到Windows/VS2012,编译器建议立即将localtime()
更改为更安全的localtime_s()
。
转换后,strftime
调用在运行时确实崩溃,并出现以下错误:
Expression: ("Invalid format directive", 0)
编译运行良好。非常感谢帮助了解这里发生了什么。我想一些我没有注意到的简单的事情。。。
C99中添加了%F
和%T
转换,VS 2012仅支持C89。
尽管它仍然没有尝试支持所有C99,但我相信VS 2015添加了足够多的功能(尤其是C99库函数,它们也是C++11的一部分),这应该可以很好地使用它。
如果您需要继续使用旧的编译器/库,%F和%T基本上都是C89中已经支持的一些格式的"快捷键"。如果我正确阅读了需求,那么以下内容应该是等效的:
std::strftime(buffer, 32, "%Y-%m-%dT%H:%M:%SZ", &timeinfo);
顺便说一句,如果编译器支持C++11,那么使用std::put_time
而不是strftime
通常会更容易、更干净。
这是一个很好的问题(投票支持)。Jerry Coffin的回答是一个很好的答案(也获得了支持)。这个答案是关于添加关于替代开源解决方案的进一步信息,该解决方案已知可用于VS-2013及更高版本、gcc和clang。此备选方案将向TimePointToISOString
产生相同的输出。为了区分它,我给它起了另一个名字:to_local_string
:
std::string
to_local_string(const std::chrono::system_clock::time_point& time)
{
using namespace date;
auto zone = current_zone();
auto local = floor<std::chrono::milliseconds>(zone->to_local(time).first);
auto dp = floor<days>(local);
year_month_day ymd = dp;
std::stringstream ss;
ss << ymd << 'T' << make_time(local-dp);
return ss.str();
}
这使用了这里的时区数据库解析器:
https://github.com/HowardHinnant/date
并记录在这里:
http://howardhinnant.github.io/tz.html
这是IANA时区数据库的解析器,在这里只用于查找本地时区的UTC偏移量。一旦找到本地时间点(存储为std::chrono::system_clock::time_point
),就会使用该库将其分解为字段类型年/月/天/小时/分钟/秒/毫秒,该库的实现位于同一github站点。
我只是在同一时间点运行了TimePointToISOString
和to_local_string
,结果是:
2016-03-23T22:54:52.626
2016-03-23T22:54:52.626
- C++为构建时间获取QDateTime的可靠方法
- 无法在 CLion 中构建 C++ 项目
- 函数向量_指针有不同的原型,我可以构建一个吗
- 如何使用ndk-build.cmd构建Android.so文件
- libssh 的函数在构建 libssh 时无法在 Qt 和 cmake 错误中找到
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- VSCode-有一个红色下划线,但程序构建和运行正确,并且出现配音错误
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 无法使用Qt Creator在Windows中构建yaml-cpp
- 构建一个由C和C++文件组成的库
- llvm构建器向基本块添加终止符
- FLTK 2.0构建和演示,适用于VS2019的2011年左右的代码库
- 如何跨平台将二进制资源构建到程序中?
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- 如何解决 Ninja c++ 构建和执行问题
- 使用 cmake 的 LLVM 构建在 tsan_libdispatch_mac.cc 期间失败; "Error: conflicting types for ..."
- CMake WxWidgets项目成功地在Linux上构建,但没有在Windows上构建
- 更改命令行 qt5 源代码构建配置的正确/快速方法
- localtime_s和strftime用法构建ISO时间字符串
- 在进行安装时,构建应用程序获取 ISO c 不允许命名可变