75 strcat(fullname,
"/");
76 strcat(fullname,
name);
78 return open(fullname, O_RDONLY |
PG_BINARY, 0);
101 if (strcmp(
name,
"GMT") == 0)
152 #define T_DAY ((time_t) (60*60*24))
153 #define T_WEEK ((time_t) (60*60*24*7))
154 #define T_MONTH ((time_t) (60*60*24*31))
156 #define MAX_TEST_TIMES (52*100)
168 int *bestscore,
char *bestzonename);
177 #if defined(HAVE_STRUCT_TM_TM_ZONE)
179 #elif defined(HAVE_INT_TIMEZONE)
182 #error No way to determine TZ? Can this happen?
194 memset(&
tm, 0,
sizeof(
tm));
209 if (s->tm_sec != p->
tm_sec ||
251 #ifdef DEBUG_IDENTIFY_TIMEZONE
252 fprintf(stderr,
"Reject TZ \"%s\": uses leap seconds\n", tzname);
267 #ifdef DEBUG_IDENTIFY_TIMEZONE
268 fprintf(stderr,
"TZ \"%s\" scores %d: at %ld %04d-%02d-%02d %02d:%02d:%02d %s, system had no data\n",
269 tzname,
i, (
long) pgtt,
278 #ifdef DEBUG_IDENTIFY_TIMEZONE
279 fprintf(stderr,
"TZ \"%s\" scores %d: at %ld %04d-%02d-%02d %02d:%02d:%02d %s versus %04d-%02d-%02d %02d:%02d:%02d %s\n",
280 tzname,
i, (
long) pgtt,
284 systm->tm_year + 1900, systm->tm_mon + 1, systm->tm_mday,
285 systm->tm_hour, systm->tm_min, systm->tm_sec,
286 systm->tm_isdst ?
"dst" :
"std");
290 if (systm->tm_isdst >= 0)
295 memset(cbuf, 0,
sizeof(cbuf));
296 strftime(cbuf,
sizeof(cbuf) - 1,
"%Z", systm);
297 if (strcmp(cbuf, pgtm->
tm_zone) != 0)
299 #ifdef DEBUG_IDENTIFY_TIMEZONE
300 fprintf(stderr,
"TZ \"%s\" scores %d: at %ld \"%s\" versus \"%s\"\n",
301 tzname,
i, (
long) pgtt,
309 #ifdef DEBUG_IDENTIFY_TIMEZONE
310 fprintf(stderr,
"TZ \"%s\" gets max score %d\n", tzname,
i);
369 tm = localtime(&tnow);
415 &bestscore, resultbuf);
419 if (strcmp(resultbuf,
"Factory") == 0)
432 memset(std_zone_name, 0,
sizeof(std_zone_name));
433 memset(dst_zone_name, 0,
sizeof(dst_zone_name));
442 tnow -= (tnow %
T_DAY);
456 if (
tm->
tm_isdst == 0 && std_zone_name[0] ==
'\0')
459 memset(cbuf, 0,
sizeof(cbuf));
460 strftime(cbuf,
sizeof(cbuf) - 1,
"%Z",
tm);
461 strcpy(std_zone_name, cbuf);
464 if (
tm->
tm_isdst > 0 && dst_zone_name[0] ==
'\0')
467 memset(cbuf, 0,
sizeof(cbuf));
468 strftime(cbuf,
sizeof(cbuf) - 1,
"%Z",
tm);
469 strcpy(dst_zone_name, cbuf);
472 if (std_zone_name[0] && dst_zone_name[0])
477 if (std_zone_name[0] ==
'\0')
479 #ifdef DEBUG_IDENTIFY_TIMEZONE
480 fprintf(stderr,
"could not determine system time zone\n");
486 if (dst_zone_name[0] !=
'\0')
488 snprintf(resultbuf,
sizeof(resultbuf),
"%s%d%s",
489 std_zone_name, -std_ofs / 3600, dst_zone_name);
495 strcpy(resultbuf, std_zone_name);
500 snprintf(resultbuf,
sizeof(resultbuf),
"%s%d",
501 std_zone_name, -std_ofs / 3600);
511 snprintf(resultbuf,
sizeof(resultbuf),
"Etc/GMT%s%d",
512 (-std_ofs > 0) ?
"+" :
"", -std_ofs / 3600);
514 #ifdef DEBUG_IDENTIFY_TIMEZONE
515 fprintf(stderr,
"could not recognize system time zone, using \"%s\"\n",
550 const char *cur_name;
556 len =
readlink(linkname, link_target,
sizeof(link_target));
557 if (len < 0 || len >=
sizeof(link_target))
559 link_target[
len] =
'\0';
561 #ifdef DEBUG_IDENTIFY_TIMEZONE
562 fprintf(stderr,
"symbolic link \"%s\" contains \"%s\"\n",
563 linkname, link_target);
573 cur_name = link_target;
577 cur_name = strchr(cur_name + 1,
'/');
578 if (cur_name == NULL)
584 }
while (*cur_name ==
'/');
591 if (*cur_name && *cur_name !=
'.' &&
596 strcpy(bestzonename, cur_name);
621 if (strcmp(zonename,
"UTC") == 0)
623 if (strcmp(zonename,
"Etc/UTC") == 0)
630 if (strcmp(zonename,
"localtime") == 0 ||
631 strcmp(zonename,
"posixrules") == 0)
658 int *bestscore,
char *bestzonename)
660 int tzdir_orig_len = strlen(tzdir);
668 for (namep = names; *namep; namep++)
680 if (
stat(tzdir, &statbuf) != 0)
682 #ifdef DEBUG_IDENTIFY_TIMEZONE
683 fprintf(stderr,
"could not stat \"%s\": %m\n",
686 tzdir[tzdir_orig_len] =
'\0';
694 bestscore, bestzonename);
701 if (score > *bestscore)
706 else if (score == *bestscore)
714 (strlen(tzdirsub) < strlen(bestzonename) ||
715 (strlen(tzdirsub) == strlen(bestzonename) &&
716 strcmp(tzdirsub, bestzonename) < 0))))
722 tzdir[tzdir_orig_len] =
'\0';
733 const char *pgtzname;
749 "Afghanistan Standard Time",
"Afghanistan Daylight Time",
754 "Alaskan Standard Time",
"Alaskan Daylight Time",
759 "Aleutian Standard Time",
"Aleutian Daylight Time",
764 "Altai Standard Time",
"Altai Daylight Time",
769 "Arab Standard Time",
"Arab Daylight Time",
774 "Arabian Standard Time",
"Arabian Daylight Time",
779 "Arabic Standard Time",
"Arabic Daylight Time",
784 "Argentina Standard Time",
"Argentina Daylight Time",
785 "America/Buenos_Aires"
789 "Armenian Standard Time",
"Armenian Daylight Time",
794 "Astrakhan Standard Time",
"Astrakhan Daylight Time",
799 "Atlantic Standard Time",
"Atlantic Daylight Time",
804 "AUS Central Standard Time",
"AUS Central Daylight Time",
809 "Aus Central W. Standard Time",
"Aus Central W. Daylight Time",
814 "AUS Eastern Standard Time",
"AUS Eastern Daylight Time",
819 "Azerbaijan Standard Time",
"Azerbaijan Daylight Time",
824 "Azores Standard Time",
"Azores Daylight Time",
829 "Bahia Standard Time",
"Bahia Daylight Time",
834 "Bangladesh Standard Time",
"Bangladesh Daylight Time",
839 "Belarus Standard Time",
"Belarus Daylight Time",
844 "Bougainville Standard Time",
"Bougainville Daylight Time",
845 "Pacific/Bougainville"
849 "Cabo Verde Standard Time",
"Cabo Verde Daylight Time",
850 "Atlantic/Cape_Verde"
854 "Canada Central Standard Time",
"Canada Central Daylight Time",
859 "Cape Verde Standard Time",
"Cape Verde Daylight Time",
860 "Atlantic/Cape_Verde"
864 "Caucasus Standard Time",
"Caucasus Daylight Time",
869 "Cen. Australia Standard Time",
"Cen. Australia Daylight Time",
874 "Central America Standard Time",
"Central America Daylight Time",
879 "Central Asia Standard Time",
"Central Asia Daylight Time",
884 "Central Brazilian Standard Time",
"Central Brazilian Daylight Time",
889 "Central Europe Standard Time",
"Central Europe Daylight Time",
894 "Central European Standard Time",
"Central European Daylight Time",
899 "Central Pacific Standard Time",
"Central Pacific Daylight Time",
900 "Pacific/Guadalcanal"
904 "Central Standard Time",
"Central Daylight Time",
909 "Central Standard Time (Mexico)",
"Central Daylight Time (Mexico)",
910 "America/Mexico_City"
914 "Chatham Islands Standard Time",
"Chatham Islands Daylight Time",
919 "China Standard Time",
"China Daylight Time",
924 "Coordinated Universal Time",
"Coordinated Universal Time",
929 "Cuba Standard Time",
"Cuba Daylight Time",
934 "Dateline Standard Time",
"Dateline Daylight Time",
939 "E. Africa Standard Time",
"E. Africa Daylight Time",
944 "E. Australia Standard Time",
"E. Australia Daylight Time",
949 "E. Europe Standard Time",
"E. Europe Daylight Time",
954 "E. South America Standard Time",
"E. South America Daylight Time",
959 "Easter Island Standard Time",
"Easter Island Daylight Time",
964 "Eastern Standard Time",
"Eastern Daylight Time",
969 "Eastern Standard Time (Mexico)",
"Eastern Daylight Time (Mexico)",
974 "Egypt Standard Time",
"Egypt Daylight Time",
979 "Ekaterinburg Standard Time",
"Ekaterinburg Daylight Time",
984 "Fiji Standard Time",
"Fiji Daylight Time",
989 "FLE Standard Time",
"FLE Daylight Time",
994 "Georgian Standard Time",
"Georgian Daylight Time",
999 "GMT Standard Time",
"GMT Daylight Time",
1004 "Greenland Standard Time",
"Greenland Daylight Time",
1016 "Greenwich Standard Time",
"Greenwich Daylight Time",
1017 "Atlantic/Reykjavik"
1021 "GTB Standard Time",
"GTB Daylight Time",
1026 "Haiti Standard Time",
"Haiti Daylight Time",
1027 "America/Port-au-Prince"
1031 "Hawaiian Standard Time",
"Hawaiian Daylight Time",
1036 "India Standard Time",
"India Daylight Time",
1041 "Iran Standard Time",
"Iran Daylight Time",
1046 "Israel Standard Time",
"Israel Daylight Time",
1051 "Jerusalem Standard Time",
"Jerusalem Daylight Time",
1056 "Jordan Standard Time",
"Jordan Daylight Time",
1061 "Kaliningrad Standard Time",
"Kaliningrad Daylight Time",
1062 "Europe/Kaliningrad"
1066 "Kamchatka Standard Time",
"Kamchatka Daylight Time",
1071 "Korea Standard Time",
"Korea Daylight Time",
1076 "Libya Standard Time",
"Libya Daylight Time",
1081 "Line Islands Standard Time",
"Line Islands Daylight Time",
1082 "Pacific/Kiritimati"
1086 "Lord Howe Standard Time",
"Lord Howe Daylight Time",
1087 "Australia/Lord_Howe"
1091 "Magadan Standard Time",
"Magadan Daylight Time",
1096 "Magallanes Standard Time",
"Magallanes Daylight Time",
1097 "America/Punta_Arenas"
1101 "Malay Peninsula Standard Time",
"Malay Peninsula Daylight Time",
1106 "Marquesas Standard Time",
"Marquesas Daylight Time",
1111 "Mauritius Standard Time",
"Mauritius Daylight Time",
1116 "Mexico Standard Time",
"Mexico Daylight Time",
1117 "America/Mexico_City"
1121 "Mexico Standard Time 2",
"Mexico Daylight Time 2",
1126 "Mid-Atlantic Standard Time",
"Mid-Atlantic Daylight Time",
1127 "Atlantic/South_Georgia"
1131 "Middle East Standard Time",
"Middle East Daylight Time",
1136 "Montevideo Standard Time",
"Montevideo Daylight Time",
1137 "America/Montevideo"
1141 "Morocco Standard Time",
"Morocco Daylight Time",
1146 "Mountain Standard Time",
"Mountain Daylight Time",
1151 "Mountain Standard Time (Mexico)",
"Mountain Daylight Time (Mexico)",
1156 "Myanmar Standard Time",
"Myanmar Daylight Time",
1161 "N. Central Asia Standard Time",
"N. Central Asia Daylight Time",
1166 "Namibia Standard Time",
"Namibia Daylight Time",
1171 "Nepal Standard Time",
"Nepal Daylight Time",
1176 "New Zealand Standard Time",
"New Zealand Daylight Time",
1181 "Newfoundland Standard Time",
"Newfoundland Daylight Time",
1186 "Norfolk Standard Time",
"Norfolk Daylight Time",
1191 "North Asia East Standard Time",
"North Asia East Daylight Time",
1196 "North Asia Standard Time",
"North Asia Daylight Time",
1201 "North Korea Standard Time",
"North Korea Daylight Time",
1206 "Novosibirsk Standard Time",
"Novosibirsk Daylight Time",
1211 "Omsk Standard Time",
"Omsk Daylight Time",
1216 "Pacific SA Standard Time",
"Pacific SA Daylight Time",
1221 "Pacific Standard Time",
"Pacific Daylight Time",
1222 "America/Los_Angeles"
1226 "Pacific Standard Time (Mexico)",
"Pacific Daylight Time (Mexico)",
1231 "Pakistan Standard Time",
"Pakistan Daylight Time",
1236 "Paraguay Standard Time",
"Paraguay Daylight Time",
1241 "Qyzylorda Standard Time",
"Qyzylorda Daylight Time",
1246 "Romance Standard Time",
"Romance Daylight Time",
1251 "Russia Time Zone 3",
"Russia Time Zone 3",
1256 "Russia Time Zone 10",
"Russia Time Zone 10",
1257 "Asia/Srednekolymsk"
1261 "Russia Time Zone 11",
"Russia Time Zone 11",
1266 "Russia TZ 1 Standard Time",
"Russia TZ 1 Daylight Time",
1267 "Europe/Kaliningrad"
1271 "Russia TZ 2 Standard Time",
"Russia TZ 2 Daylight Time",
1276 "Russia TZ 3 Standard Time",
"Russia TZ 3 Daylight Time",
1281 "Russia TZ 4 Standard Time",
"Russia TZ 4 Daylight Time",
1282 "Asia/Yekaterinburg"
1286 "Russia TZ 5 Standard Time",
"Russia TZ 5 Daylight Time",
1291 "Russia TZ 6 Standard Time",
"Russia TZ 6 Daylight Time",
1296 "Russia TZ 7 Standard Time",
"Russia TZ 7 Daylight Time",
1301 "Russia TZ 8 Standard Time",
"Russia TZ 8 Daylight Time",
1306 "Russia TZ 9 Standard Time",
"Russia TZ 9 Daylight Time",
1311 "Russia TZ 10 Standard Time",
"Russia TZ 10 Daylight Time",
1316 "Russia TZ 11 Standard Time",
"Russia TZ 11 Daylight Time",
1321 "Russian Standard Time",
"Russian Daylight Time",
1326 "SA Eastern Standard Time",
"SA Eastern Daylight Time",
1331 "SA Pacific Standard Time",
"SA Pacific Daylight Time",
1336 "SA Western Standard Time",
"SA Western Daylight Time",
1341 "Saint Pierre Standard Time",
"Saint Pierre Daylight Time",
1346 "Sakhalin Standard Time",
"Sakhalin Daylight Time",
1351 "Samoa Standard Time",
"Samoa Daylight Time",
1356 "Sao Tome Standard Time",
"Sao Tome Daylight Time",
1361 "Saratov Standard Time",
"Saratov Daylight Time",
1366 "SE Asia Standard Time",
"SE Asia Daylight Time",
1371 "Singapore Standard Time",
"Singapore Daylight Time",
1376 "South Africa Standard Time",
"South Africa Daylight Time",
1377 "Africa/Johannesburg"
1381 "South Sudan Standard Time",
"South Sudan Daylight Time",
1386 "Sri Lanka Standard Time",
"Sri Lanka Daylight Time",
1391 "Sudan Standard Time",
"Sudan Daylight Time",
1396 "Syria Standard Time",
"Syria Daylight Time",
1401 "Taipei Standard Time",
"Taipei Daylight Time",
1406 "Tasmania Standard Time",
"Tasmania Daylight Time",
1411 "Tocantins Standard Time",
"Tocantins Daylight Time",
1416 "Tokyo Standard Time",
"Tokyo Daylight Time",
1421 "Tomsk Standard Time",
"Tomsk Daylight Time",
1426 "Tonga Standard Time",
"Tonga Daylight Time",
1431 "Transbaikal Standard Time",
"Transbaikal Daylight Time",
1436 "Turkey Standard Time",
"Turkey Daylight Time",
1441 "Turks And Caicos Standard Time",
"Turks And Caicos Daylight Time",
1442 "America/Grand_Turk"
1446 "Ulaanbaatar Standard Time",
"Ulaanbaatar Daylight Time",
1451 "US Eastern Standard Time",
"US Eastern Daylight Time",
1452 "America/Indianapolis"
1456 "US Mountain Standard Time",
"US Mountain Daylight Time",
1496 "Venezuela Standard Time",
"Venezuela Daylight Time",
1501 "Vladivostok Standard Time",
"Vladivostok Daylight Time",
1506 "Volgograd Standard Time",
"Volgograd Daylight Time",
1511 "W. Australia Standard Time",
"W. Australia Daylight Time",
1516 "W. Central Africa Standard Time",
"W. Central Africa Daylight Time",
1521 "W. Europe Standard Time",
"W. Europe Daylight Time",
1526 "W. Mongolia Standard Time",
"W. Mongolia Daylight Time",
1531 "West Asia Standard Time",
"West Asia Daylight Time",
1536 "West Bank Gaza Standard Time",
"West Bank Gaza Daylight Time",
1541 "West Bank Standard Time",
"West Bank Daylight Time",
1546 "West Pacific Standard Time",
"West Pacific Daylight Time",
1547 "Pacific/Port_Moresby"
1551 "Yakutsk Standard Time",
"Yakutsk Daylight Time",
1556 "Yukon Standard Time",
"Yukon Daylight Time",
1557 "America/Whitehorse"
1569 char localtzname[256];
1570 time_t t = time(NULL);
1571 struct tm *
tm = localtime(&t);
1577 #ifdef DEBUG_IDENTIFY_TIMEZONE
1578 fprintf(stderr,
"could not identify system time zone: localtime() failed\n");
1583 memset(tzname, 0,
sizeof(tzname));
1584 strftime(tzname,
sizeof(tzname) - 1,
"%Z",
tm);
1586 for (
i = 0; win32_tzmap[
i].stdname != NULL;
i++)
1588 if (strcmp(tzname, win32_tzmap[
i].stdname) == 0 ||
1589 strcmp(tzname, win32_tzmap[
i].dstname) == 0)
1591 #ifdef DEBUG_IDENTIFY_TIMEZONE
1592 fprintf(stderr,
"TZ \"%s\" matches system time zone \"%s\"\n",
1593 win32_tzmap[
i].pgtzname, tzname);
1595 return win32_tzmap[
i].pgtzname;
1604 memset(localtzname, 0,
sizeof(localtzname));
1605 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1606 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
1609 &rootKey) != ERROR_SUCCESS)
1611 #ifdef DEBUG_IDENTIFY_TIMEZONE
1612 fprintf(stderr,
"could not open registry key to identify system time zone: error code %lu\n",
1627 memset(keyname, 0,
sizeof(keyname));
1628 namesize =
sizeof(keyname);
1629 if ((r = RegEnumKeyEx(rootKey,
1636 &lastwrite)) != ERROR_SUCCESS)
1638 if (r == ERROR_NO_MORE_ITEMS)
1640 #ifdef DEBUG_IDENTIFY_TIMEZONE
1641 fprintf(stderr,
"could not enumerate registry subkeys to identify system time zone: %d\n",
1647 if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &
key)) != ERROR_SUCCESS)
1649 #ifdef DEBUG_IDENTIFY_TIMEZONE
1650 fprintf(stderr,
"could not open registry subkey to identify system time zone: %d\n",
1656 memset(zonename, 0,
sizeof(zonename));
1657 namesize =
sizeof(zonename);
1658 if ((r = RegQueryValueEx(
key,
"Std", NULL, NULL, (
unsigned char *) zonename, &namesize)) != ERROR_SUCCESS)
1660 #ifdef DEBUG_IDENTIFY_TIMEZONE
1661 fprintf(stderr,
"could not query value for key \"std\" to identify system time zone \"%s\": %d\n",
1667 if (strcmp(tzname, zonename) == 0)
1670 strcpy(localtzname, keyname);
1674 memset(zonename, 0,
sizeof(zonename));
1675 namesize =
sizeof(zonename);
1676 if ((r = RegQueryValueEx(
key,
"Dlt", NULL, NULL, (
unsigned char *) zonename, &namesize)) != ERROR_SUCCESS)
1678 #ifdef DEBUG_IDENTIFY_TIMEZONE
1679 fprintf(stderr,
"could not query value for key \"dlt\" to identify system time zone \"%s\": %d\n",
1685 if (strcmp(tzname, zonename) == 0)
1688 strcpy(localtzname, keyname);
1696 RegCloseKey(rootKey);
1701 for (
i = 0; win32_tzmap[
i].stdname != NULL;
i++)
1703 if (strcmp(localtzname, win32_tzmap[
i].stdname) == 0 ||
1704 strcmp(localtzname, win32_tzmap[
i].dstname) == 0)
1706 #ifdef DEBUG_IDENTIFY_TIMEZONE
1707 fprintf(stderr,
"TZ \"%s\" matches localized system time zone \"%s\" (\"%s\")\n",
1708 win32_tzmap[
i].pgtzname, tzname, localtzname);
1710 return win32_tzmap[
i].pgtzname;
1715 #ifdef DEBUG_IDENTIFY_TIMEZONE
1716 fprintf(stderr,
"could not find a match for system time zone \"%s\"\n",
1732 if (!tzname || !tzname[0])
1767 tzname = getenv(
"TZ");
Datum idx(PG_FUNCTION_ARGS)
static void scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry *tt, int *bestscore, char *bestzonename)
static pg_tz * pg_load_tz(const char *name)
static bool compare_tm(struct tm *s, struct pg_tm *p)
static int zone_name_pref(const char *zonename)
int pg_open_tzfile(const char *name, char *canonname)
static time_t build_time_t(int year, int month, int day)
static const char * identify_system_timezone(void)
static bool perfect_timezone_match(const char *tzname, struct tztry *tt)
static int get_timezone_offset(struct tm *tm)
static bool validate_zone(const char *tzname)
static int score_timezone(const char *tzname, struct tztry *tt)
static const char * pg_TZDIR(void)
static bool check_system_link_file(const char *linkname, struct tztry *tt, char *bestzonename)
const char * select_default_timezone(const char *share_path)
static char tzdirpath[MAXPGPATH]
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
bool tzparse(const char *name, struct state *sp, bool lastditch)
void pgfnames_cleanup(char **filenames)
char ** pgfnames(const char *path)
bool pg_tz_acceptable(pg_tz *tz)
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
size_t strlcpy(char *dst, const char *src, size_t siz)
char TZname[TZ_STRLEN_MAX+1]
time_t test_times[MAX_TEST_TIMES]
#define readlink(path, buf, size)