【问题标题】:Parse date string to remove hours, minutes and seconds from timestamp解析日期字符串以从时间戳中删除小时、分钟和秒
【发布时间】:2017-10-19 09:56:27
【问题描述】:

假设我从 Web 服务器接收到一个要解析的字符串。此字符串包含格式为YYYY-MM-DD 的日期。 我想要的是将它转换为代表当天开始的时间戳,因此我不想要秒、分钟和小时。

作为一个虚拟示例,我试图提取当天的时间戳,一旦转换为YYYY-MM-DD 格式。代码如下:

#include <chrono>                                                                                                                                                                                                                                                              
#include <iomanip>                                                                                                                                                                                                                                                             
#include <iostream>                                                                                                                                                                                                                                                            
#include <sstream>
int main()
{
    // Current time at GMT
    std::time_t now = std::time(0);
    std::tm *now_tm = std::gmtime(&now);
    std::ostringstream oss;
    // Extract yyyy-mm-dd = %F
    oss << std::put_time(now_tm, "%F");
    // Use oss to get a date without seconds from
    // current time at gmt
    std::tm tm;
    std::istringstream ss(oss.str());
    ss >> std::get_time(&tm, "%F");
    std::time_t current_date = std::mktime(&tm);
    std::cout << oss.str() << std::endl;
    std::cout << "cd: " << current_date << std::endl;
    return 0;
}

输出是:

2017-10-19
cd: 1908337984324104

提取的时间戳显然是错误的。使用%F格式解析2017-10-19字符串的问题在哪里?

【问题讨论】:

    标签: c++ date chrono


    【解决方案1】:

    您可以使用Howard Hinnant's, free, open-source, header-only chrono-extension library 在不离开chrono 类型系统的安全性的情况下执行此操作。

    #include "date/date.h"
    #include <iostream>
    
    int
    main()
    {
        std::istringstream ss{"2017-10-19"};
        date::sys_seconds tp;
        ss >> date::parse("%F", tp);
        std::cout << date::format("%F\n", tp);
        using date::operator<<;
        std::cout << "cd: " << tp.time_since_epoch() << '\n';
    }
    

    date::sys_seconds 是一个std::chrono::time_point,在Unix Time 中计数chrono::seconds。您可以使用%F 直接解析到它。您还可以使用相同的格式字符串 (%F) 对其进行格式化,并检查 chrono::seconds 的基础计数。该程序输出:

    2017-10-19
    cd: 1508371200s
    

    【讨论】:

    • 太好了。谢谢你的建议。保持我的赞成票
    【解决方案2】:

    documentation of std::get_time 未列出转换说明符 %F。在检查流标志时(你总是应该这样做!),它还会告诉转换失败,至少在我的编译器中是这样。

    因此,通过将其替换为 %Y-%m-%d,转换成功。最后,您默认构造了 tm 变量而不将其归零(例如,通过值初始化)。修复此问题时,代码也按预期工作:

    #include <chrono>                                                                                                                                                                                                                                                              
    #include <iomanip>                                                                                                                                                                                                                                                             
    #include <iostream>                                                                                                                                                                                                                                                            
    #include <sstream>
    int main()
    {
        // Current time at GMT
        std::time_t now = std::time(0);
        std::tm *now_tm = std::gmtime(&now);
        std::ostringstream oss;
        // Extract yyyy-mm-dd = %F
        oss << std::put_time(now_tm, "%Y-%m-%d");
        // Use oss to get a date without seconds from
        // current time at gmt
        std::tm tm{ }; // value-initialize!
        std::istringstream ss(oss.str());
        ss >> std::get_time(&tm, "%Y-%m-%d");
        if(!ss) std::cout << "conversion error\n";
        else {
            std::time_t current_date = std::mktime(&tm);
            std::cout << current_date << '\n';
            std::cout << "cd: " << current_date << '\n';
        }
        return 0;
    }
    

    http://coliru.stacked-crooked.com/a/d86aa1e1d890a14d

    【讨论】:

    • 非常感谢!我正在查看另一个时间格式化函数的文档,猜测它会是一样的。我错了。
    猜你喜欢
    • 1970-01-01
    • 2017-06-10
    • 2013-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多