在C中,有任何API将time()
函数返回的时间转换为特定的时区吗?有一个功能strftime()
可以转换为系统的当前时区.但我想要的是函数输入是时间(返回time()
)和timeZone,它将以所述时区格式转换特定的格式化时间.
有这样的API吗?
POSIX指定tzset()
:
该
tzset()
功能必须使用环境变量TZ的值来设置由所用时间转换信息ctime
,localtime
,mktime
,和strftime
.如果环境中不存在TZ,则应使用实现定义的默认时区信息.
所以,理论上你可以使用这样的东西将t0
(a time_t
)转换成美国/东部时间,而不是你的默认TZ:
char old_tz[64];
strcpy(old_tz, getenv("TZ"));
setenv("TZ", "EST5", 1);
tzset();
struct tm *lt = localtime(&t0);
char buffer[64];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", lt);
setenv("TZ", old_tz, 1);
tzset();
Run Code Online (Sandbox Code Playgroud)
这样可以保留旧时区的副本(当您使用这些东西时,不能依赖它不会更改或超出范围),然后在环境中设置目标时区.然后它告诉系统查看$ TZ并相应地设置本地时区.然后,将给定time_t
值转换为分解的本地时间localtime()
,格式化字符串,然后重置TZ环境变量并告诉系统再次查看它tzset()
.
在实践中,这可能会也可能不会起作用; 这取决于系统.
如果你需要这些东西的线程安全版本,你将不得不更加努力.这绝对不是编写的线程安全的.
示例代码在错误检查方面有所减少 - 它没有任何错误检查.
我永远不会声称这是一种简单的方法; 应该有更好的方法.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
static void time_convert(time_t t0, char const *tz_value)
{
char old_tz[64];
strcpy(old_tz, getenv("TZ"));
setenv("TZ", tz_value, 1);
tzset();
char new_tz[64];
strcpy(new_tz, getenv("TZ"));
char buffer[64];
struct tm *lt = localtime(&t0);
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", lt);
setenv("TZ", old_tz, 1);
tzset();
printf("%ld = %s (TZ=%s)\n", (long)t0, buffer, new_tz);
}
int main(void)
{
time_t t0 = time(0);
char *tz = getenv("TZ");
time_convert(t0, tz);
time_convert(t0, "UTC0");
time_convert(t0, "IST-5:30");
time_convert(t0, "EST5");
time_convert(t0, "EST5EDT");
time_convert(t0, "PST8");
time_convert(t0, "PST8PDT");
}
Run Code Online (Sandbox Code Playgroud)
1335761328 = 2012-04-29 23:48:48 (TZ=CST6CDT)
1335761328 = 2012-04-30 04:48:48 (TZ=UTC0)
1335761328 = 2012-04-30 10:18:48 (TZ=IST-5:30)
1335761328 = 2012-04-29 23:48:48 (TZ=EST5)
1335761328 = 2012-04-30 00:48:48 (TZ=EST5EDT)
1335761328 = 2012-04-29 20:48:48 (TZ=PST8)
1335761328 = 2012-04-29 21:48:48 (TZ=PST8PDT)
Run Code Online (Sandbox Code Playgroud)
请注意,当EST和PST的字符串没有指定夏令时代码时,您将获得一个时区偏移量; 如果设置了夏令时代码(例如"EST5EDT"
或"PST8PDT"
)并且打印时间是在一年中的适当时间(例如4月底),则会打印出EDT或PDT时间值.
另请注意,有关如何处理时区的ISO标准存在冲突.ISO 8601(日期/时间格式)表示UTC(格林威治)以东的时区为正,而UTC以西的时区为负.至少一些其他标准(例如SQL,ISO 9075)使用相同的表示法.另一方面,POSIX(又名ISO 9945)在TZ中使用相反的约定,如示例代码所示.只有长期存在的先例才能接受冲突.C标准没有提及TZ环境变量的格式(或存在)(尽管C99§7.23.3.5 该strftime
函数多次引用ISO 8601).
而且(正如有用的提醒,为什么错误检查是一个好主意),在Mac OS X 10.7.3上,我的环境没有设置TZ(但它通常是美国/太平洋,又名Cupertino,又名America/Los_Angeles , 时间).所以上面的代码在getenv()
返回空指针时崩溃.我TZ=CST6CDT
在环境中运行它,正如您从第一行输出中看到的那样.
这里确实需要看三个步骤。首先,atime_t
代表绝对时间戳——至少在概念上类似于 UTC 时间戳。它(通常)不位于任何特定时区——它通常表示自某个纪元(通常是 1970 年 1 月 1 日午夜)以来的秒数。
您可以将其转换为struct tm
,这会将时间戳分解为实际的日期和时间 - 年、月、日、小时、分钟和秒。有两个函数可以执行此转换:gmtime
,将其保留为 UTC 样式时间(即格林威治时区)。另一个是localtime
,它将其转换为环境已配置为代表机器位置的任何时区。
下一步是将strftime
其转换为可读的内容。这是基于当前的语言环境,所以(例如)当我写这篇文章时,我认为它是“星期日”。但是,如果我的计算机配置为西班牙语,则可能会显示为“Domingo”或该顺序上的其他内容。
你确实有两个截然不同的问题。您只能将 a 转换time_t
为两个时区之一的时间:“本地”时区(至少,无论机器已配置为“本地”时区)或格林威治时间。如果您想要任何其他时区,您几乎会遇到诸如转换为 GM 时间,然后调整到您选择的时区之类的问题。
还有更多调整格式的规定。默认情况下,该库将始终转换为“C”语言环境,这几乎是美国英语的简化版本。您还可以设置无名区域设置(“”),它为您提供一个与计算机配置方式相匹配的区域设置。作为第三种选择,大多数图书馆都会让您指定特定区域设置的名称,因此,如果您希望日期格式按照加拿大法语区的某人的预期,则可以将区域设置设置为“French_Canada”之类的内容这就是你会得到的(尽管你使用的字符串因标准库而异,所以你可能需要使用“fr-can”之类的东西)。
归档时间: |
|
查看次数: |
3676 次 |
最近记录: |