【问题标题】:Time since epoch is -1自纪元以来的时间为-1
【发布时间】:2013-03-26 01:43:47
【问题描述】:

我正在尝试获取自纪元以来经过的秒数。代码:

long parseTime(string time) {

  cout << "Time entered = " << time << endl;

  long timeSinceEpoch;

  //takes in time in string format - date + time and returns seconds from epoch.
  /* Steps:
   * 1. Remove trailing and leading spaces.
   * 2. Check format of date.
   * 3. Convert to epoch.
   */

  //remove trailing and leading spaces.
  /*
  unsigned int leading = 0, trailing = 0;
  string whitespace = " \t";

  leading = time.find_first_not_of(whitespace);
  trailing = time.find_last_not_of(whitespace);

  string newTime = time.substr(leading, (trailing - leading + 1));
  cout << "Old time = " << time << " new time = " << newTime << endl;
  */
  string newTime = time;

  struct tm t;

  if(newTime.find("/") != string::npos) {
    //format of date is mm/dd/yyyy. followed by clock in hh:mm (24 hour clock).
    cout << "Time format contains slashes." << endl;
    if(strptime(newTime.c_str(), "%m/%e/%Y %H:%M", &t) == NULL) {
      cout << "Error. Check string for formatting." << endl;
    }
  } else if(newTime.find("-") != string::npos) {
    //format of date is yyyy-mm-dd hh:mm:ss (hh in 24 hour clock format).
    if(strptime(newTime.c_str(), "%Y-%m-%e %H:%M:%S", &t) == NULL) {
     cout << "Error. Check string for formatting of new date." << endl;
    }
  }

  if(t.tm_isdst) {
    t.tm_isdst = 0;
  }

  timeSinceEpoch = mktime(&t);
  cout << "Time since epoch = " << timeSinceEpoch << endl;

  return timeSinceEpoch;
}

现在,当将包含日期和时间的字符串传递给函数时:
3/26/2013 3:17
它导致自 epoch = -1 以来的时间。这是调试器的输出:

Breakpoint 2, parseTime (time=...) at informationExtractor.cpp:44
44        cout << "Time entered = " << time << endl;
(gdb) n
Time entered = 3/26/2013 3:17
66        string newTime = time;
(gdb)
70        if(newTime.find("/") != string::npos) {
(gdb) p newTime
$3 = {static npos = <optimized out>,
  _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
    _M_p = 0x8004ab0c "3/26/2013 3:17"}}
(gdb) n
72          cout << "Time format contains slashes." << endl;
(gdb)
Time format contains slashes.
73          if(strptime(newTime.c_str(), "%m/%e/%Y %H:%M", &t) == NULL) {
(gdb)
83        if(t.tm_isdst) {
(gdb) p newTime.c_str()@strlen(newTime.c_str())
Only values in memory can be extended with '@'.
(gdb) n
84          t.tm_isdst = 0;
(gdb) p newTime
$4 = {static npos = <optimized out>,
  _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},
    _M_p = 0x8004ab0c "3/26/2013 3:17"}}
(gdb) n
87        timeSinceEpoch = mktime(&t);
(gdb) p t
$5 = {tm_sec = 1628993312, tm_min = 17, tm_hour = 3, tm_mday = 26, tm_mon = 2, tm_year = 113, tm_wday = 2, tm_yday = 84,
  tm_isdst = 0}
(gdb) n
88        cout << "Time since epoch = " << timeSinceEpoch << endl;
(gdb)
Time since epoch = -1
90        return timeSinceEpoch;
(gdb)  

如果您注意到,t 中的 tm_sec 是 1628993312,而 timesinceEpoch 是 -1。 tm_sec 也在 long 的范围内,timesinceEpoch 的数据类型。欢迎任何关于为什么以及如何解决此问题的想法。

【问题讨论】:

    标签: c++ epoch ctime


    【解决方案1】:

    关键是在您的代码中 tm_sec 是一个未初始化的值。它应该是一个介于 0 和 59 之间的值。因此,将这行代码添加到您的第一个 if 分支中。

    if(strptime(newTime.c_str(), "%m/%e/%Y %H:%M", &t) == NULL) {
      cout << "Error. Check string for formatting." << endl;
    }
    t.tm_sec = 0; // initialise seconds field
    

    【讨论】:

    • tm_sec 在用strptime 初始化后设置为0?那将如何工作?此外,调试器输出显示tm_sec(自纪元以来的时间)在调用 mktime 后被设置为 -1 之前被初始化为 1628993312。
    • 我的意思是它没有被strptime初始化,你的格式字符串中没有%S。
    • 我不确定我是否理解这一点。 %S 是秒,输入到函数的时间字符串没有秒,只有小时:分钟。
    • 没关系,但是因为当你的日期中有斜线时,tm 结构中的 tm_sec 字段没有被设置。但是 mktime 需要设置 tm 结构中的所有字段。所以在这种情况下你必须手动设置它。
    【解决方案2】:

    约翰是对的。 strptime 不初始化 tm 并且仅触摸明确指定的字段 (see "Notes" of strptime(3)), 所以t.tm_sec 没有被初始化。

    为了防止这种错误,你可以声明带有初始化的变量

    struct tm t = { 0 }; // zero filled
    

    【讨论】:

      猜你喜欢
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      • 2013-05-14
      • 2013-10-25
      • 2019-12-04
      相关资源
      最近更新 更多