是否有预定义的方法可以将小时和分钟添加到通过gmtime
获得的time.h
?我想写一个程序来显示各个国家的时间,所以我必须自己写逻辑还是有预定义的方法?
2 回答
如果您有时区名称(如Europe/Helsinki
orUS/Eastern
或MST
),则有一个非常简单的 POSIX 界面。
它确实为整个进程应用了时区,因此如果您使用线程,则需要包装您的日期/时间函数以避免并发日期/时间访问,除非它们使用相同的时区,例如使用互斥锁。此处显示的示例不是线程安全的,以使示例更易于理解。
首先,将环境变量设置为TZ
以冒号为前缀的时区名称。这是 POSIX 系统中用于为单个进程设置时区的方法(并影响进程中的所有线程)。例如,
setenv("TZ", ":Europe/Helsinki", 1);
设置赫尔辛基时区。详情请参阅man 3 setenv
。仅此还不够;您还必须通过调用来告诉 C 库更新当前时区
tzset();
然后,您可以检查全局变量tzname[0]
(应包含Europe
)和tzname[1]
(应包含Helsinki
)以查看实际设置的时区。详情请参阅man 3 timezone
;例如,您可以使用 POSIX 时区定义语法来指定自定义时区。
在上述两行之后,无论何时使用localtime()
或localtime_r()
,都会应用选定的时区。就这么容易。
如果您还希望更改时间戳的格式以符合特定的语言环境,您可以通过以下方式设置语言环境(例如,to fi_FI.utf8
)
setlocale(LC_TIME, "fi_FI.utf8");
请注意,正如man 3 setlocale
手册页所说,语言环境必须采用规范格式,短格式之类的fi
将不起作用。然后,使用例如
time_t now_time;
struct tm *now_tm;
char *format;
char buffer[256];
size_t length;
time(&now_time);
now_tm = localtime(&now_time);
if (!now_tm) {
/* Error, cannot get local time corresponding to now_time! */
return -1;
}
format = nl_langinfo(D_T_FMT);
if (!format || !*format) {
/* Error, cannot get date-time formatting string for this locale */
return -1;
}
/* Note: both now_tm and format point to static buffers,
* and they will be overwritten by subsequent calls.
*/
length = strftime(buffer, sizeof buffer, format, now_tm);
if (length < 1 || length >= sizeof buffer) {
/* Error in locale configuration; cannot generate date-time string. */
return -1;
}
此时buffer
包含芬兰语(或上次setlocale(LC_TIME, locale)
通话中设置的任何语言环境)、芬兰时区(或上次setenv("TZ", ":Europe/Helsinki", 1); tzset();
通话中设置的任何时区)的日期和时间。
(最后的length
检查向后兼容一些非常旧的系统,sizeof buffer
如果缓冲区太小,则返回。较新的系统在缓冲区足够大时返回,但我希望 256 字节足以满足任何时间和日期语。)
我想指出这一点,因为在类似 POSIX 的系统中,语言环境(语言和格式)和时区是完全分开的。
没有标准化的功能可以完成必要的工作。但是,您可以通过修改struct tm
. 该结构包含许多成员;一个小时,一个分钟等。一旦您更新了结构的成员,您应该调用mktime
以规范化值。
例如,如果分钟已设置为 55,而您添加 10,则它们将设置为 65。呼叫mktime
会将分钟设置为 5,并相应地更新小时和可能的其他成员。
例如,添加十分钟如下所示:
struct tm *t = ...
t->tm_min += 10;
mktime(t);