如何将日期时间转换为 c 中的 unix 时间戳?
Posted
技术标签:
【中文标题】如何将日期时间转换为 c 中的 unix 时间戳?【英文标题】:how to convert datetime to unix timestamp in c? 【发布时间】:2010-11-03 09:42:52 【问题描述】:场景是:我使用 libexif 获取格式为“YYYY-MM-DD HH:MM:SS”的日期时间。为了最大限度地减少节省成本,我想将日期时间转换为仅花费 64 位或 32 位的 unix 时间戳等。 c有什么明确的方法吗?
【问题讨论】:
【参考方案1】:您可以尝试strptime 和mktime 的组合
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,请参阅以下问题:***.com/questions/321849/… 我用 valgrind 得到了Conditional jump or move depends on uninitialised value(s)
,在这里看到同样的问题:***.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
【讨论】:
以上是关于如何将日期时间转换为 c 中的 unix 时间戳?的主要内容,如果未能解决你的问题,请参考以下文章