GNU date
命令的信息页面包含以下示例:
例如,使用GNU
date
命令你可以回答这个问题 “在纽约几点钟的时候 巴黎时钟显示10月6:30 2004年3月31日?“通过使用日期开始 用`TZ =“Europe / Paris”'如图所示 以下shell脚本:$ export TZ="America/New_York" $ date --date='TZ="Europe/Paris" 2004-10-31 06:30' Sun Oct 31 01:30:00 EDT 2004
在这个例子中,' - 日' 操作数以自己的'TZ'开头 设置,所以该操作数的其余部分 按照处理 '欧洲/巴黎'的规则,对待 字符串
2004-10-31 06:30
就像它一样 在巴黎。但是,自从date
命令的输出是 根据整体处理 时区规则,它使用纽约 时间。 (巴黎通常是六个小时 2004年领先于纽约,但这一点 例子是指一个简短的万圣节 差距是五个小时的时期。)
我试图在C语言中以编程方式完成基本相同的事情,而无需调用date
程序数百万次。基本上我正在寻找一种方法,在一个时区中采取任意日期和时间,并将其转换为另一个时区中的等效日期和时间,可以直接转换为UTC转换。我不关心输入和输出时间的格式,只要我可以使用标准函数(strftime
/ strptime
/ mktime
/等)来操作它们。
date
程序似乎使用coreutils
包内部的复杂例程来实现这一点,我正在寻找一种方法,使用标准POSIX / Linux例程或外部库在C中执行此操作。我看了很多zoneinfo看起来很有希望,但我找不到任何有用的库。
答案 0 :(得分:3)
我想出了一个似乎在Linux上使用glibc的解决方案,我不知道这种行为有多便携,任何关于可移植性的评论或更好的方法都会受到欢迎。
convert_time.c(无需检查错误):
#define _XOPEN_SOURCE
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
struct tm mytm = {0};
time_t mytime;
char buf[100];
mytm.tm_isdst = -1;
putenv(argv[1]);
tzset();
strptime(argv[2], "%Y-%m-%d %H:%M", &mytm);
mytime = mktime(&mytm);
putenv(argv[3]);
tzset();
localtime_r(&mytime, &mytm);
strftime(buf, 100, "%a, %d %b %Y %H:%M:%S %z(%Z)", &mytm);
puts(buf);
return 0;
}
第一个参数是源时区(实际上是“TZ = Timezone”传递给putenv),第二个参数是指定格式的时间,最后一个参数是目标时区。我使用的是zoneinfo时区名称,glibc使用zoneinfo数据库支持这些名称。
几个DST测试边案例的结果对应于使用zoneinfo数据库的等效date
命令和this站点的结果:
$ ./convert_time "TZ=America/New_York" "2005-05-31 06:30" "TZ=America/Indiana/Indianapolis"
Tue, 31 May 2005 05:30:00 -0500(EST)
$ ./convert_time "TZ=America/New_York" "2006-05-31 06:30" "TZ=America/Indiana/Indianapolis"
Wed, 31 May 2006 06:30:00 -0400(EDT)
$ ./convert_time "TZ=Europe/Paris" "2004-10-30 06:30" "TZ=America/New_York"
Sat, 30 Oct 2004 00:30:00 -0400(EDT)
$ ./convert_time "TZ=Europe/Paris" "2004-10-31 06:30" "TZ=America/New_York"
Sun, 31 Oct 2004 01:30:00 -0400(EDT)
$ ./convert_time "TZ=Europe/Paris" "2004-11-01 06:30" "TZ=America/New_York"
Mon, 01 Nov 2004 00:30:00 -0500(EST)
答案 1 :(得分:2)
时间:
gmtime
mktime
重新规范化日期计算将类似,但稍微复杂一点。
答案 2 :(得分:0)
我实际上是在寻找你所做的相同答案,这就是我提出的解决方案。 以下示例程序获取本地系统时间并将其转换为您想要的任何时区。
// compile: gcc snippet.c
// usage: ./a.out Europe/Berlin Pacific/Nauru Asia/Hong_Kong Asia/Kabul
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
int main(int argc, char *argv[])
{
char buf[80];
time_t tt = time(NULL);
struct tm tm;
int i;
if (!localtime_r(&tt, &tm)) {
printf("Could not convert time_t to tm struct. %s\n", strerror(errno));
return 1;
}
printf("time_t: %ld\n", tt);
printf("timezone: %ld, %s/%s, daylight:%d\n", timezone, tzname[0], tzname[1], daylight);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z %Z", &tm);
printf("time: %s\n", buf);
for (i = 1; i < argc; ++i) {
printf("\ninput: %s\n", argv[i]);
snprintf(buf, sizeof(buf), "TZ=%s", argv[i]);
putenv(buf);
tzset();
printf("\ttimezone: %ld, %s/%s, daylight:%d\n", timezone, tzname[0], tzname[1], daylight);
if (!localtime_r(&tt, &tm)) {
printf("Could not convert time_t to tm struct. %s\n", strerror(errno));
return 1;
}
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z %Z", &tm);
printf("\ttime: %s\n", buf);
}
return 0;
}