【问题标题】:how to convert struct tm to time_t in c++如何在 C++ 中将 struct tm 转换为 time_t
【发布时间】:2018-06-04 22:13:00
【问题描述】:

给定的函数是用于处理日期和时间的类的一部分。我解析的文件需要将给定的字符串数据转换为 time_t 但 mktime 不起作用。为什么?

 struct tm DateTimeUtils::makeTime(string arrTime)//accepts in format"2315"means 11.15 pm
{
    struct tm neww;
    string hour = arrTime.substr(0,2);
    int hour_int = stoi(hour);
    neww.tm_hour=hour_int;//when this is directly printed generates correct value


    string minute = arrTime.substr(2,2);
    int minute_int = stoi(minute);
    neww.tm_min=(minute_int);//when this is directly printed generates correct value

    time_t t1 = mktime(&neww);//only returns -1
    cout<<t1;

    return neww;

}

【问题讨论】:

  • tm 结构中不仅有 tm_min 和 tm_hour。见这里:cplusplus.com/reference/ctime/tm
  • 我通过添加以下代码修改了代码: struct tm DateTimeUtils::makeTime(string arrTime) { struct tm neww;新w.tm_sec=0-61;新w.tm_mday=1-31;新w.tm_mon=0-11;新w.tm_year=1900;新w.tm_wday=0-6;新w.tm_yday=0-365;字符串小时 = arrTime.substr(0,2); int hour_int = stoi(小时); neww.tm_hour=hour_int;字符串分钟 = arrTime.substr(2,2); int minute_int = stoi(分钟); neww.tm_min=(minute_int); time_t t1 = mktime(&neww); cout
  • “我修改了代码...” - 太好了。现在modify your question 在您的更改中包含一个附录。代码墙不属于 cmets;它们属于已发布的问题,理想情况下,它们会被最小化以仅展示与您的问题相关的问题。

标签: c++ mktime time-t


【解决方案1】:

来自mktime(3) man page

time_t ... 表示自 Epoch 1970-01-01 00:00:00 +0000 (UTC) 以来经过的秒数。

那么你就有了struct tm 的字段,尤其是这个:

tm_year

自 1900 年以来的年数。

所以基本上如果 tm_year 设置为 0 并且我们正确地进行了数学运算,我们会得到 70 年的差异,需要以秒为单位表示,这可能太大了。

您可以通过将 struct tm 值初始化为 Epoch 并将其用作基本参考来解决此问题:

 struct tm DateTimeUtils::makeTime(string arrTime)//accepts in format"2315"means 11.15 pm
{
    time_t tmp = { 0 };
    struct tm neww = *localtime(&tmp);
    string hour = arrTime.substr(0,2);
    int hour_int = stoi(hour);
    neww.tm_hour=hour_int;//when this is directly printed generates correct value


    string minute = arrTime.substr(2,2);
    int minute_int = stoi(minute);
    neww.tm_min=(minute_int);//when this is directly printed generates correct value

    time_t t1 = mktime(&neww);//only returns -1
    cout<<t1;

    return neww;
}

【讨论】:

  • time_t 在大多数实现中是long int,这是一个有符号整数类型。因此,它能够具有相同的正负值范围(在 32 位机器上)大约从 -2910 亿年到 +2910 亿年。
  • 请注意,mktime() 是时区敏感的:在世界上大多数地方,提供1970-01-01T00:00 不会产生mktime(...) == 0。因此,您需要将秒/分钟/小时添加到您从 localtime() 调用中获得的值中,而不是仅仅覆盖这些值。
  • @Detonar 32 位可以表示 2^32 = 4294967296,一年大约有 31536000 秒。 4294967296 / 31536000 = 136。所以实际上你可以代表 136 年,而不是数十亿年。但是由于某种原因,如果我超过 68 年,我的机器上的 mktime 会失败,这似乎是理论限制的一半,但不知道为什么。
  • @Drax a long int 在 32 位系统上表示从 -2^63 到 +2^63-1 的 64 位含义,即 -9223372036854775808 到 +9223372036854775807 秒......即使它只是一个简单的int,这将超过你提到的70年的差异。
  • 好吧,如果它只是一个简单的int 就可以解释它,因为int 已签名。但这会很奇怪。
【解决方案2】:

在这种情况下,使用前清除结构通常会有所帮助:

struct tm neww;
memset((void *)&neww, 0, sizeof(tm));

【讨论】:

  • 仍然返回-1!
  • 然后检查您传递的确切值。也许您传递了错误的值,例如小时 = 30、分钟 = 100 等。还有什么是 neww.tm_mday=1-31?你过了-30了吗?
  • neww.tm_sec=60;新w.tm_mday=1;新w.tm_mon=11;新w.tm_year=1900;新w.tm_wday=6; neww.tm_yday=365;
  • 至少您可以有冲突的日期设置:tm_mday、tm_wday 和 tm_yday,只指定其中之一。还有year=1900就是1900+1900,见cplusplus.com/reference/ctime/tm
  • struct tm DateTimeUtils::makeTime(string arrTime) { struct tm neww; memset((void *)&neww, 0, sizeof(tm));新w.tm_sec=1;新w.tm_mday=1;新w.tm_mon=1; neww.tm_year=0;字符串小时 = arrTime.substr(0,2); int hour_int = stoi(小时); neww.tm_hour=hour_int;字符串分钟 = arrTime.substr(2,2); int minute_int = stoi(分钟); neww.tm_min=(minute_int); time_t t1 = mktime(&neww); cout
【解决方案3】:

通常time_t被定义为64位整数,解析范围为

-2^63 到 +2^63-1(-9223372036854775808 到 +9223372036854775807)

大约是从-2920亿年到+292年。

但是。如果出于某种原因,在您的系统上 time_t 刚刚定义为 32 位整数(16 位嵌入式系统或奇怪的体系结构或头文件),我们会得到一个范围

2^31 到 2^31-1(-2147483648 到 +2147483647)

大约从 -68 岁到 +68 岁。

您可以通过在调用 mktime() 之前重新定义 time_t 来解决此问题。

#define time_t long int

或者如果真的使用 16 位系统

#define time_t long long int

【讨论】:

    猜你喜欢
    • 2015-05-06
    • 2014-02-02
    • 1970-01-01
    • 2021-07-21
    • 2019-03-16
    • 1970-01-01
    • 2015-09-09
    • 2016-05-23
    • 2012-06-22
    相关资源
    最近更新 更多