6
6
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7
7
*
8
8
* IDENTIFICATION
9
- * $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.59 2008/02/16 21:16:04 tgl Exp $
9
+ * $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.60 2008/07/01 03:40:55 tgl Exp $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
@@ -198,7 +198,7 @@ scan_directory_ci(const char *dirname, const char *fname, int fnamelen,
198
198
#define T_WEEK ((time_t) (60*60*24*7))
199
199
#define T_MONTH ((time_t) (60*60*24*31))
200
200
201
- #define MAX_TEST_TIMES (52*100)/* 100 years, or 1904..2004 */
201
+ #define MAX_TEST_TIMES (52*100)/* 100 years */
202
202
203
203
struct tztry
204
204
{
@@ -367,6 +367,7 @@ identify_system_timezone(void)
367
367
time_t t ;
368
368
struct tztry tt ;
369
369
struct tm * tm ;
370
+ int thisyear ;
370
371
int bestscore ;
371
372
char tmptzdir [MAXPGPATH ];
372
373
int std_ofs ;
@@ -379,11 +380,14 @@ identify_system_timezone(void)
379
380
380
381
/*
381
382
* Set up the list of dates to be probed to see how well our timezone
382
- * matches the system zone. We first probe January and July of 2004; this
383
- * serves to quickly eliminate the vast majority of the TZ database
384
- * entries. If those dates match, we probe every week from 2004 backwards
385
- * to late 1904. (Weekly resolution is good enough to identify DST
386
- * transition rules, since everybody switches on Sundays.)The further
383
+ * matches the system zone. We first probe January and July of the
384
+ * current year; this serves to quickly eliminate the vast majority of the
385
+ * TZ database entries. If those dates match, we probe every week for 100
386
+ * years backwards from the current July. (Weekly resolution is good
387
+ * enough to identify DST transition rules, since everybody switches on
388
+ * Sundays.) This is sufficient to cover most of the Unix time_t range,
389
+ * and we don't want to look further than that since many systems won't
390
+ * have sane TZ behavior further back anyway. The further
387
391
* back the zone matches, the better we score it. This may seem like a
388
392
* rather random way of doing things, but experience has shown that
389
393
* system-supplied timezone definitions are likely to have DST behavior
@@ -393,9 +397,29 @@ identify_system_timezone(void)
393
397
* (Note: we probe Thursdays, not Sundays, to avoid triggering
394
398
* DST-transition bugs in localtime itself.)
395
399
*/
400
+ tnow = time (NULL );
401
+ tm = localtime (& tnow );
402
+ if (!tm )
403
+ return NULL ;/* give up if localtime is broken... */
404
+ thisyear = tm -> tm_year + 1900 ;
405
+
406
+ t = build_time_t (thisyear ,1 ,15 );
407
+ /*
408
+ * Round back to GMT midnight Thursday. This depends on the knowledge
409
+ * that the time_t origin is Thu Jan 01 1970. (With a different origin
410
+ * we'd be probing some other day of the week, but it wouldn't matter
411
+ * anyway unless localtime() had DST-transition bugs.)
412
+ */
413
+ t -= (t %T_WEEK );
414
+
396
415
tt .n_test_times = 0 ;
397
- tt .test_times [tt .n_test_times ++ ]= build_time_t (2004 ,1 ,15 );
398
- tt .test_times [tt .n_test_times ++ ]= t = build_time_t (2004 ,7 ,15 );
416
+ tt .test_times [tt .n_test_times ++ ]= t ;
417
+
418
+ t = build_time_t (thisyear ,7 ,15 );
419
+ t -= (t %T_WEEK );
420
+
421
+ tt .test_times [tt .n_test_times ++ ]= t ;
422
+
399
423
while (tt .n_test_times < MAX_TEST_TIMES )
400
424
{
401
425
t -= T_WEEK ;
@@ -410,7 +434,12 @@ identify_system_timezone(void)
410
434
& tt ,
411
435
& bestscore ,resultbuf );
412
436
if (bestscore > 0 )
437
+ {
438
+ /* Ignore zic's rather silly "Factory" time zone; use GMT instead */
439
+ if (strcmp (resultbuf ,"Factory" )== 0 )
440
+ return NULL ;
413
441
return resultbuf ;
442
+ }
414
443
415
444
/*
416
445
* Couldn't find a match in the database, so next we try constructed zone