将日期时间转换为毫秒 - C++ - 跨平台

4

我想将格式为"20160907-05:00:54.123"的字符串转换成毫秒。 我知道在Windows中没有可用的strptime函数,并且我希望能够在Windows和Linux上运行我的程序。我也不能使用第三方库。 我可以对字符串进行标记化并转换。但是是否有更优雅的方法,例如使用strptime函数来完成这个任务?


1
您是指从哪个时间开始转换为毫秒?您是指 UNIX 纪元时间戳吗? - Hatted Rooster
1
@GillBates 我将会得到一个按照上述格式的字符串。 - Will_Panda
1
是的,但那只是一个日期,如果不知道起始点,你无法将任意日期转换为毫秒。 - Hatted Rooster
2
@Will_Panda 他的意思是你用哪个时代来计算毫秒数。就像“20160907-05:00:54.123距离“20160907-05:00:54.000”有123毫秒。 - Danh
Boost是一个选项吗?http://www.boost.org/doc/libs/1_56_0/doc/html/date_time/date_time_io.html? - Antonio
显示剩余9条评论
3个回答

6
< p >那么std::sscanf怎么样?

#include <iostream>
#include <cstring>

int main() {
    const char *str_time = "20160907-05:00:54.123";
    unsigned int year, month, day, hour, minute, second, miliseconds;

    if (std::sscanf(str_time, "%4u%2u%2u-%2u:%2u:%2u.%3u", &year, &month,
               &day, &hour, &minute, &second,&miliseconds) != 7)
    {
        std::cout << "Parse failed" << std::endl;
    } 
    else
    {
        std::cout << year << month << day << "-" << hour << ":" 
                  << minute << ":" << second << "." << miliseconds
                  << std::endl;
    }
}

输出 (ideone): 201697-5:0:54.123.

然而,您应该确保输入是有效的(例如,日期可以在[0,99]范围内)。


是的,这个方法可行,你说得对,我必须确保输入是有效的。但是我正在寻找更加优雅的解决方案,而不是逐个拆分每个元素。谢谢。 - Will_Panda

4

很遗憾不能使用第三方库,因为这里有一个(MIT许可证),它只有一个头文件,在Linux和Windows上运行,并且能够无缝处理毫秒级别的时间:

#include "date.h"
#include <iostream>
#include <sstream>

int
main()
{
    date::sys_time<std::chrono::milliseconds> tp;
    std::istringstream in{"20160907-05:00:54.123"};
    date::parse(in, "%Y%m%d-%T", tp);
    std::cout << tp.time_since_epoch().count() << '\n';
}

这会输出:
1473224454123

为您完成错误检查。如果日期无效,流将fail()

date::sys_time<std::chrono::milliseconds>std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>的类型别名。也就是说,它来自于system_clock::time_point家族,只有milliseconds精度。

完全记录在:

https://howardhinnant.github.io/date/date.html

这再也没有比这更优雅的了。


看起来是个不错的选择。但不幸的是我不能使用任何一个。 - Will_Panda

3
鉴于您的字符串格式,以下方式解析相当容易(尽管正则表达式或get_time可能更加优雅):
tm t;
t.tm_year = stoi(s.substr(0, 4));
t.tm_mon = stoi(s.substr(4, 2));
t.tm_mday = stoi(s.substr(6, 2));
t.tm_hour = stoi(s.substr(9, 2));
t.tm_min = stoi(s.substr(12, 2));
t.tm_sec = 0;
double sec = stod(s.substr(15));

可以使用mktime函数来计算自历元以来的时间:

mktime(&t) + sec * 1000

请注意,分数秒需要进行不同的处理 - 不幸的是,tm 只有整数秒。
(在此处查看完整代码。)

编辑

正如Mine和Panagiotis Kanavos在评论中正确指出的那样,Visual C++显然已经支持get_time相当长时间了,并且使用它更为简短(请注意,小数秒需要以相同的方式处理)。


@Will_Panda :-) 我很不幸地同意 - 它并不是最优雅的构造物;更像是丑陋的棕色胶带。 - Ami Tavory
1
除了毫秒部分外,std::get_time(&when, "%Y%m%d-%H:%M:%S"); 看起来更简洁。 - Mine
@Mine 我同意(我在答案中也写了这个);注意这个问题没有标记为c++11。顺便说一句,毫秒是一个固有的问题,因为“tm”似乎没有亚秒字段。 - Ami Tavory
@AmiTavory Visual C++在2010年加入了C++11支持和get_time功能。 - Panagiotis Kanavos
楼主提到了Windows。可能是Visual C++或者gcc。但是有些项目还停留在古老的Borland或Microsoft编译器上(想想1998年)。 - Panagiotis Kanavos
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接