简体   繁体   English

如何将日期时间转换为 c 中的 unix 时间戳?

[英]how to convert datetime to unix timestamp in c?

the scenario is: I get datetime in format "YYYY-MM-DD HH:MM:SS" with libexif.场景是:我使用 libexif 获取格式为“YYYY-MM-DD HH:MM:SS”的日期时间。 To minimize the saving cost, I wanna convert the datetime to unix timestamp or alike which only cost 64bit or 32bit.为了尽量减少节省成本,我想将日期时间转换为 unix 时间戳或类似的时间戳,只需 64 位或 32 位。 Is there any explicit way with c? c 有什么明确的方法吗?

You could try a combination of strptime and mktime您可以尝试结合使用strptimemktime

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

Convert each part of the date/time into an integer to populate a struct tm , then convert that into a time_t using mktime .将日期/时间的每个部分转换为 integer 以填充struct tm ,然后使用mktime将其转换为time_t

Here is a wired solution in c/pseudo code I just hacked together.这是我刚刚一起破解的 c/伪代码中的有线解决方案。 Good luck!祝你好运!

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)

What about sscanf? 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

Here's a ready snippet when strptime is not available:当 strptime 不可用时,这是一个现成的片段:

#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;
}

Adjust youself a string in sscanf to what you need.根据需要调整 sscanf 中的字符串。 To ignore time zone and convert always as GMT/UTC substract a timezone (or _timezone ) from seconds ( timezone global is defined in time.h. DST is already ignored by zeroing tm_isdst field of tm .要忽略时区并始终转换为 GMT/UTC,请从seconds中减去timezone (或_timezone )( timezone全局在 time.h 中定义。DST 已通过将tmtm_isdst字段置零而被忽略。

Linux supports the getdate() function, which I think is more practical than calling strptime() directly. Linux支持getdate() function,我觉得比直接调用strptime()更实用。 This is because the getdate() function automatically checks many formats for you.这是因为getdate() function 会自动为您检查多种格式。 It is an equivalent to calling strptime() with various formats until the function works or all formats were tested.它等同于以各种格式调用strptime() ,直到 function 工作或所有格式都经过测试。

// 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));

Note: timegm() is similar to mktime() except that it ignores the locale and uses UTC.注意: timegm()类似于mktime() ,只是它忽略语言环境并使用 UTC。 In most cases that's the right way to convert your dates.在大多数情况下,这是转换日期的正确方法。

The datemsk.fmt file would include at least these two formats to support the above dates: datemsk.fmt 文件将至少包含以下两种格式以支持上述日期:

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

The number of supported formats is not limited, although you may not want to have too many.支持的格式数量没有限制,尽管您可能不想拥有太多。 It's going to be rather slow if you have too many formats.如果格式太多,速度会很慢。 You could also dynamically manage your formats and call strptime() in a loop.您还可以动态管理您的格式并在循环中调用strptime()

Linux also offers a getdate_r() function which is thread safe. Linux 还提供了线程安全的getdate_r() function。

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

for anyone using gcc, following code is working for me:对于使用 gcc 的任何人,以下代码对我有用:

#define YEAR_OFFSET 1900

struct tm* dt = (struct tm*)malloc(sizeof(struct tm));
char *strVar = "2022-08-13 23:09:47"; //! "YYYY-MM-DD HH:MM:SS"
time_t timeVar;
if(sscanf(strVar, "%d-%hhd-%hhd %hhd:%hhd:%hhd", &dt->tm_year, &dt->tm_mon, &dt->tm_mday, &dt->tm_hour, &dt->tm_min, &dt->tm_sec)==6)
{
    dt->tm_year -= YEAR_OFFSET;
    dt->tm_mon -= 1;
    timeVar = mktime(&tmVar);
}
else
    ;// bad format
free(dt);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM