获取相对于UTC的本地时间偏移(以分钟为单位)的C代码?
我没有找到一种简单的方法来获取本地时间和UTC时间之间的时间偏移量(以分钟为单位) 起初我打算使用获取相对于UTC的本地时间偏移(以分钟为单位)的C代码?,c,time,offset,utc,C,Time,Offset,Utc,我没有找到一种简单的方法来获取本地时间和UTC时间之间的时间偏移量(以分钟为单位) 起初我打算使用tzset(),但它不提供夏令时。根据手册页,如果日光节约生效,它只是一个与零不同的整数。虽然通常是一小时,但在某些国家可能是半小时 我希望避免计算gmtime()和localtime()返回的当前UTC之间的时差 一个更一般的解决方案将为我提供指定位置和正时间值的信息,或者至少是局部信息 编辑1:用例是获取正确的本地时间偏移。 顺便说一句,如果您认为操纵时间的libc函数还可以,请阅读以下内容 编
tzset()
,但它不提供夏令时。根据手册页,如果日光节约生效,它只是一个与零不同的整数。虽然通常是一小时,但在某些国家可能是半小时
我希望避免计算gmtime()
和localtime()
返回的当前UTC之间的时差
一个更一般的解决方案将为我提供指定位置和正时间值的信息,或者至少是局部信息 编辑1:用例是获取正确的本地时间偏移。 顺便说一句,如果您认为操纵时间的libc函数还可以,请阅读以下内容 编辑2:到目前为止,计算UTC时间偏移量(以分钟为单位)的最佳最简单解决方案是
// Bogus: assumes DST is always one hour
tzset();
int offset = (int)(-timezone / 60 + (daylight ? 60 : 0));
问题是要确定实际的日间节能时间
编辑3:受的启发,我想出了以下解决方案。这是一个黑客程序,它的代码<>代码> MKTime](/Cord>)考虑“代码”> GMSTIME()/<代码>的输出作为LoalalTimes。当DST更改在UTC时间和localtime之间的时间跨度内时,结果不准确
#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;
}
#包括
#包括
int main()
{
time\u t rawtime=时间(空);
struct tm*ptm=gmtime(&rawtime);
//请求在时区数据库中使用mktime()looksup dst
ptm->tm_isdst=-1;
时间\u t gmt=mktime(ptm);
双偏移量=difftime(rawtime,gmt)/60;
printf(“%f\n”,偏移量);
返回0;
}
系统的strftime()函数是否支持%z
和%z
说明符?在FreeBSD上
我可以用这个来打印这个:
$ date +"%Z: %z"
CEST: +0200
ISO C99在7.23.3.5的strftime
功能中有此功能:
此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);
}
#包括
#包括
int main()
{
time\u t rawtime=时间(空);
struct tm*ptm=gmtime(&rawtime);
时间\u t gmt=mktime(ptm);
ptm=本地时间(&rawtime);
时间偏移=原始时间-gmt+(ptm->tm isdst?3600:0);
printf(“%i\n”,(int)偏移量);
}
但它使用gmtime和localtime。你为什么不想使用这些函数呢?我想,唯一简单方便的方法是使用
localtime
和gmtime
并在几分钟内手动计算增量,因为这两个函数存在于所有已知系统上。例如:
int deltam() {
time_t t = time(NULL);
struct tm *loc = localtime(&t);
/* save values because they could be erased by the call to gmtime */
int loc_min = loc->tm_min;
int loc_hour = loc->tm_hour;
int loc_day = loc->tm_mday;
struct tm *utc = gmtime(&t);
int delta = loc_min - utc->tm_min;
int deltaj = loc_day - utc->tm_mday;
delta += (loc_hour - utc->tm_hour) * 60;
/* hack for the day because the difference actually is only 0, 1 or -1 */
if ((deltaj == 1) || (deltaj < -1)) {
delta += 1440;
}
else if ((deltaj == -1) || (deltaj > 1)) {
delta -= 1440;
}
return delta;
}
int deltam(){
时间t=时间(空);
struct tm*loc=本地时间(&t);
/*保存值,因为可以通过调用gmtime擦除这些值*/
int loc_min=loc->tm_min;
int loc\U hour=loc->tm\U hour;
int loc\U day=loc->tm\U mday;
struct tm*utc=gmtime(&t);
int delta=loc_min-utc->tm_min;
int deltaj=loc\U day-utc->tm\U mday;
增量+=(当地时间-utc->tm时间)*60;
/*因为实际差异只有0、1或-1*/
如果((deltaj==1)| |(deltaj<-1)){
delta+=1440;
}
else如果((deltaj==-1)| |(deltaj>1)){
delta-=1440;
}
返回三角洲;
}
当心,我并没有测试所有可能的角落案例,但这可能是您需求的起点
。。。要获取本地时间偏移。。。相对于UTC
答案是好的。所以我想我会测试它并清理一些细节。我可能会发表评论,但显然太大了。我只在我的时区使用它,但其他人可能想在他们的机器和时区上试用
我访问社区维基是为了不获得代表
这个答案类似于,只是它减去附近的struct tm
值,而不是假设DST班次为1小时,time\u t
以秒为单位
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// return difference in **seconds** of the tm_mday, tm_hour, tm_min, tm_sec members.
long tz_offset_second(time_t t) {
struct tm local = *localtime(&t);
struct tm utc = *gmtime(&t);
long diff = ((local.tm_hour - utc.tm_hour) * 60 + (local.tm_min - utc.tm_min))
* 60L + (local.tm_sec - utc.tm_sec);
int delta_day = local.tm_mday - utc.tm_mday;
// If |delta_day| > 1, then end-of-month wrap
if ((delta_day == 1) || (delta_day < -1)) {
diff += 24L * 60 * 60;
} else if ((delta_day == -1) || (delta_day > 1)) {
diff -= 24L * 60 * 60;
}
return diff;
}
void testtz(void) {
long off = -1;
int delta = 600;
for (time_t t = 0; t < LONG_MAX-delta; t+=delta) {
long off2 = tz_offset_second(t);
// Print time whenever offset changes.
if (off != off2) {
struct tm utc = *gmtime(&t);
printf("%10jd %04d-%02d-%02dT%02d:%02d:%02dZ\n", (intmax_t) t,
utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday,
utc.tm_hour, utc.tm_min, utc.tm_sec);
struct tm local = *localtime(&t);
off = off2;
printf("%10s %04d-%02d-%02d %02d:%02d:%02d %2d %6ld\n\n", "",
local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,
local.tm_hour, local.tm_min, local.tm_sec, local.tm_isdst ,off);
fflush(stdout);
}
}
puts("Done");
}
我想为这个问题提供另一个答案,AFAICS也处理IDL 此解决方案取决于
timegm
和mktime
。在Windows上,可以从CRT中以\u mkgmtime
的形式获得timegm
,换句话说,定义一个条件宏
#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;
}
你为什么需要这个?更多地解释上下文;为什么您不能简单地使用
gmtime
和localtime
并改变它们的struct tm
?为什么您的用户会关心本地时间偏移?还有很多奇怪的情况(例如除夕夜…),你的问题很可能是操作系统特有的。。。AFAIK,不在标准C99中,但在POSIX@BasileStarynkevitch区域设置在C99中,甚至C89也有strftime
,可惜只有%Z
,而不是%Z
“通用解决方案将为指定位置提供此信息”-->您希望如何指定位置?纬度/经度?现在你需要一张时区地图。由于地图随时间而变化,现在需要地图的历史记录。相反,建议使用简单设计来实现“特定时区的通用解决方案”。@BasileStarynkevitch它适用于此小型库:。这是一项正在进行的工作。我仍然需要验证一些东西的有效性,比如分钟时间偏移分辨率。我的问题不是针对操作系统的。我希望该库可以在Windows或Linux上使用。在Unix和GNU上,tm结构具有保存请求信息的TMgmtoff字段。这将是获取信息的一种方法。有点复杂,但它会起作用。但举例来说,VisualStudio不支持C99。不确定风投2015,但这是一个众所周知的问题。我更愿意避免对C99的依赖。解析文本“-0030”
(和其他)需要小心以正确应用符号。例如,sscanf(“-0030”、%c%2d%2d”、&sign、&hour、&min);增量=(符号='-'?-1:1)*(小时*60+分钟)鳕鱼
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
// return difference in **seconds** of the tm_mday, tm_hour, tm_min, tm_sec members.
long tz_offset_second(time_t t) {
struct tm local = *localtime(&t);
struct tm utc = *gmtime(&t);
long diff = ((local.tm_hour - utc.tm_hour) * 60 + (local.tm_min - utc.tm_min))
* 60L + (local.tm_sec - utc.tm_sec);
int delta_day = local.tm_mday - utc.tm_mday;
// If |delta_day| > 1, then end-of-month wrap
if ((delta_day == 1) || (delta_day < -1)) {
diff += 24L * 60 * 60;
} else if ((delta_day == -1) || (delta_day > 1)) {
diff -= 24L * 60 * 60;
}
return diff;
}
void testtz(void) {
long off = -1;
int delta = 600;
for (time_t t = 0; t < LONG_MAX-delta; t+=delta) {
long off2 = tz_offset_second(t);
// Print time whenever offset changes.
if (off != off2) {
struct tm utc = *gmtime(&t);
printf("%10jd %04d-%02d-%02dT%02d:%02d:%02dZ\n", (intmax_t) t,
utc.tm_year + 1900, utc.tm_mon + 1, utc.tm_mday,
utc.tm_hour, utc.tm_min, utc.tm_sec);
struct tm local = *localtime(&t);
off = off2;
printf("%10s %04d-%02d-%02d %02d:%02d:%02d %2d %6ld\n\n", "",
local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,
local.tm_hour, local.tm_min, local.tm_sec, local.tm_isdst ,off);
fflush(stdout);
}
}
puts("Done");
}
v----v Difference in seconds
0 1970-01-01T00:00:00Z
1969-12-31 18:00:00 0 -21600
5731200 1970-03-08T08:00:00Z
1970-03-08 03:00:00 1 -18000
26290800 1970-11-01T07:00:00Z
1970-11-01 01:00:00 0 -21600
...
2109222000 2036-11-02T07:00:00Z
2036-11-02 01:00:00 0 -21600
2120112000 2037-03-08T08:00:00Z
2037-03-08 03:00:00 1 -18000
2140671600 2037-11-01T07:00:00Z
2037-11-01 01:00:00 0 -21600
Done
#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;
}