在Python或Java中,您可以根据时区的IANA名称(例如“America / Los_Angeles”)获取UTC偏移量(当前时间)。例如,请参阅Get UTC offset from time zone name in python。
如何在Ubuntu 14.04上使用C / C ++做同样的事情?
编辑:最好以线程安全的方式(没有环境变量)。
答案 0 :(得分:2)
您提到了这个事实,但重要的是要注意UTC与时区中的时间之间的偏差不一定是恒定的。如果时区执行夏令时(夏令时)调整,则偏移量将根据一年中的时间而变化。
找到偏移的一种方法是花时间感兴趣,将其交给localtime()
函数,然后查看tm_gmtoff
字段。通过将TZ
环境变量设置为您感兴趣的区域名称来执行此操作。以下是针对当前时间执行此操作的示例:
#include <time.h>
#include <stdio.h>
int main()
{
setenv("TZ", "America/Los_Angeles", 1);
time_t t = time(NULL);
struct tm *tmp = localtime(&t);
printf("%ld\n", tmp->tm_gmtoff);
}
目前这打印-25200,表明洛杉矶是25200秒,或420分钟,或格林威治以西7小时。但下周(实际上是明天)美国退出DST,此时此代码将开始打印-28800。
由于tm_gmtoff
字段不可移植,因此无法保证正常工作。但我相信所有版本的Linux都会拥有它。 (您可能需要使用-D_BSD_SOURCE
或其他内容进行编译,或者将该字段称为__tm_gmtoff
。但根据我的经验,它默认情况下可以正常工作,只需tm_gmtoff
。)
另一种方式是使用gmtime
和mktime
来回,如Sam Varshavchik的回答所述。
附录:您询问了不使用环境变量的问题。有一种方法,但遗憾的是它的标准更低。有BSD函数tzalloc
和localtime_rz
可以完成这项工作,但它们在Linux上不存在。以下是代码的外观:
timezone_t tz = tzalloc("America/Los_Angeles");
if(tz == NULL) return 1;
time_t t = time(NULL);
struct tm tm, *tmp = localtime_rz(tz, &t, &tm);
printf("%ld\n", tmp->tm_gmtoff);
对我来说,打印-28800(因为PDT在几分钟之前就回到了PST)。
如果你有,你也可以在Sam Varshavchik的回答中使用localtime_rz
和mktime
。当然,Howard Hinnant的图书馆显然是线程安全的,根本不需要使用TZ
。
编辑(OP):localtime_rz
和tzalloc
的代码可以从https://www.iana.org/time-zones下载,适用于Ubuntu 14.04。
答案 1 :(得分:2)
您可以使用此free open source C++11/14 library执行此操作:
#include "chrono_io.h"
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
auto zt = make_zoned("America/Los_Angeles", system_clock::now());
std::cout << zt.get_info().offset << '\n';
}
目前输出:
-25200s
或者你可以这样格式化它:
std::cout << make_time(zt.get_info().offset) << '\n';
目前输出:
-07:00:00
工厂职能make_zoned
使用IANA名称&#34; America / Los_Angeles&#34;创建zoned_time
。以及std::chrono::system_clock
的当前时间。 zoned_time
当时的时区有<{3}} 。该信息是一种名为member getter to get the information的类型,它包含各种有用信息,包括当前的UTC偏移量。
UTC偏移量存储为std::chrono::seconds
。标头"chrono_io.h"
将格式化durations
以进行流式传输。或者sys_info
实用程序可用于将持续时间格式化为hh:mm:ss
。
上面的程序是线程安全的。您不必担心其他一些过程会改变您的TZ,或以任何其他方式更改计算机的当前时区。如果您想要有关当前时区的信息,也可以使用current_zone()
代替"America/Los_Angeles"
。
如果你想探索其他时间,那就很容易了。例如,从2016年11月6日当地时间凌晨2点开始:
auto zt = make_zoned("America/Los_Angeles", local_days{nov/6/2016} + 2h);
输出更改为:
-28800s
-08:00:00
有关此图书馆的更多信息已在Cppcon 2016上展示,可在此处查看:
答案 2 :(得分:1)
首先使用gmtime()
将当前纪元时间转换为UTC时间,然后使用mktime()
重新计算纪元时间,然后将结果与实际纪元时间进行比较。
gmtime()
以UTC计算struct tm
,而mktime()
则假定struct tm
代表当前的本地日历时间。因此,通过进行此循环计算,您可以间接计算当前时区偏移量。
请注意,如果mktime()
无法转换为纪元时间,则struct tm
会返回错误,这将在标准时间和备用时间之间的某些转换期间发生。在你的情况下,由你决定这意味着什么。
配方看起来像这样:
time_t t = time(NULL);
struct tm *tmp = gmtime(&t);
time_t t2 = mktime(tmp);
int offset = t - t2;
有关详细信息,请参阅the documentation of these library functions。
要使用特定时区,请设置TZ
环境变量,或者您可以尝试使用localtime_rz
,如Steve Summit的答案。如上所述,请注意mktime
有时会在不可逆转的时间内返回-1。