一、相关内容
Glibc中存储时间转换信息的有:tzname、timezone、daylight三个全局变量,声明在time.h中。
Glibc中关于时区设置的函数有:tzset(),声明在time.h中。此函数由依赖于时区的其他时间转换函数(mktime、localtime、ctime)自动调用。
tzset()主要用于设置时间变量,它通过获取TZ环境变量初始化tzname变量,在类
System-V系统中,它同时设置timezone(相对UTC以西的秒数,向西为正,向东为负)和daylight变量。如果环境没有配置TZ,则使用系统时区(系统时区是通过将/etc/localtime链接到tzfile格式文件配置);如果环境中配置了TZ,但其值为空或无法解析则使用协调世界时(UTC)。
具体相关信息可通过man tzset查看。
二、环境变量TZ和TZDIR
TZ:如果设置了此变量,则其值优先于系统配置的时区。
TZDIR:如果设置了此变量,则其值优先于系统配置的时区数据库目录路径。
三、时区格式及设置
时区环境变量TZ共有两种格式:一种直接使用包含时区的字符串,另一种指定从相应文件中读取时区信息,具体如下:
1. 格式一
TZ=std offset[dst[offset][,start[/time],end[/time]]]
std:表示时区缩写(详情),比如CST。经测试可任意值,但必须至少3个字母,否则会不生效。
offset:表示当地时间和UTC时间的偏移。如果当地时区在本初子午线以西,偏移量为正;如果当地时区在东边,偏移量为负。
dst[offset]:指定夏令时时区名称及偏移时间,格式为[+|-]hh[:mm[:ss]],跟std offset类似,若省略偏移量,则默认为比标准时间提前一小时。
start[/time],end[/time]:指定夏令时生效及结束时间。start和end有如下几种格式:
1)Jn:n表示从1到365的儒略日。闰年不考虑在内,所以2月28日,n为59;3月1日,n为60。
2)n:n表示从0到365的儒略日,包含闰年的2月29日。
3)Mm.w.d:
m:指一年中的第几月(1 <= m <= 12)。
w:指一个月中的第几周(1 <= w <= 5),1表示第一周,5表示最后一周。
d:指一周中的第几天(0 <= d <= 6),0表示星期天。
time:该字段表示本地时间对夏时制生效或结束的时间,如果省略默认为02:00:00。
示例:
TZ="NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0"
说明:
NZST,表示新西兰标准时间;-12:00:00表示比UTC早12小时;NZDT,表示新西兰夏时制时间;-13:00:00,表示夏时制时间比UTC早13小时(即比标准时间快1小时);M10.1.0,M3.3.0表示夏令时从10月第一个星期日02:00:00开始到3月第三个星期日02:00:00结束。
2. 格式二
TZ=:[filespec]
filespec:指定获取时区的文件,省略或无效则使用协调世界时(UTC)。如果filespec路径不是以’/’开头(绝对路径),则在系统时区目录(/usr/share/zoneinfo/)下查找对应文件。
3个相关路径:
/etc/localtime:系统时区文件,一般链接到具体某个时区文件。
/usr/share/zoneinfo/:系统时区数据库目录。
/usr/share/zoneinfo/posixrules:当TZ变量包含DST时区但没有开始和结束时间时,则使用该文件规则进行解析。
以上是当前的标准文件位置,但是在编译glibc(tzfile.h)时可以配置它们。
示例:
TZ=":Pacific/Auckland"
说明:
指定在系统时区数据库目录(/usr/share/zoneinfo/)下查找Pacific/Auckland文件,作为获取时区信息文件。
四、代码示例
环境变量TZ,在代码中可以通过setenv或putenv设置,但只针对本进程有效。示例如下:
#include
#include
#include
int main(int argc, const char *argv[])
{
time_t now;
time(&now);
printf("UTC now time:%s\n", asctime(gmtime(&now)));
setenv("TZ", "NZST-12:00:00", 1);
printf("NZST now time(not consider DST):%s\n", ctime(&now));
setenv("TZ", ":Pacific/Auckland", 1);
printf("NZST now time:%s\n", ctime(&now));
setenv("TZ", "NZST-12:00:00NZDT-13:00:00,M10.1.0,M3.3.0", 1);
printf("NZDT now time:%s\n", ctime(&now));
return 0;
}
运行结果: