在设备应用中,用户需要根据自己的时区设置设备时区。在可交互的系统中或者完整的linux系统中可以通过设置/etc/TZ等时区文件链接的文件来修改设备时区。但是在一些rtos或者不能使用上面设置TZ文件方式的系统中,可以通过设置应用进程的TZ环境变量的方式来设置时区,此时在通过localtime等函数转换的时间就是本地时间了。
效果展示$ make test
./timezone
Europe/London ts 1647169200, date 2022-03-13 11:00:00
America/Anchorage ts 1647169199, date 2022-03-13 01:59:59
America/Anchorage ts 1647169200, date 2022-03-13 03:00:00
Australia/Adelaide ts 1647169200, date 2022-03-13 21:30:00
Europe/London ts 1648917000, date 2022-04-02 17:30:00
America/Anchorage ts 1648917000, date 2022-04-02 08:30:00
Australia/Adelaide ts 1648916999, date 2022-04-03 02:59:59
Australia/Adelaide ts 1648917000, date 2022-04-03 02:00:00
代码展示
citylist.h
#ifndef __CITYLIST_H_
#define __CITYLIST_H_
static const char cityList[][2][128]={
{ "Pacific/Midway", "SST11" },
{ "Pacific/Honolulu", "HST10" },
{ "America/Anchorage", "AKST9AKDT,M3.2.0,M11.1.0" },
{ "America/Los_Angeles", "PST8PDT,M3.2.0,M11.1.0" },
{ "America/Tijuana", "PST8PDT,M3.2.0,M11.1.0" },
{ "America/Phoenix", "MST7" },
{ "America/Chihuahua", "MST7MDT,M4.1.0,M10.5.0" },
{ "America/Denver", "MST7MDT,M3.2.0,M11.1.0" },
{ "America/Costa_Rica", "CST6" },
{ "America/Chicago", "CST6CDT,M3.2.0,M11.1.0" },
{ "America/Mexico_City", "CST6CDT,M4.1.0,M10.5.0" },
{ "America/Regina", "CST6" },
{ "America/Bogota", "<-05>5" },
{ "America/New_York", "EST5EDT,M3.2.0,M11.1.0" },
{ "America/Caracas", "<-04>4" },
{ "America/Barbados", "AST4" },
{ "America/Halifax", "AST4ADT,M3.2.0,M11.1.0" },
{ "America/Manaus", "<-04>4" },
{ "America/Santiago", "" },
{ "America/St_Johns", "NST3:30NDT,M3.2.0,M11.1.0" },
{ "America/Sao_Paulo", "<-03>3" },
{ "America/Argentina/Buenos_Aires", "<-03>3" },
{ "America/Godthab", "" },
{ "America/Montevideo", "<-03>3" },
{ "Atlantic/South_Georgia", "<-02>2" },
{ "Atlantic/Azores", "<-01>1<+00>,M3.5.0/0,M10.5.0/1" },
{ "Atlantic/Cape_Verde", "<-01>1" },
{ "Africa/Casablanca", "<+01>-1" },
{ "Europe/London", "GMT0BST,M3.5.0/1,M10.5.0" },
{ "Europe/Amsterdam", "CET-1CEST,M3.5.0,M10.5.0/3" },
{ "Europe/Belgrade", "CET-1CEST,M3.5.0,M10.5.0/3" },
{ "Europe/Brussels", "CET-1CEST,M3.5.0,M10.5.0/3" },
{ "Europe/Sarajevo", "CET-1CEST,M3.5.0,M10.5.0/3" },
{ "Africa/Windhoek", "CAT-2" },
{ "Africa/Brazzaville", "WAT-1" },
{ "Asia/Amman", "EET-2EEST,M3.5.4/24,M10.5.5/1" },
{ "Europe/Athens", "EET-2EEST,M3.5.0/3,M10.5.0/4" },
{ "Europe/Istanbul", "<+03>-3" },
{ "Asia/Beirut", "EET-2EEST,M3.5.0/0,M10.5.0/0" },
{ "Africa/Cairo", "EET-2" },
{ "Europe/Helsinki", "EET-2EEST,M3.5.0/3,M10.5.0/4" },
{ "Asia/Jerusalem", "" },
{ "Europe/Minsk", "<+03>-3" },
{ "Africa/Harare", "CAT-2" },
{ "Asia/Baghdad", "<+03>-3" },
{ "Europe/Moscow", "MSK-3" },
{ "Asia/Kuwait", "<+03>-3" },
{ "Africa/Nairobi", "EAT-3" },
{ "Asia/Tehran", "<+0330>-3:30<+0430>,J79/24,J263/24" },
{ "Asia/Baku", "<+04>-4" },
{ "Asia/Tbilisi", "<+04>-4" },
{ "Asia/Yerevan", "<+04>-4" },
{ "Asia/Dubai", "<+04>-4" },
{ "Asia/Kabul", "<+0430>-4:30" },
{ "Asia/Karachi", "PKT-5" },
{ "Asia/Oral", "<+05>-5" },
{ "Asia/Yekaterinburg", "<+05>-5" },
{ "Asia/Calcutta", "IST-5:30" },
{ "Asia/Colombo", "<+0530>-5:30" },
{ "Asia/Katmandu", "<+0545>-5:45" },
{ "Asia/Almaty", "<+06>-6" },
{ "Asia/Rangoon", "<+0630>-6:30" },
{ "Asia/Krasnoyarsk", "<+07>-7" },
{ "Asia/Bangkok", "<+07>-7" },
{ "Asia/Jakarta", "WIB-7" },
{ "Asia/Shanghai", "CST-8" },
{ "Asia/Hong_Kong", "HKT-8" },
{ "Asia/Irkutsk", "<+08>-8" },
{ "Asia/Kuala_Lumpur", "<+08>-8" },
{ "Australia/Perth", "AWST-8" },
{ "Asia/Taipei", "CST-8" },
{ "Asia/Seoul", "KST-9" },
{ "Asia/Tokyo", "JST-9" },
{ "Asia/Yakutsk", "<+09>-9" },
{ "Australia/Adelaide", "ACST-9:30ACDT,M10.1.0,M4.1.0/3" },
{ "Australia/Darwin", "ACST-9:30" },
{ "Australia/Brisbane", "AEST-10" },
{ "Australia/Hobart", "AEST-10AEDT,M10.1.0,M4.1.0/3" },
{ "Australia/Sydney", "AEST-10AEDT,M10.1.0,M4.1.0/3" },
{ "Asia/Vladivostok", "<+10>-10" },
{ "Pacific/Guam", "ChST-10" },
{ "Asia/Magadan", "<+11>-11" },
{ "Pacific/Majuro", "<+12>-12" },
{ "Pacific/Auckland", "NZST-12NZDT,M9.5.0,M4.1.0/3" },
{ "Pacific/Fiji", "" },
{ "Pacific/Tongatapu", "<+13>-13" }
};
#endif
main.c
#include
#include
#include
#include
#include "citylist.h"
/**
* @brief 根据设置的地区设置时区
* */
int setTimeZone( const char *pRegion )
{
int ret = 0;
for( int i=0; i<sizeof(cityList)/2/128; i++ ){
/* printf("--->%s,%d,%s\n", pRegion, i, cityList[i][0]); */
if( strcmp( pRegion, cityList[i][0] ) == 0 ){
setenv( "TZ", cityList[i][1], 1 );
break;
}
}
tzset();
return ret;
}
void printTime( const char *pRegion, time_t ts )
{
setTimeZone(pRegion);
struct tm *date = localtime( &ts );
printf("%-20s ts %lu, date %4d-%02d-%02d %02d:%02d:%02d\n", pRegion, ts, date->tm_year+1900, date->tm_mon+1, date->tm_mday, date->tm_hour, date->tm_min, date->tm_sec);
}
int main()
{
time_t ts;
ts = 1647169200;
printTime( "Europe/London", ts );
printTime( "America/Anchorage", ts-1 );
printTime( "America/Anchorage", ts );
printTime( "Australia/Adelaide", ts );
printf("\n\n");
ts = 1648917000;
printTime( "Europe/London", ts );
printTime( "America/Anchorage", ts );
printTime( "Australia/Adelaide", ts-1 );
printTime( "Australia/Adelaide", ts );
return 0;
}
Makefile
taget=timezone
all: $(taget)
$(taget): main.c
gcc -o $@ $^
test: $(taget)
./$(taget)
clean:
rm $(taget)
拓展
其中citylist.h中的城市列表中的环境变量是从linux的时区文件中提取的。
提取环境变量的代码为:
tzif-display.c
#define _GNU_SOURCE
#define _POSIX_C_SOURCE
#include /// For printf, fopen, fclose, FILE
#include /// For malloc, free
#include /// For error
#include /// For errno
#include /// for memset, memcpy, memmem
#include /// for stat
#include /// for setlocale
#include /// for ctime_r, tzset
#define TRUE -1
#define FALSE 0
/***************************************************
* definition of a tzfile header
***************************************************/
#define HEADER_LEN 44
typedef struct {
char magicnumber[6]; // = TZif2 or TZif// char reserved[15]; // nulls
long
unsigned ; ttisgmtcnt// number of UTC/local indicators stored in the file. long
unsigned ; ttisstdcnt// number of standard/wall indicators stored in the file. long
unsigned ; leapcnt// number of leap seconds for which data is stored in the file. long
unsigned ; timecnt// number of "transition times" for which data is stored in the file. long
unsigned ; typecnt// number of "local time types" for which data is stored in the file (must not be zero). long
unsigned ; charcnt// number of characters of "timezone abbreviation strings" stored in the file. }
; timezonefileheader#
defineTZIF1_FIELD_SIZE 4 #
defineTZIF2_FIELD_SIZE 8 /***************************************************
* parse a tzfile "long format" value
***************************************************/
long
parse_tz_long (const char * ,sourceptrconst int ) field_sizelong
{
= retval 0 ;char
* ;long_ptr// if (sizeof(long) < field_size)
// printf("warning: field truncated because it is larger than a 'long' integer\n\n");
int
, i;j=
long_ptr ( char*)& ;retvalif
( (<field_size sizeof (long))&& ( [sourceptr0]8 >> ))for
{
( =isizeof(long)-1;( )i>=field_size;-- i)[ long_ptr]i= 255 ;}
=
j 0 ;for
( =i-field_size1;( 0i>=)&& ( <jsizeof(long));-- i)[
{
long_ptr]j= [ sourceptr]i;++
j;}
return
; retval}
/***************************************************
* read a tzheader file
***************************************************/
int
read_tz_header (* timezonefileheader ,headerconst char * )temp_bufferconst
{
int = field_size 4 ;memcpy
(, header->magicnumber& [temp_buffer0],5 ) ;[
header->magicnumber5]= ';' =parse_tz_long
header->ttisgmtcnt ( &[20temp_buffer],); field_size=parse_tz_long
header->ttisstdcnt ( &[24temp_buffer],); field_size=parse_tz_long
header->leapcnt ( &[28temp_buffer],); field_size=parse_tz_long
header->timecnt ( &[32temp_buffer],); field_size=parse_tz_long
header->typecnt ( &[36temp_buffer],); field_size=parse_tz_long
header->charcnt ( &[40temp_buffer],); field_sizeif(
== 0header->typecnt ) printf(
{
"Error in file format. Zero local time types suggested.\n");return;
} FALSEif
(
== 0header->timecnt ) printf(
{
"No transition times recorded in this file\n");return;
} FALSEreturn
;
} TRUE/***********************************************************************
* tzif2_handle
***********************************************************************/
char
*
tzif2_handle( *, timezonefileheader consttzhchar * , size_ttzfile_buffer_ptr) char buffer_size *
{
; charstart_ptr[
5 magicnumber]="TZif2" ; =memmem
start_ptr ( ,, tzfile_buffer_ptr& buffer_size, 5magicnumber) ; if(
== NULLstart_ptr ) printf(
{
"error finding tzif2 header\n");returnNULL
; }if
(
read_tz_header ( ,( tzhchar *))== start_ptr ) printf FALSE (
{
"Error reading header file version 2\n");returnNULL
; }return
+
; start_ptr } HEADER_LEN/***************************************************
* Display contents of a timezone file
***************************************************/
void
handle_tzfile_data
( char* , consttz,
const timezonefileheader tzhchar
* ,const tzfile_buffer_ptrint
/// 4bytes for tzif1, 8bytes for tzif2 ) field_size /***************************************************
*
* Structure of the timezone files
*
***************************************************/
char
{
*
; charlocal_time_type_ptr*
; charttinfo_read_ptr*
;char tz_abbrev_ptr*
; charleapinfo_ptr*
; charwall_indicator_ptr*
; /********************************************************************
*
* Beginning of code for function display_tzfile_data
*
********************************************************************/local_indicator_ptr=
(
local_time_type_ptr char *)+. tzfile_buffer_ptr * tzh;timecnt=field_size+
ttinfo_read_ptr . local_time_type_ptr ; tzh=timecnt+
tz_abbrev_ptr ( ttinfo_read_ptr . *tzh6typecnt ) ;=+
leapinfo_ptr ( tz_abbrev_ptr . )tzh;charcnt=+
wall_indicator_ptr ( leapinfo_ptr . *tzh*leapcnt2field_size);=+
local_indicator_ptr . wall_indicator_ptr ; tzhifttisstdcnt(
== )field_size char TZIF2_FIELD_SIZE*
{
; =start_line_ptrstrchr
start_line_ptr ( +. local_indicator_ptr , tzh10ttisgmtcnt) ; if(
== NULLstart_line_ptr ) printf(
"\nno \'general rule\' information found at end of file\n");elsechar
*
{
; =end_line_ptrstrchr
end_line_ptr ( +1 start_line_ptr,10) ; if(
== NULLend_line_ptr ) printf(
"\nerror finding \'general rule\' info terminator symbol\n");else*
=
{
';'end_line_ptr /* printf("\ngeneral rule (unparsed): %s\n", start_line_ptr+1 ); */ memcpy(
,
+1 tz, start_line_ptr-); end_line_ptr } start_line_ptr }}
}
#
define
TZ_DIR_LIST
"/usr/share/zoneinfo"int GetTZValFromZoneinfo (
const char*, char *zoneInfo) int =TZ 0
{
; ret * ;char
FILE *tz_file;
char *tzif_buffer_ptr;
int ;start_ptrstruct
stat field_size;
; do file_statuschar
timezonefileheader tzh[
128{
] zoneInfoPath;snprintf(,
sizeof( zoneInfoPath) ,"%s/%s"zoneInfoPath,,); TZ_DIR_LIST= zoneInfo fopen(
tz_file , "rb") zoneInfoPath; if(==
NULL )tz_file error (,
{
0,errno"tz file %s not found\n",);= zoneInfoPath-1
ret ; break;}
if(
fstat
( fileno() ,& tz_file)!= 0file_status) printf ("error retreiving file status\n"
{
);=-1
ret ; break;}
=(
char
tzif_buffer_ptr * )malloc (. ); file_statusifst_size (==
NULL )tzif_buffer_ptr printf ("memory allocation error - tzif buffer\n"
{
);=;break
ret ; errno}
if(
fread
( , ., tzif_buffer_ptr1 file_status,st_size) !=1 tz_file) printf ( "error reading into tzif buffer\n"
{
);free()
;=tzif_buffer_ptr;break
ret ; errno}
fclose(
)
;iftz_file(read_tz_header
( & ,) ==tzh) tzif_buffer_ptr printf ( FALSE "Error reading header file version 1\n"
{
);=-1
ret ; break;}
if(
.
[ 4tzh]magicnumber==50) = tzif2_handle (
{
start_ptr & ,& [tzh] ,tzif_buffer_ptr.HEADER_LEN-) file_status;st_size = HEADER_LEN;}
field_size else TZIF2_FIELD_SIZE=
&
[
{
start_ptr ] ;tzif_buffer_ptr=HEADER_LEN;}
field_size if TZIF1_FIELD_SIZE(
!=
NULL )start_ptr handle_tzfile_data ( , ,, TZ) tzh; start_ptrfree field_size ()
;}tzif_buffer_ptrwhile(
0);return;}
void retmain
(
int ,const char argc* [ ] )argvchar[ 128
{
] tz;/* GetTZValFromZoneinfo( "America/New_York", tz ); */memset(
,
0, tzsizeof () );tzGetTZValFromZoneinfo ([
1] argv,);printf tz ("tz = %s\n"
,);} tz =Cuba
CST5CDT,M3.2.0/0,M11.1.0/1
编译执行:
$ gcc tzif-display.c
$ ./a.out Cuba
tz CST5CDT,M3.2.0/0,M11.1.0/1
如上就可以提取的环境变量为,根据需要提取对应的城市地区的环境变量
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)