This is the 22nd day of my participation in the August Wen Challenge.More challenges in August

I’ve learned about time zones in Linux. Make small notes, including the code.

Name of time zone

If daylight saving time (DST) is not used, the name of the time zone is stdoffset. The name of the time zone plus the time offset. A positive time offset indicates the west zone and a negative time offset indicates the east zone. If our country uses “CST-8”, namely east eight area. The Linux directory /usr/share/zoneinfo/ stores time zone information files for different countries and regions. On an embedded device, if space is limited, you can simplify some information, for example, use files in the /usr/share/zoneinfo/Etc/ directory. Note that the files in this directory are in GMT** form. GMT+8 refers to GMT+8, which means the GMT time plus 8 hours. However, if the time zone is set to GMT+8, the system time differs from the actual time by 16 hours.

Code snippets

1. Get time zone:

One way to do this is to use date +%z to get the time zone offset in hours, positive or negative. This value is considered normal, meaning that a positive number represents the actual number of hours more than GMT. Use date +%Z to get the time zone name. The code is as follows:

Int get_timezone(int* timezone) {const char* date_cmd = "date +%z"; FILE *fp = NULL; char timezone_info[16] = {0}; int tmp_time_zone = 0; fp = popen(date_cmd, "r"); if (fp == NULL) { return -1; } fread(timezone_info, sizeof(timezone_info), 1, fp); pclose(fp); timezone_info[strlen(timezone_info) - 1] = '\0'; if (isdigit(timezone_info[1]) && isdigit(timezone_info[2])) { tmp_time_zone = (timezone_info[1] - '0') * 10 + (timezone_info[2] - '0'); if (timezone_info[0] == '-') { tmp_time_zone = - tmp_time_zone; } *timezone = tmp_time_zone; return 0; } else { *timezone = 0; return -1; } return 0; }Copy the code

Another way is to use the global variable timezone, which stores the time in seconds. Negative numbers represent the eastern regions. The implementation code is as follows:

int get_timezone(int* timezone) { extern long timezone; // The time zone, in seconds, such as GMT-8, is -28800 seconds tzset(); *tz = -(int)(timezone / 3600); // Return 0; }Copy the code

The get_timezone function returns positive and negative values that are converted for easy calculation. For example, ONVIF sets only UTC time, not local time, so add the UTC time to the time zone value returned by the function to calculate the local time. In addition to timezone, there are two global variables tzname and daylight. Example code for their use is as follows:

/** * @brief Obtain the time zone name and time offset ** @param tz1[OUT] Time name 0 * @param tz2[OUT] Time name 1 * @param tz_seconds[OUT] Time offset, in seconds, for example, east 8. The difference from the GMT is -28800 seconds * @param daylight_saving[OUT] If the DAYLIGHT saving time is 0, this parameter is used. If the daylight saving time is not 0, this parameter is used. Success -1: failed * @note Use the east 8 zone test, daylight_saving is 1, do not know whether the test is normal: PST8PDT time zone rm/etc/localtime ln -s/usr/share/zoneinfo PST8PDT/etc/localtime tzname [0] : PST tzname [1] : PDT timezone: */ void get_tz_name(char* tz1, char* tz2, long* tz_seconds, int* daylight_saving) { extern char *tzname[2]; extern long timezone; // extern int daylight; // extern int daylight; tzset(); Strcpy (tz1, tzname[0]) must be executed; strcpy(tz2, tzname[1]); *tz_seconds = timezone; *daylight_saving = daylight; }Copy the code

Time zone name and time zone value conversion:

The time zone name used by ONVIF is posiX standard, but you need to know from that which time zone to correspond to the GMT** form. The conversion code is as follows:

/** * @brief The time zone name is converted to the value of the time zone. ** @param tzname[IN] The time zone name is posiX standard. For example, GMT+8 is set to GMT+8. 1024 success: The time zone value returned here is for program convenience. For example, 8 is returned to indicate east 8 time (different from the above time zone name), * so the GMT plus 8 hours is the local time. */ int convert_tzname2tz(const char* tzname) {#define IS_TZ(foo) (! strncmp(tzname, foo, strlen(foo))) // "GMTxxx" first: GMT0/GMT+0/GMT-0 GMT-8 GMT-08 // CST if (IS_TZ("GMT") || IS_TZ("CST")) { char *endptr; long val = strtol(&tzname[3], &endptr, 10); if (val >= -12 && val <= 12) return -val; else return 1024; } else if (IS_TZ("IDLW")) { return -12; } else if (IS_TZ("NT")||IS_TZ("NUT")||IS_TZ("SST")) { return -11; } else if (IS_TZ("AHST") || IS_TZ("CAT")||IS_TZ("HST")||IS_TZ("HDT")||IS_TZ("TAHT")) { return -10; } else if (IS_TZ("YST")||IS_TZ("YDT")||IS_TZ("GAMT")) { return -9; } else if (IS_TZ("PST")||IS_TZ("PDT")) { return -8; } else if (IS_TZ("MST")||IS_TZ("MDT")) { return -7; } else if (IS_TZ("CDT")) { return -6; } else if (IS_TZ("EST")||IS_TZ("EDT")||IS_TZ("EAST")) { return -5; } else if (IS_TZ("AST")||IS_TZ("ADT")||IS_TZ("GYT")||IS_TZ("WART")) { return -4; } else if (IS_TZ("CLT")||IS_TZ("BRT")||IS_TZ("PMST")||IS_TZ("WGT")) { return -3; } else if (IS_TZ("AT")||IS_TZ("GST")) { return -2; } else if (IS_TZ("WAT")) { return -1; } else if (IS_TZ("Zulu")||IS_TZ("UT")||IS_TZ("UTC")||IS_TZ("UCT")|| IS_TZ("Greenwich")||IS_TZ("BST")) { return 0; } else if (IS_TZ("CET")||IS_TZ("FWT")||IS_TZ("MET")||IS_TZ("MEWT") ||IS_TZ("SWT")||IS_TZ("MEST")||IS_TZ("MESZ")||IS_TZ("SST") ||IS_TZ("FST")) { return 1; } else if (IS_TZ("EET")||IS_TZ("IST")) { return 2; } else if (IS_TZ("BT")||IS_TZ("MSK")) { return 3; } else if (IS_TZ("ZP4")) { return 4; } else if (IS_TZ("ZP5")) { return 5; } else if (IS_TZ("ZP6")) { return 6; } else if (IS_TZ("ZP7")) { return 7; } else if (IS_TZ("WAST")||IS_TZ("HKT")||IS_TZ("SGT")) { return 8; } else if (IS_TZ("JST")) { return 9; } else if (IS_TZ("ACT")) { return 10; } else if (IS_TZ("EAST")) { return 11; } else if (IS_TZ("IDLE")) { return 12; } else { return 1024; } return 1024; }Copy the code

Examples of code for converting a time zone value to a time zone name:

/* g_tz_name indicates the time zone name. Check the file in the /usr/share/zoneinfo /etc/directory. A positive number indicates that the time zone is west of the prime meridian, and a negative number indicates that the time zone is east of the prime meridian. If you do not understand the document, run man tzset in Linux to read the document. */ const char* g_tz_name[25] = { "GMT+12", "GMT+11", "GMT+10", "GMT+9", "GMT+8", "GMT+7", "GMT+6", "GMT+5", "GMT+4", "GMT+3", "GMT+2", "GMT+1", "GMT", "GMT-1", "GMT-2", "GMT-3", "GMT-4", "GMT-5", "GMT-6", "GMT-7", "GMT-8", "GMT-9", "GMT-10", "GMT-11", "GMT-12", }; /** * @brief return timezone name ** @param timezone[IN] timezone value, such as +8, * * @return timezone name */ const char* get_timezone_info(int timezone) {return g_tz_name[timezone + 12]; }Copy the code