当前位置:  开发笔记 > 编程语言 > 正文

将struct tm(以UTC表示)转换为time_t类型的简便方法

如何解决《将structtm(以UTC表示)转换为time_t类型的简便方法》经验,为你挑选了6个好方法。

我该怎么办?有mktime函数,但是将输入视为以本地时间表示,但如果我的输入tm变量恰好是UTC,我该如何执行转换.



1> Martin York..:

使用timegm()而不是mktime()


很好的答案 - 唯一的缺点是它是非标准的(如在POSIX或C标准中),而不是在POSIX或C标准中.
向下投票,因为你没有解释为什么人们应该使用`timegm()`而不是`mktime()`; 没有解释我包括赞成达纳的论点.

2> hobo..:

对于Windows上的用户,可以使用以下功能:

_mkgmtime

链接获取更多信息:https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/mkgmtime-mkgmtime32-mkgmtime64



3> 小智..:

这是我使用的解决方案(不记得我发现它的位置)当它不是Windows平台时

time_t _mkgmtime(const struct tm *tm) 
{
    // Month-to-day offset for non-leap-years.
    static const int month_day[12] =
    {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

    // Most of the calculation is easy; leap years are the main difficulty.
    int month = tm->tm_mon % 12;
    int year = tm->tm_year + tm->tm_mon / 12;
    if (month < 0) {   // Negative values % 12 are still negative.
        month += 12;
        --year;
    }

    // This is the number of Februaries since 1900.
    const int year_for_leap = (month > 1) ? year + 1 : year;

    time_t rt = tm->tm_sec                             // Seconds
        + 60 * (tm->tm_min                          // Minute = 60 seconds
        + 60 * (tm->tm_hour                         // Hour = 60 minutes
        + 24 * (month_day[month] + tm->tm_mday - 1  // Day = 24 hours
        + 365 * (year - 70)                         // Year = 365 days
        + (year_for_leap - 69) / 4                  // Every 4 years is     leap...
        - (year_for_leap - 1) / 100                 // Except centuries...
        + (year_for_leap + 299) / 400)));           // Except 400s.
    return rt < 0 ? -1 : rt;
}



4> 小智..:

以下实现timegm(1)在Android上运行,也可能适用于其他Unix变体:

time_t timegm( struct tm *tm ) {
  time_t t = mktime( tm );
  return t + localtime( &t )->tm_gmtoff;
}



5> Tom..:

timegm() 可以工作,但并不存在于所有系统上.

这是一个只使用ANSI C的版本.(编辑:不是严格的ANSI C!我在time_t上做数学,假设单位是自纪元以来的秒数.AFAIK,标准没有定义time_t的单位.)注意,它利用黑客,可以说,确定机器的时区,然后相应地调整mktime的结果.


/*
  returns the utc timezone offset
  (e.g. -8 hours for PST)
*/
int get_utc_offset() {

  time_t zero = 24*60*60L;
  struct tm * timeptr;
  int gmtime_hours;

  /* get the local time for Jan 2, 1900 00:00 UTC */
  timeptr = localtime( &zero );
  gmtime_hours = timeptr->tm_hour;

  /* if the local time is the "day before" the UTC, subtract 24 hours
    from the hours to get the UTC offset */
  if( timeptr->tm_mday < 2 )
    gmtime_hours -= 24;

  return gmtime_hours;

}

/*
  the utc analogue of mktime,
  (much like timegm on some systems)
*/
time_t tm_to_time_t_utc( struct tm * timeptr ) {

  /* gets the epoch time relative to the local time zone,
  and then adds the appropriate number of seconds to make it UTC */
  return mktime( timeptr ) + get_utc_offset() * 3600;

}


除非您的时区UTC偏移是整个小时,否则此代码将无效.有12个时区,这是不正确的.参考.https://en.wikipedia.org/wiki/Time_zone#List_of_UTC_offsets

6> liberforce..:

Loki Astari的答案是一个良好的开端,timegm是可能的解决方案之一.但是,手册timegm版本提供了它,因为timegm它不符合POSIX标准.这里是:

#include 
#include 

time_t
my_timegm(struct tm *tm)
{
    time_t ret;
    char *tz;

    tz = getenv("TZ");
    if (tz)
        tz = strdup(tz);
    setenv("TZ", "", 1);
    tzset();
    ret = mktime(tm);
    if (tz) {
        setenv("TZ", tz, 1);
        free(tz);
    } else
        unsetenv("TZ");
    tzset();
    return ret;
}

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有