【问题标题】:Date/time conversion: string representation to time_t [closed]日期/时间转换:字符串表示为 time_t [关闭]
【发布时间】:2010-09-24 05:19:12
【问题描述】:

如何在 C 或 C++ 中将格式为 "MM-DD-YY HH:MM:SS" 的日期字符串转换为 time_t 值?

【问题讨论】:

    标签: c++ c datetime


    【解决方案1】:

    恐怕标准 C / C++ 中没有。 POSIX 函数strptime 可以转换为struct tm,然后可以使用mktime 转换为time_t

    如果你的目标是跨平台兼容,最好使用boost::date_time,它具有复杂的功能。

    【讨论】:

      【解决方案2】:

      使用strptime() 将时间解析为struct tm,然后使用mktime() 转换为time_t

      【讨论】:

      • strptime() 在 Windows 上似乎不可用。有什么好的选择吗?
      • 不知道在 Windows 上是否是一个好的替代方案,有几个开源实现可供您使用。或者,如果您知道日期将始终采用您提供的格式,您可以将其解析为 struct tm,也许使用 sscanf,然后使用 mktime 获取 time_t。
      • @An̲̳̳drew strptime() 通常在带有 gcc 编译器的 Windows 上可用。可用性是编译器问题,而不是操作系统问题。
      【解决方案3】:

      Boost 的日期时间库应该会有所帮助;特别是你可能想看看http://www.boost.org/doc/libs/1_37_0/doc/html/date_time/date_time_io.html

      【讨论】:

        【解决方案4】:

        在没有strptime 的情况下,您可以使用sscanf 将数据解析为struct tm,然后调用mktime。不是最优雅的解决方案,但它会起作用。

        【讨论】:

          【解决方案5】:
              static time_t MKTimestamp(int year, int month, int day, int hour, int min, int sec)
          {
              time_t rawtime;
              struct tm * timeinfo;
          
              time ( &rawtime );
              timeinfo = gmtime ( &rawtime );
              timeinfo->tm_year = year-1900 ;
              timeinfo->tm_mon = month-1;
              timeinfo->tm_mday = day;
              timeinfo->tm_hour = hour;
              timeinfo->tm_min = min;
              timeinfo->tm_sec = sec;
              timeinfo->tm_isdst = 0; // disable daylight saving time
          
              time_t ret = mktime ( timeinfo );
          
              return ret;
          }
          
           static time_t GetDateTime(const std::string pstr)
          {
              try 
              {
                  // yyyy-mm-dd
                  int m, d, y, h, min;
                  std::istringstream istr (pstr);
          
                  istr >> y;
                  istr.ignore();
                  istr >> m;
                  istr.ignore();
                  istr >> d;
                  istr.ignore();
                  istr >> h;
                  istr.ignore();
                  istr >> min;
                  time_t t;
          
                  t=MKTimestamp(y,m,d,h-1,min,0);
                  return t;
              }
              catch(...)
              {
          
              }
          }
          

          【讨论】:

            【解决方案6】:

            请注意,接受的答案中提到的strptime 不可移植。这是我用来将字符串转换为 std::time_t 的方便 C++11 代码:

            static std::time_t to_time_t(const std::string& str, bool is_dst = false, const std::string& format = "%Y-%b-%d %H:%M:%S")
            {
                std::tm t = {0};
                t.tm_isdst = is_dst ? 1 : 0;
                std::istringstream ss(str);
                ss >> std::get_time(&t, format.c_str());
                return mktime(&t);
            }
            

            你可以这样称呼它:

            std::time_t t = to_time_t("2018-February-12 23:12:34");
            

            可以找到字符串格式参数here

            【讨论】:

            • 1) 代码未设置tm_isdst 成员。不这样做会导致不一致的结果。 2) struct tm 确实允许其他成员受益于初始化。也许std::tm t = { 0 };? 3) OP 的月份字符串是数字,而不是字母,使用"%m" 而不是"%b"。 4) OP 使用的顺序与 YMD hms 不同。
            • 我添加了 dst 选项。用 0 初始化是个好主意。其他内容可以根据个人需求轻松调整。
            【解决方案7】:

            将格式为“MM-DD-YY HH:MM:SS”的日期字符串转换为 time_t 的最佳方法

            将代码限制为标准 C 库函数正在寻找 strftime() 的倒数。要扩展@Rob 的总体思路,请使用sscanf()

            使用"%n" 检测完成的扫描

            time_t date_string_to_time(const char *date) {
              struct tm tm = { 0 }; // Important, initialize all members
              int n = 0;
              sscanf(date, "%d-%d-%d %d:%d:%d %n", &tm.tm_mon, &tm.tm_mday, &tm.tm_year,
                  &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &n);
              // If scan did not completely succeed or extra junk
              if (n == 0 || date[n]) {
                return (time_t) -1;
              }
              tm.tm_isdst = -1; // Assume local daylight setting per date/time
              tm.tm_mon--;      // Months since January
              // Assume 2 digit year if in the range 2000-2099, else assume year as given
              if (tm.tm_year >= 0 && tm.tm_year < 100) {
                tm.tm_year += 2000;
              }
              tm.tm_year -= 1900; // Years since 1900
              time_t t = mktime(&tm);
              return t;
            }
            

            附加代码可用于确保只有 2 位时间戳部分、正值、间距等。

            注意:这里假设“MM-DD-YY HH:MM:SS”是本地时间。

            【讨论】:

            • 有趣,我从来没有真正找到%n 的用例,因为我一直使用*scanf 的返回值来确保扫描所有参数。但是,%n(您使用它的方式)似乎做到了这一点并且确保在预期的字符串之后没有额外的gumpf。现在我并不经常学习关于 C 的任何新知识,所以很荣幸 :-)
            • @paxdiablo 谢谢。通常," %n" 也有助于检测任何必需的尾随文本,返回值无法区分。例如。 "%d xyz %n".
            猜你喜欢
            • 2018-07-25
            • 2013-06-28
            • 2021-03-21
            • 2013-02-13
            • 1970-01-01
            • 2020-05-24
            • 2022-08-04
            • 2020-12-19
            • 2022-12-20
            相关资源
            最近更新 更多