解析日期字符串以从时间戳中删除小时、分钟和秒

Parse date string to remove hours, minutes and seconds from timestamp

本文关键字:小时 删除 分钟 时间戳 日期 字符串      更新时间:2023-10-16

假设我从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字符串的问题在哪里?

通过使用 Howard Hinnant 的免费、开源、仅标题时间扩展库,您可以在不离开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("%Fn", tp);
    using date::operator<<;
    std::cout << "cd: " << tp.time_since_epoch() << 'n';
}

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

2017-10-19
cd: 1508371200s

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 errorn";
    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