【问题标题】:how to convert datetime to unix timestamp in c?如何将日期时间转换为 c 中的 unix 时间戳?
【发布时间】:2010-11-03 09:42:52
【问题描述】:

场景是:我使用 libexif 获取格式为“YYYY-MM-DD HH:MM:SS”的日期时间。为了最大限度地减少节省成本,我想将日期时间转换为仅花费 64 位或 32 位的 unix 时间戳等。 c有什么明确的方法吗?

【问题讨论】:

    标签: c unix datetime timestamp


    【解决方案1】:

    您可以尝试strptimemktime 的组合

    struct tm tm;
    time_t epoch;
    if ( strptime(timestamp, "%Y-%m-%d %H:%M:%S", &tm) != NULL )
      epoch = mktime(&tm);
    else
      // badness
    

    【讨论】:

    • 我知道一定有类似 strptime 的东西,但我找不到。我 99% 的时间都在使用 Microsoft,但他们不支持它。
    • +1:我在想strptime,但我不记得它的函数名了。
    • 附带说明,如果您使用的是 Windows,请参阅以下问题:stackoverflow.com/questions/321849/…
    • 我用 valgrind 得到了Conditional jump or move depends on uninitialised value(s),在这里看到同样的问题:stackoverflow.com/questions/9037631/…。将结构 tm 全部设置为零有帮助。
    • 我建议timegm() 而不是mktime() 以避免时区问题。
    【解决方案2】:

    将日期/时间的每一部分转换为整数以填充struct tm,然后使用mktime 将其转换为time_t

    【讨论】:

    • mktime() 通常是错误的函数,timegm() 更有可能是正确的函数。它不会考虑时区。
    【解决方案3】:

    这是我刚刚编写的 c/伪代码中的有线解决方案。祝你好运!

    char * runner = NULL;
    char *string_orig = "YYYY-MM-DD HH:MM:SS";
    time_t time = 0;
    struct tm tmp;
    
    use strstr(string_orig, "-") and atoi foreach
    
      tmp->tm_year .. 
      tmp->tm_mon  .. 
      tmp->tm_mday ..  
      tmp->tm_hour  .. 
      tmp->tm_min  .. 
      tmp->tm_sec .. 
    
    with *runner as help
    
    time = mktime(&tm)
    

    【讨论】:

      【解决方案4】:

      sscanf 呢?

      struct tm tmVar;
      char *strVar = "YYYY-MM-DD HH:MM:SS";
      time_t timeVar;
      if(sscanf(strVar, "%d-%d-%d %d:%d:%d", &tm.tm_year, /* the other fields */)==6)
          timeVar = mktime(&tmVar);
      else
          // bad format
      

      【讨论】:

        【解决方案5】:

        当 strptime 不可用时,这是一个现成的 sn-p:

        #include <stddef.h>
        #include <time.h> 
        #include <stdio.h> 
        
        time_t string_to_seconds(const char *timestamp_str)
        {
            struct tm tm;
            time_t seconds;
            int r;
        
            if (timestamp_str == NULL) {
                printf("null argument\n");
                return (time_t)-1;
            }
            r = sscanf(timestamp_str, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
            if (r != 6) {
                printf("expected %d numbers scanned in %s\n", r, timestamp_str);
                return (time_t)-1;
            }
        
            tm.tm_year -= 1900;
            tm.tm_mon -= 1;
            tm.tm_isdst = 0;
            seconds = mktime(&tm);
            if (seconds == (time_t)-1) {
                printf("reading time from %s failed\n", timestamp_str);
            }
        
            return seconds;
        }
        

        将 sscanf 中的字符串调整为您需要的字符串。要忽略时区并始终转换为 GMT/UTC 从 seconds 中减去 timezone(或 _timezone)(timezone 全局在 time.h 中定义。DST 已通过将 @ 的 tm_isdst 字段归零而被忽略987654327@.

        【讨论】:

          【解决方案6】:

          Linux支持getdate()函数,我觉得比直接调用strptime()更实用。这是因为getdate() 函数会自动为您检查许多 格式。相当于以各种格式调用strptime(),直到函数正常工作或所有格式都经过测试。

          // setenv() should be called only once
          setenv("DATEMSK", "/usr/share/myprog/datemsk.fmt", 0);
          
          // convert a date
          struct tm * t1(getdate("2018-03-31 14:35:46"));
          if(t1 == nullptr) ...handle error...
          time_t date1(timegm(t1));
          
          // convert another date
          struct tm * t2(getdate("03/31/2018 14:35:46"));
          if(t2 == nullptr) ...handle error...
          time_t date2(timegm(t2));
          

          注意:timegm()mktime() 类似,只是它忽略了区域设置并使用 UTC。在大多数情况下,这是转换日期的正确方法。

          datemsk.fmt 文件将至少包含这两种格式以支持上述日期:

          %Y-%b-%d %H:%M:%S
          %b/%d/%Y %H:%M:%S
          

          支持的格式数量不受限制,但您可能不想拥有太多。如果格式太多,它会很慢。您还可以动态管理格式并循环调用strptime()

          Linux 还提供了一个线程安全的getdate_r() 函数。

          手册页:http://pubs.opengroup.org/onlinepubs/7908799/xsh/getdate.html

          【讨论】:

            猜你喜欢
            • 2020-10-19
            • 2019-04-24
            • 1970-01-01
            • 1970-01-01
            • 2015-02-09
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-07
            相关资源
            最近更新 更多