C代码获取相对于UTC的本地时间偏移(以分钟为单位)?

chm*_*ike 9 c time utc offset

我没有找到一种简单的方法来获得当地时间和UTC时间之间的分钟数.

起初我打算使用,tzset()但它不提供夏令时.根据手册页,如果日光节省有效,它只是一个不等于零的整数.虽然通常是一个小时,但在某些国家可能需要半小时.

我宁愿避免计算当前UTC返回的时间差gmtime()localtime().

更通用的解决方案将为我提供指定位置和正time_t值的信息,或至少在本地.

编辑1:用例是为https://github.com/chmike/timez获取正确的本地时间偏移量.顺便说一句,如果您认为libc函数操作时间还可以,请阅读https://rachelbythebay.com/w/2013/03/17/time/.

编辑2:迄今为止我用来计算UTC时间偏移的最佳和最简单的解决方案是

// Bogus: assumes DST is always one hour
tzset();
int offset = (int)(-timezone / 60 + (daylight ? 60 : 0));
Run Code Online (Sandbox Code Playgroud)

问题是确定实际的节省时间.

编辑3:受到@trenki答案的启发,我提出了以下解决方案.这是一个黑客,因为它mktime()可以将输出gmtime()视为本地时间.当DST更改在UTC时间和本地时间之间的时间跨度时,结果是不准确的.

#include <stdio.h>
#include <time.h>

int main()
{
    time_t rawtime = time(NULL);
    struct tm *ptm = gmtime(&rawtime);
    // Request that mktime() looksup dst in timezone database
    ptm->tm_isdst = -1;                
    time_t gmt = mktime(ptm);
    double offset = difftime(rawtime, gmt) / 60;
    printf("%f\n", offset);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

tre*_*nki 5

此C代码以分钟为单位计算相对于UTC的本地时间偏移。假定DST总是偏移一小时。

#include <stdio.h>
#include <time.h>

int main()
{
    time_t rawtime = time(NULL);
    struct tm *ptm = gmtime(&rawtime);
    time_t gmt = mktime(ptm);
    ptm = localtime(&rawtime);
    time_t offset = rawtime - gmt + (ptm->tm_isdst ? 3600 : 0);

    printf("%i\n", (int)offset);
}
Run Code Online (Sandbox Code Playgroud)

虽然它使用gmtime和localtime。您为什么不想使用这些功能?

  • 在豪勋爵岛(澳大利亚),夏令时为 30 分钟。请参阅http://www.timeanddate.com/time/zone/australia/lord-howe-island。我宁愿避免 `gmtime()` 和 `localtime()` 因为 1) 它涉及比所需更多的计算 2) 计算字段的时间偏移很棘手并且容易出错。 (2认同)

deg*_*ski 1

我想对这个问题提交另一个答案,即 AFAICS 也涉及 IDL。

该解决方案取决于timegmmktime。在 Windows 上timegm可从 CRT 获取_mkgmtime,换句话说,定义一个条件宏。

#if _WIN32
#    define timegm _mkgmtime
#endif

int local_utc_offset_minutes ( ) {
    time_t t  = time ( NULL );
    struct tm * locg = localtime ( &t );
    struct tm locl;
    memcpy ( &locl, locg, sizeof ( struct tm ) );
    return (int)( timegm ( locg ) - mktime ( &locl ) ) / 60;
}
Run Code Online (Sandbox Code Playgroud)