Example #1
0
File: pgtz.c Project: colinet/sqlix
/*
 * See how well a specific timezone setting matches the system behavior
 *
 * We score a timezone setting according to the number of test times it
 * matches.  (The test times are ordered later-to-earlier, but this routine
 * doesn't actually know that; it just scans until the first non-match.)
 *
 * We return -1 for a completely unusable setting; this is worse than the
 * score of zero for a setting that works but matches not even the first
 * test time.
 */
static int
score_timezone(const char *tzname, struct tztry * tt)
{
	int i;
	pg_time_t pgtt;
	struct tm* systm;
	struct pg_tm* pgtm;
	char cbuf[TZ_STRLEN_MAX + 1];
	pg_tz tz;


	/*
	 * Load timezone directly. Don't use pg_tzset, because we don't want all
	 * timezones loaded in the cache at startup.
	 */
	if (tzload(tzname, NULL, &tz.state, TRUE) != 0) {
		if (tzname[0] == ':' || tzparse(tzname, &tz.state, FALSE) != 0) {
			return -1;			/* can't handle the TZ name at all */
		}
	}

	/* Reject if leap seconds involved */
	if (!tz_acceptable(&tz)) {
		elog(DEBUG4, "Reject TZ \"%s\": uses leap seconds", tzname);
		return -1;
	}

	/* Check for match at all the test times */
	for (i = 0; i < tt->n_test_times; i++) {
		pgtt = (pg_time_t) (tt->test_times[i]);
		pgtm = pg_localtime(&pgtt, &tz);
		if (!pgtm)
			return -1;			/* probably shouldn't happen */

		systm = localtime(&(tt->test_times[i]));
		if (!systm) {
			elog(DEBUG4,
				"TZ \"%s\" scores %d:"
				" at %ld %04d-%02d-%02d %02d:%02d:%02d %s, system had no data",
				tzname, i, (long) pgtt,
				pgtm->tm_year + 1900, pgtm->tm_mon + 1, pgtm->tm_mday,
				pgtm->tm_hour, pgtm->tm_min, pgtm->tm_sec,
				pgtm->tm_isdst ? "dst" : "std");
			return i;
		}

		if (!compare_tm(systm, pgtm)) {
			elog(DEBUG4,
				"TZ \"%s\" scores %d:"
				" at %ld %04d-%02d-%02d %02d:%02d:%02d %s"
				" versus %04d-%02d-%02d %02d:%02d:%02d %s",
				tzname, i, (long) pgtt,
				pgtm->tm_year + 1900, pgtm->tm_mon + 1, pgtm->tm_mday,
				pgtm->tm_hour, pgtm->tm_min, pgtm->tm_sec,
				pgtm->tm_isdst ? "dst" : "std",
				systm->tm_year + 1900, systm->tm_mon + 1, systm->tm_mday,
				systm->tm_hour, systm->tm_min, systm->tm_sec,
				systm->tm_isdst ? "dst" : "std");
			return i;
		}

		if (systm->tm_isdst >= 0) {
			/* Check match of zone names, too */
			if (pgtm->tm_zone == NULL)
				return -1;		/* probably shouldn't happen */

			memset(cbuf, 0, sizeof(cbuf));
			strftime(cbuf, sizeof(cbuf) - 1, "%Z", systm);		/* zone abbr */
			if (strcmp(cbuf, pgtm->tm_zone) != 0) {
				elog(DEBUG4, "TZ \"%s\" scores %d: at %ld \"%s\" versus \"%s\"",
					tzname, i, (long) pgtt,
					pgtm->tm_zone, cbuf);
				return i;
			}
		}
	}

	elog(DEBUG4, "TZ \"%s\" gets max score %d", tzname, i);
	return i;
}
Example #2
0
/*
 * See how well a specific timezone setting matches the system behavior
 *
 * We score a timezone setting according to the number of test times it
 * matches.  (The test times are ordered later-to-earlier, but this routine
 * doesn't actually know that; it just scans until the first non-match.)
 *
 * We return -1 for a completely unusable setting; this is worse than the
 * score of zero for a setting that works but matches not even the first
 * test time.
 */
static int
score_timezone(const char *tzname, struct tztry *tt)
{
	int			i;
	pg_time_t	pgtt;
	struct tm  *systm;
	struct pg_tm *pgtm;
	char		cbuf[TZ_STRLEN_MAX + 1];
	pg_tz	   *tz;

	/* Load timezone definition */
	tz = pg_load_tz(tzname);
	if (!tz)
		return -1;				/* unrecognized zone name */

	/* Reject if leap seconds involved */
	if (!pg_tz_acceptable(tz))
	{
#ifdef DEBUG_IDENTIFY_TIMEZONE
		fprintf(stderr, "Reject TZ \"%s\": uses leap seconds\n", tzname);
#endif
		return -1;
	}

	/* Check for match at all the test times */
	for (i = 0; i < tt->n_test_times; i++)
	{
		pgtt = (pg_time_t) (tt->test_times[i]);
		pgtm = pg_localtime(&pgtt, tz);
		if (!pgtm)
			return -1;			/* probably shouldn't happen */
		systm = localtime(&(tt->test_times[i]));
		if (!systm)
		{
#ifdef DEBUG_IDENTIFY_TIMEZONE
			fprintf(stderr, "TZ \"%s\" scores %d: at %ld %04d-%02d-%02d %02d:%02d:%02d %s, system had no data\n",
					tzname, i, (long) pgtt,
					pgtm->tm_year + 1900, pgtm->tm_mon + 1, pgtm->tm_mday,
					pgtm->tm_hour, pgtm->tm_min, pgtm->tm_sec,
					pgtm->tm_isdst ? "dst" : "std");
#endif
			return i;
		}
		if (!compare_tm(systm, pgtm))
		{
#ifdef DEBUG_IDENTIFY_TIMEZONE
			fprintf(stderr, "TZ \"%s\" scores %d: at %ld %04d-%02d-%02d %02d:%02d:%02d %s versus %04d-%02d-%02d %02d:%02d:%02d %s\n",
					tzname, i, (long) pgtt,
					pgtm->tm_year + 1900, pgtm->tm_mon + 1, pgtm->tm_mday,
					pgtm->tm_hour, pgtm->tm_min, pgtm->tm_sec,
					pgtm->tm_isdst ? "dst" : "std",
					systm->tm_year + 1900, systm->tm_mon + 1, systm->tm_mday,
					systm->tm_hour, systm->tm_min, systm->tm_sec,
					systm->tm_isdst ? "dst" : "std");
#endif
			return i;
		}
		if (systm->tm_isdst >= 0)
		{
			/* Check match of zone names, too */
			if (pgtm->tm_zone == NULL)
				return -1;		/* probably shouldn't happen */
			memset(cbuf, 0, sizeof(cbuf));
			strftime(cbuf, sizeof(cbuf) - 1, "%Z", systm);	/* zone abbr */
			if (strcmp(cbuf, pgtm->tm_zone) != 0)
			{
#ifdef DEBUG_IDENTIFY_TIMEZONE
				fprintf(stderr, "TZ \"%s\" scores %d: at %ld \"%s\" versus \"%s\"\n",
						tzname, i, (long) pgtt,
						pgtm->tm_zone, cbuf);
#endif
				return i;
			}
		}
	}

#ifdef DEBUG_IDENTIFY_TIMEZONE
	fprintf(stderr, "TZ \"%s\" gets max score %d\n", tzname, i);
#endif

	return i;
}