PostgreSQL Source Code git master
localtime.c File Reference
#include "c.h"
#include <fcntl.h>
#include "datatype/timestamp.h"
#include "pgtz.h"
#include "private.h"
#include "tzfile.h"
Include dependency graph for localtime.c:

Go to the source code of this file.

Data Structures

struct  rule
 
union  input_buffer
 
union  local_storage
 
struct  local_storage::file_analysis
 

Macros

#define WILDABBR   " "
 
#define TZDEFRULESTRING   ",M3.2.0,M11.1.0"
 

Enumerations

enum  r_type { JULIAN_DAY , DAY_OF_YEAR , MONTH_NTH_DAY_OF_WEEK }
 

Functions

static struct pg_tmgmtsub (pg_time_t const *timep, int_fast32_t offset, struct pg_tm *tmp)
 
static bool increment_overflow (int *ip, int j)
 
static bool increment_overflow_time (pg_time_t *tp, int_fast32_t j)
 
static int_fast64_t leapcorr (struct state const *sp, pg_time_t)
 
static struct pg_tmtimesub (pg_time_t const *timep, int_fast32_t offset, struct state const *sp, struct pg_tm *tmp)
 
static bool typesequiv (struct state const *sp, int a, int b)
 
static void init_ttinfo (struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
 
static int_fast32_t detzcode (const char *const codep)
 
static int_fast64_t detzcode64 (const char *const codep)
 
static bool differ_by_repeat (const pg_time_t t1, const pg_time_t t0)
 
static int tzloadbody (char const *name, char *canonname, struct state *sp, bool doextend, union local_storage *lsp)
 
int tzload (char const *name, char *canonname, struct state *sp, bool doextend)
 
static const char * getzname (const char *strp)
 
static const char * getqzname (const char *strp, const int delim)
 
static const char * getnum (const char *strp, int *const nump, const int min, const int max)
 
static const char * getsecs (const char *strp, int_fast32_t *const secsp)
 
static const char * getoffset (const char *strp, int_fast32_t *const offsetp)
 
static const char * getrule (const char *strp, struct rule *const rulep)
 
static int_fast32_t transtime (const int year, const struct rule *const rulep, const int_fast32_t offset)
 
bool tzparse (const char *name, struct state *sp, bool lastditch)
 
static void gmtload (struct state *const sp)
 
static struct pg_tmlocalsub (struct state const *sp, pg_time_t const *timep, struct pg_tm *const tmp)
 
struct pg_tmpg_localtime (const pg_time_t *timep, const pg_tz *tz)
 
struct pg_tmpg_gmtime (const pg_time_t *timep)
 
static int leaps_thru_end_of_nonneg (int y)
 
static int leaps_thru_end_of (const int y)
 
int pg_next_dst_boundary (const pg_time_t *timep, long int *before_gmtoff, int *before_isdst, pg_time_t *boundary, long int *after_gmtoff, int *after_isdst, const pg_tz *tz)
 
bool pg_interpret_timezone_abbrev (const char *abbrev, const pg_time_t *timep, long int *gmtoff, int *isdst, const pg_tz *tz)
 
bool pg_timezone_abbrev_is_known (const char *abbrev, bool *isfixed, long int *gmtoff, int *isdst, const pg_tz *tz)
 
const char * pg_get_next_timezone_abbrev (int *indx, const pg_tz *tz)
 
bool pg_get_timezone_offset (const pg_tz *tz, long int *gmtoff)
 
const char * pg_get_timezone_name (pg_tz *tz)
 
bool pg_tz_acceptable (pg_tz *tz)
 

Variables

static const char wildabbr [] = WILDABBR
 
static const char gmt [] = "GMT"
 
static struct pg_tm tm
 
static const int mon_lengths [2][MONSPERYEAR]
 
static const int year_lengths [2]
 

Macro Definition Documentation

◆ TZDEFRULESTRING

#define TZDEFRULESTRING   ",M3.2.0,M11.1.0"

Definition at line 61 of file localtime.c.

◆ WILDABBR

#define WILDABBR   " "

Definition at line 48 of file localtime.c.

Enumeration Type Documentation

◆ r_type

enum r_type
Enumerator
JULIAN_DAY 
DAY_OF_YEAR 
MONTH_NTH_DAY_OF_WEEK 

Definition at line 65 of file localtime.c.

66{
67 JULIAN_DAY, /* Jn = Julian day */
68 DAY_OF_YEAR, /* n = day of year */
69 MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
70};
@ JULIAN_DAY
Definition: localtime.c:67
@ MONTH_NTH_DAY_OF_WEEK
Definition: localtime.c:69
@ DAY_OF_YEAR
Definition: localtime.c:68

Function Documentation

◆ detzcode()

static int_fast32_t detzcode ( const char *const  codep)
static

Definition at line 118 of file localtime.c.

119{
120 int_fast32_t result;
121 int i;
122 int_fast32_t one = 1;
123 int_fast32_t halfmaxval = one << (32 - 2);
124 int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
125 int_fast32_t minval = -1 - maxval;
126
127 result = codep[0] & 0x7f;
128 for (i = 1; i < 4; ++i)
129 result = (result << 8) | (codep[i] & 0xff);
130
131 if (codep[0] & 0x80)
132 {
133 /*
134 * Do two's-complement negation even on non-two's-complement machines.
135 * If the result would be minval - 1, return minval.
136 */
137 result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
138 result += minval;
139 }
140 return result;
141}
int i
Definition: isn.c:77
#define TWOS_COMPLEMENT(t)
Definition: private.h:54

References i, and TWOS_COMPLEMENT.

Referenced by tzloadbody().

◆ detzcode64()

static int_fast64_t detzcode64 ( const char *const  codep)
static

Definition at line 144 of file localtime.c.

145{
146 uint_fast64_t result;
147 int i;
148 int_fast64_t one = 1;
149 int_fast64_t halfmaxval = one << (64 - 2);
150 int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
151 int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
152
153 result = codep[0] & 0x7f;
154 for (i = 1; i < 8; ++i)
155 result = (result << 8) | (codep[i] & 0xff);
156
157 if (codep[0] & 0x80)
158 {
159 /*
160 * Do two's-complement negation even on non-two's-complement machines.
161 * If the result would be minval - 1, return minval.
162 */
163 result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
164 result += minval;
165 }
166 return result;
167}

References i, and TWOS_COMPLEMENT.

Referenced by tzloadbody().

◆ differ_by_repeat()

static bool differ_by_repeat ( const pg_time_t  t1,
const pg_time_t  t0 
)
static

Definition at line 170 of file localtime.c.

171{
173 return 0;
174 return t1 - t0 == SECSPERREPEAT;
175}
int64 pg_time_t
Definition: pgtime.h:23
#define SECSPERREPEAT
Definition: private.h:151
#define SECSPERREPEAT_BITS
Definition: private.h:153
#define TYPE_BIT(type)
Definition: private.h:52
#define TYPE_SIGNED(type)
Definition: private.h:53

References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, and TYPE_SIGNED.

Referenced by tzloadbody().

◆ getnum()

static const char * getnum ( const char *  strp,
int *const  nump,
const int  min,
const int  max 
)
static

Definition at line 681 of file localtime.c.

682{
683 char c;
684 int num;
685
686 if (strp == NULL || !is_digit(c = *strp))
687 return NULL;
688 num = 0;
689 do
690 {
691 num = num * 10 + (c - '0');
692 if (num > max)
693 return NULL; /* illegal value */
694 c = *++strp;
695 } while (is_digit(c));
696 if (num < min)
697 return NULL; /* illegal value */
698 *nump = num;
699 return strp;
700}
char * c
#define is_digit(c)
Definition: private.h:45

References is_digit.

Referenced by getrule(), and getsecs().

◆ getoffset()

static const char * getoffset ( const char *  strp,
int_fast32_t *const  offsetp 
)
static

Definition at line 752 of file localtime.c.

753{
754 bool neg = false;
755
756 if (*strp == '-')
757 {
758 neg = true;
759 ++strp;
760 }
761 else if (*strp == '+')
762 ++strp;
763 strp = getsecs(strp, offsetp);
764 if (strp == NULL)
765 return NULL; /* illegal time */
766 if (neg)
767 *offsetp = -*offsetp;
768 return strp;
769}
static const char * getsecs(const char *strp, int_fast32_t *const secsp)
Definition: localtime.c:711

References getsecs().

Referenced by getrule(), and tzparse().

◆ getqzname()

static const char * getqzname ( const char *  strp,
const int  delim 
)
static

Definition at line 664 of file localtime.c.

665{
666 int c;
667
668 while ((c = *strp) != '\0' && c != delim)
669 ++strp;
670 return strp;
671}

Referenced by tzparse().

◆ getrule()

static const char * getrule ( const char *  strp,
struct rule *const  rulep 
)
static

Definition at line 779 of file localtime.c.

780{
781 if (*strp == 'J')
782 {
783 /*
784 * Julian day.
785 */
786 rulep->r_type = JULIAN_DAY;
787 ++strp;
788 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
789 }
790 else if (*strp == 'M')
791 {
792 /*
793 * Month, week, day.
794 */
796 ++strp;
797 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
798 if (strp == NULL)
799 return NULL;
800 if (*strp++ != '.')
801 return NULL;
802 strp = getnum(strp, &rulep->r_week, 1, 5);
803 if (strp == NULL)
804 return NULL;
805 if (*strp++ != '.')
806 return NULL;
807 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
808 }
809 else if (is_digit(*strp))
810 {
811 /*
812 * Day of year.
813 */
814 rulep->r_type = DAY_OF_YEAR;
815 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
816 }
817 else
818 return NULL; /* invalid format */
819 if (strp == NULL)
820 return NULL;
821 if (*strp == '/')
822 {
823 /*
824 * Time specified.
825 */
826 ++strp;
827 strp = getoffset(strp, &rulep->r_time);
828 }
829 else
830 rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
831 return strp;
832}
static const char * getnum(const char *strp, int *const nump, const int min, const int max)
Definition: localtime.c:681
static const char * getoffset(const char *strp, int_fast32_t *const offsetp)
Definition: localtime.c:752
#define SECSPERHOUR
Definition: private.h:99
#define DAYSPERNYEAR
Definition: private.h:97
#define MONSPERYEAR
Definition: private.h:101
#define DAYSPERWEEK
Definition: private.h:96
#define DAYSPERLYEAR
Definition: private.h:98
enum r_type r_type
Definition: localtime.c:74
int r_mon
Definition: localtime.c:77
int r_day
Definition: localtime.c:75
int_fast32_t r_time
Definition: localtime.c:78
int r_week
Definition: localtime.c:76

References DAY_OF_YEAR, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getoffset(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.

Referenced by tzparse().

◆ getsecs()

static const char * getsecs ( const char *  strp,
int_fast32_t *const  secsp 
)
static

Definition at line 711 of file localtime.c.

712{
713 int num;
714
715 /*
716 * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
717 * "M10.4.6/26", which does not conform to Posix, but which specifies the
718 * equivalent of "02:00 on the first Sunday on or after 23 Oct".
719 */
720 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
721 if (strp == NULL)
722 return NULL;
723 *secsp = num * (int_fast32_t) SECSPERHOUR;
724 if (*strp == ':')
725 {
726 ++strp;
727 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
728 if (strp == NULL)
729 return NULL;
730 *secsp += num * SECSPERMIN;
731 if (*strp == ':')
732 {
733 ++strp;
734 /* 'SECSPERMIN' allows for leap seconds. */
735 strp = getnum(strp, &num, 0, SECSPERMIN);
736 if (strp == NULL)
737 return NULL;
738 *secsp += num;
739 }
740 }
741 return strp;
742}
#define SECSPERMIN
Definition: private.h:93
#define HOURSPERDAY
Definition: private.h:95
#define MINSPERHOUR
Definition: private.h:94

References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, SECSPERHOUR, and SECSPERMIN.

Referenced by getoffset().

◆ getzname()

static const char * getzname ( const char *  strp)
static

Definition at line 643 of file localtime.c.

644{
645 char c;
646
647 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
648 c != '+')
649 ++strp;
650 return strp;
651}

References is_digit.

Referenced by tzparse().

◆ gmtload()

static void gmtload ( struct state *const  sp)
static

Definition at line 1246 of file localtime.c.

1247{
1248 if (tzload(gmt, NULL, sp, true) != 0)
1249 tzparse(gmt, sp, true);
1250}
int tzload(char const *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:587
static const char gmt[]
Definition: localtime.c:53
bool tzparse(const char *name, struct state *sp, bool lastditch)
Definition: localtime.c:937

References gmt, tzload(), and tzparse().

Referenced by gmtsub().

◆ gmtsub()

static struct pg_tm * gmtsub ( pg_time_t const *  timep,
int_fast32_t  offset,
struct pg_tm tmp 
)
static

Definition at line 1358 of file localtime.c.

1360{
1361 struct pg_tm *result;
1362
1363 /* GMT timezone state data is kept here */
1364 static struct state *gmtptr = NULL;
1365
1366 if (gmtptr == NULL)
1367 {
1368 /* Allocate on first use */
1369 gmtptr = (struct state *) malloc(sizeof(struct state));
1370 if (gmtptr == NULL)
1371 return NULL; /* errno should be set by malloc */
1372 gmtload(gmtptr);
1373 }
1374
1375 result = timesub(timep, offset, gmtptr, tmp);
1376
1377 /*
1378 * Could get fancy here and deliver something such as "+xx" or "-xx" if
1379 * offset is non-zero, but this is no time for a treasure hunt.
1380 */
1381 if (offset != 0)
1382 tmp->tm_zone = wildabbr;
1383 else
1384 tmp->tm_zone = gmtptr->chars;
1385
1386 return result;
1387}
#define malloc(a)
Definition: header.h:50
static void gmtload(struct state *const sp)
Definition: localtime.c:1246
static struct pg_tm * timesub(pg_time_t const *timep, int_fast32_t offset, struct state const *sp, struct pg_tm *tmp)
Definition: localtime.c:1415
static const char wildabbr[]
Definition: localtime.c:51
Definition: pgtime.h:35
Definition: regguts.h:323
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, 4),(2 *(TZ_STRLEN_MAX+1)))]
Definition: pgtz.h:53
struct state * tmp
Definition: regguts.h:331

References state::chars, gmtload(), malloc, timesub(), state::tmp, and wildabbr.

Referenced by localsub(), and pg_gmtime().

◆ increment_overflow()

static bool increment_overflow ( int *  ip,
int  j 
)
static

Definition at line 1540 of file localtime.c.

1541{
1542 int const i = *ip;
1543
1544 /*----------
1545 * If i >= 0 there can only be overflow if i + j > INT_MAX
1546 * or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1547 * If i < 0 there can only be overflow if i + j < INT_MIN
1548 * or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1549 *----------
1550 */
1551 if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1552 return true;
1553 *ip += j;
1554 return false;
1555}
int j
Definition: isn.c:78

References i, and j.

Referenced by timesub().

◆ increment_overflow_time()

static bool increment_overflow_time ( pg_time_t tp,
int_fast32_t  j 
)
static

Definition at line 1558 of file localtime.c.

1559{
1560 /*----------
1561 * This is like
1562 * 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1563 * except that it does the right thing even if *tp + j would overflow.
1564 *----------
1565 */
1566 if (!(j < 0
1567 ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1568 : *tp <= TIME_T_MAX - j))
1569 return true;
1570 *tp += j;
1571 return false;
1572}
#define TIME_T_MAX
Definition: private.h:69
#define TIME_T_MIN
Definition: private.h:68

References j, TIME_T_MAX, TIME_T_MIN, and TYPE_SIGNED.

Referenced by tzparse().

◆ init_ttinfo()

static void init_ttinfo ( struct ttinfo s,
int_fast32_t  utoff,
bool  isdst,
int  desigidx 
)
static

Definition at line 108 of file localtime.c.

109{
110 s->tt_utoff = utoff;
111 s->tt_isdst = isdst;
113 s->tt_ttisstd = false;
114 s->tt_ttisut = false;
115}
int_fast32_t tt_utoff
Definition: pgtz.h:28
bool tt_ttisstd
Definition: pgtz.h:31
int tt_desigidx
Definition: pgtz.h:30
bool tt_isdst
Definition: pgtz.h:29
bool tt_ttisut
Definition: pgtz.h:32
static unsigned char desigidx[TZ_MAX_TYPES]
Definition: zic.c:401

References desigidx, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_ttisstd, ttinfo::tt_ttisut, and ttinfo::tt_utoff.

Referenced by tzparse().

◆ leapcorr()

static int_fast64_t leapcorr ( struct state const *  sp,
pg_time_t  t 
)
static

Definition at line 1575 of file localtime.c.

1576{
1577 struct lsinfo const *lp;
1578 int i;
1579
1580 i = sp->leapcnt;
1581 while (--i >= 0)
1582 {
1583 lp = &sp->lsis[i];
1584 if (t >= lp->ls_trans)
1585 return lp->ls_corr;
1586 }
1587 return 0;
1588}
Definition: pgtz.h:36
int_fast64_t ls_corr
Definition: pgtz.h:38
pg_time_t ls_trans
Definition: pgtz.h:37

References i, state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, and state::lsis.

Referenced by tzloadbody().

◆ leaps_thru_end_of()

static int leaps_thru_end_of ( const int  y)
static

Definition at line 1407 of file localtime.c.

1408{
1409 return (y < 0
1410 ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1412}
int y
Definition: isn.c:76
static int leaps_thru_end_of_nonneg(int y)
Definition: localtime.c:1401

References leaps_thru_end_of_nonneg(), and y.

Referenced by timesub().

◆ leaps_thru_end_of_nonneg()

static int leaps_thru_end_of_nonneg ( int  y)
static

Definition at line 1401 of file localtime.c.

1402{
1403 return y / 4 - y / 100 + y / 400;
1404}

References y.

Referenced by leaps_thru_end_of().

◆ localsub()

static struct pg_tm * localsub ( struct state const *  sp,
pg_time_t const *  timep,
struct pg_tm *const  tmp 
)
static

Definition at line 1260 of file localtime.c.

1262{
1263 const struct ttinfo *ttisp;
1264 int i;
1265 struct pg_tm *result;
1266 const pg_time_t t = *timep;
1267
1268 if (sp == NULL)
1269 return gmtsub(timep, 0, tmp);
1270 if ((sp->goback && t < sp->ats[0]) ||
1271 (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1272 {
1273 pg_time_t newt = t;
1274 pg_time_t seconds;
1275 pg_time_t years;
1276
1277 if (t < sp->ats[0])
1278 seconds = sp->ats[0] - t;
1279 else
1280 seconds = t - sp->ats[sp->timecnt - 1];
1281 --seconds;
1282 years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
1283 seconds = years * AVGSECSPERYEAR;
1284 if (t < sp->ats[0])
1285 newt += seconds;
1286 else
1287 newt -= seconds;
1288 if (newt < sp->ats[0] ||
1289 newt > sp->ats[sp->timecnt - 1])
1290 return NULL; /* "cannot happen" */
1291 result = localsub(sp, &newt, tmp);
1292 if (result)
1293 {
1294 int_fast64_t newy;
1295
1296 newy = result->tm_year;
1297 if (t < sp->ats[0])
1298 newy -= years;
1299 else
1300 newy += years;
1301 if (!(INT_MIN <= newy && newy <= INT_MAX))
1302 return NULL;
1303 result->tm_year = newy;
1304 }
1305 return result;
1306 }
1307 if (sp->timecnt == 0 || t < sp->ats[0])
1308 {
1309 i = sp->defaulttype;
1310 }
1311 else
1312 {
1313 int lo = 1;
1314 int hi = sp->timecnt;
1315
1316 while (lo < hi)
1317 {
1318 int mid = (lo + hi) >> 1;
1319
1320 if (t < sp->ats[mid])
1321 hi = mid;
1322 else
1323 lo = mid + 1;
1324 }
1325 i = (int) sp->types[lo - 1];
1326 }
1327 ttisp = &sp->ttis[i];
1328
1329 /*
1330 * To get (wrong) behavior that's compatible with System V Release 2.0
1331 * you'd replace the statement below with t += ttisp->tt_utoff;
1332 * timesub(&t, 0L, sp, tmp);
1333 */
1334 result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1335 if (result)
1336 {
1337 result->tm_isdst = ttisp->tt_isdst;
1338 result->tm_zone = unconstify(char *, &sp->chars[ttisp->tt_desigidx]);
1339 }
1340 return result;
1341}
#define unconstify(underlying_type, expr)
Definition: c.h:1233
static struct pg_tm * localsub(struct state const *sp, pg_time_t const *timep, struct pg_tm *const tmp)
Definition: localtime.c:1260
static struct pg_tm * gmtsub(pg_time_t const *timep, int_fast32_t offset, struct pg_tm *tmp)
Definition: localtime.c:1358
#define AVGSECSPERYEAR
Definition: private.h:150
#define YEARSPERREPEAT
Definition: private.h:91
const char * tm_zone
Definition: pgtime.h:46
int tm_isdst
Definition: pgtime.h:44
int tm_year
Definition: pgtime.h:41
Definition: pgtz.h:27

References state::ats, AVGSECSPERYEAR, state::chars, state::defaulttype, gmtsub(), state::goahead, state::goback, i, localsub(), SECSPERREPEAT, state::timecnt, timesub(), pg_tm::tm_isdst, pg_tm::tm_year, pg_tm::tm_zone, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, state::types, unconstify, and YEARSPERREPEAT.

Referenced by localsub(), and pg_localtime().

◆ pg_get_next_timezone_abbrev()

const char * pg_get_next_timezone_abbrev ( int *  indx,
const pg_tz tz 
)

Definition at line 1937 of file localtime.c.

1939{
1940 const char *result;
1941 const struct state *sp = &tz->state;
1942 const char *abbrs;
1943 int abbrind;
1944
1945 /* If we're still in range, the result is the current abbrev. */
1946 abbrs = sp->chars;
1947 abbrind = *indx;
1948 if (abbrind < 0 || abbrind >= sp->charcnt)
1949 return NULL;
1950 result = abbrs + abbrind;
1951
1952 /* Advance *indx past this abbrev and its trailing null. */
1953 while (abbrs[abbrind] != '\0')
1954 abbrind++;
1955 abbrind++;
1956 *indx = abbrind;
1957
1958 return result;
1959}
struct state state
Definition: pgtz.h:69
int charcnt
Definition: pgtz.h:46

References state::charcnt, state::chars, and pg_tz::state.

Referenced by pg_timezone_abbrevs_zone().

◆ pg_get_timezone_name()

const char * pg_get_timezone_name ( pg_tz tz)

Definition at line 1990 of file localtime.c.

1991{
1992 if (tz)
1993 return tz->TZname;
1994 return NULL;
1995}
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:68

References pg_tz::TZname.

Referenced by show_log_timezone(), show_timezone(), and timetz_at_local().

◆ pg_get_timezone_offset()

bool pg_get_timezone_offset ( const pg_tz tz,
long int *  gmtoff 
)

Definition at line 1966 of file localtime.c.

1967{
1968 /*
1969 * The zone could have more than one ttinfo, if it's historically used
1970 * more than one abbreviation. We return true as long as they all have
1971 * the same gmtoff.
1972 */
1973 const struct state *sp;
1974 int i;
1975
1976 sp = &tz->state;
1977 for (i = 1; i < sp->typecnt; i++)
1978 {
1979 if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
1980 return false;
1981 }
1982 *gmtoff = sp->ttis[0].tt_utoff;
1983 return true;
1984}
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
int typecnt
Definition: pgtz.h:45

References i, pg_tz::state, ttinfo::tt_utoff, state::ttis, and state::typecnt.

Referenced by DecodeTimeOnly(), and TimestampTimestampTzRequiresRewrite().

◆ pg_gmtime()

struct pg_tm * pg_gmtime ( const pg_time_t timep)

Definition at line 1390 of file localtime.c.

1391{
1392 return gmtsub(timep, 0, &tm);
1393}
static struct pg_tm tm
Definition: localtime.c:104

References gmtsub(), and tm.

Referenced by AddFileToBackupManifest(), and GetEpochTime().

◆ pg_interpret_timezone_abbrev()

bool pg_interpret_timezone_abbrev ( const char *  abbrev,
const pg_time_t timep,
long int *  gmtoff,
int *  isdst,
const pg_tz tz 
)

Definition at line 1744 of file localtime.c.

1749{
1750 const struct state *sp;
1751 const char *abbrs;
1752 const struct ttinfo *ttisp;
1753 int abbrind;
1754 int cutoff;
1755 int i;
1756 const pg_time_t t = *timep;
1757
1758 sp = &tz->state;
1759
1760 /*
1761 * Locate the abbreviation in the zone's abbreviation list. We assume
1762 * there are not duplicates in the list.
1763 */
1764 abbrs = sp->chars;
1765 abbrind = 0;
1766 while (abbrind < sp->charcnt)
1767 {
1768 if (strcmp(abbrev, abbrs + abbrind) == 0)
1769 break;
1770 while (abbrs[abbrind] != '\0')
1771 abbrind++;
1772 abbrind++;
1773 }
1774 if (abbrind >= sp->charcnt)
1775 return false; /* not there! */
1776
1777 /*
1778 * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1779 * (goback/goahead zones). Finding the newest or oldest meaning of the
1780 * abbreviation should get us what we want, since extrapolation would just
1781 * be repeating the newest or oldest meanings.
1782 *
1783 * Use binary search to locate the first transition > cutoff time. (Note
1784 * that sp->timecnt could be zero, in which case this loop does nothing
1785 * and only the defaulttype entry will be checked.)
1786 */
1787 {
1788 int lo = 0;
1789 int hi = sp->timecnt;
1790
1791 while (lo < hi)
1792 {
1793 int mid = (lo + hi) >> 1;
1794
1795 if (t < sp->ats[mid])
1796 hi = mid;
1797 else
1798 lo = mid + 1;
1799 }
1800 cutoff = lo;
1801 }
1802
1803 /*
1804 * Scan backwards to find the latest interval using the given abbrev
1805 * before the cutoff time.
1806 */
1807 for (i = cutoff - 1; i >= 0; i--)
1808 {
1809 ttisp = &sp->ttis[sp->types[i]];
1810 if (ttisp->tt_desigidx == abbrind)
1811 {
1812 *gmtoff = ttisp->tt_utoff;
1813 *isdst = ttisp->tt_isdst;
1814 return true;
1815 }
1816 }
1817
1818 /*
1819 * Not found yet; check the defaulttype, which is notionally the era
1820 * before any of the entries in sp->types[].
1821 */
1822 ttisp = &sp->ttis[sp->defaulttype];
1823 if (ttisp->tt_desigidx == abbrind)
1824 {
1825 *gmtoff = ttisp->tt_utoff;
1826 *isdst = ttisp->tt_isdst;
1827 return true;
1828 }
1829
1830 /*
1831 * Not there, so scan forwards to find the first one after the cutoff.
1832 */
1833 for (i = cutoff; i < sp->timecnt; i++)
1834 {
1835 ttisp = &sp->ttis[sp->types[i]];
1836 if (ttisp->tt_desigidx == abbrind)
1837 {
1838 *gmtoff = ttisp->tt_utoff;
1839 *isdst = ttisp->tt_isdst;
1840 return true;
1841 }
1842 }
1843
1844 return false; /* hm, not actually used in any interval? */
1845}
int timecnt
Definition: pgtz.h:44
unsigned char types[TZ_MAX_TIMES]
Definition: pgtz.h:50
int defaulttype
Definition: pgtz.h:61
static int charcnt
Definition: zic.c:178

References state::charcnt, charcnt, state::chars, state::defaulttype, i, pg_tz::state, state::timecnt, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, and state::types.

Referenced by DetermineTimeZoneAbbrevOffsetInternal(), and pg_timezone_abbrevs_zone().

◆ pg_localtime()

struct pg_tm * pg_localtime ( const pg_time_t timep,
const pg_tz tz 
)

◆ pg_next_dst_boundary()

int pg_next_dst_boundary ( const pg_time_t timep,
long int *  before_gmtoff,
int *  before_isdst,
pg_time_t boundary,
long int *  after_gmtoff,
int *  after_isdst,
const pg_tz tz 
)

Definition at line 1611 of file localtime.c.

1618{
1619 const struct state *sp;
1620 const struct ttinfo *ttisp;
1621 int i;
1622 int j;
1623 const pg_time_t t = *timep;
1624
1625 sp = &tz->state;
1626 if (sp->timecnt == 0)
1627 {
1628 /* non-DST zone, use the defaulttype */
1629 ttisp = &sp->ttis[sp->defaulttype];
1630 *before_gmtoff = ttisp->tt_utoff;
1631 *before_isdst = ttisp->tt_isdst;
1632 return 0;
1633 }
1634 if ((sp->goback && t < sp->ats[0]) ||
1635 (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1636 {
1637 /* For values outside the transition table, extrapolate */
1638 pg_time_t newt = t;
1639 pg_time_t seconds;
1640 pg_time_t tcycles;
1641 int64 icycles;
1642 int result;
1643
1644 if (t < sp->ats[0])
1645 seconds = sp->ats[0] - t;
1646 else
1647 seconds = t - sp->ats[sp->timecnt - 1];
1648 --seconds;
1649 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1650 ++tcycles;
1651 icycles = tcycles;
1652 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1653 return -1;
1654 seconds = icycles;
1655 seconds *= YEARSPERREPEAT;
1656 seconds *= AVGSECSPERYEAR;
1657 if (t < sp->ats[0])
1658 newt += seconds;
1659 else
1660 newt -= seconds;
1661 if (newt < sp->ats[0] ||
1662 newt > sp->ats[sp->timecnt - 1])
1663 return -1; /* "cannot happen" */
1664
1665 result = pg_next_dst_boundary(&newt, before_gmtoff,
1666 before_isdst,
1667 boundary,
1668 after_gmtoff,
1669 after_isdst,
1670 tz);
1671 if (t < sp->ats[0])
1672 *boundary -= seconds;
1673 else
1674 *boundary += seconds;
1675 return result;
1676 }
1677
1678 if (t >= sp->ats[sp->timecnt - 1])
1679 {
1680 /* No known transition > t, so use last known segment's type */
1681 i = sp->types[sp->timecnt - 1];
1682 ttisp = &sp->ttis[i];
1683 *before_gmtoff = ttisp->tt_utoff;
1684 *before_isdst = ttisp->tt_isdst;
1685 return 0;
1686 }
1687 if (t < sp->ats[0])
1688 {
1689 /* For "before", use the defaulttype */
1690 ttisp = &sp->ttis[sp->defaulttype];
1691 *before_gmtoff = ttisp->tt_utoff;
1692 *before_isdst = ttisp->tt_isdst;
1693 *boundary = sp->ats[0];
1694 /* And for "after", use the first segment's type */
1695 i = sp->types[0];
1696 ttisp = &sp->ttis[i];
1697 *after_gmtoff = ttisp->tt_utoff;
1698 *after_isdst = ttisp->tt_isdst;
1699 return 1;
1700 }
1701 /* Else search to find the boundary following t */
1702 {
1703 int lo = 1;
1704 int hi = sp->timecnt - 1;
1705
1706 while (lo < hi)
1707 {
1708 int mid = (lo + hi) >> 1;
1709
1710 if (t < sp->ats[mid])
1711 hi = mid;
1712 else
1713 lo = mid + 1;
1714 }
1715 i = lo;
1716 }
1717 j = sp->types[i - 1];
1718 ttisp = &sp->ttis[j];
1719 *before_gmtoff = ttisp->tt_utoff;
1720 *before_isdst = ttisp->tt_isdst;
1721 *boundary = sp->ats[i];
1722 j = sp->types[i];
1723 ttisp = &sp->ttis[j];
1724 *after_gmtoff = ttisp->tt_utoff;
1725 *after_isdst = ttisp->tt_isdst;
1726 return 1;
1727}
int64_t int64
Definition: c.h:538
int pg_next_dst_boundary(const pg_time_t *timep, long int *before_gmtoff, int *before_isdst, pg_time_t *boundary, long int *after_gmtoff, int *after_isdst, const pg_tz *tz)
Definition: localtime.c:1611
bool goback
Definition: pgtz.h:47
pg_time_t ats[TZ_MAX_TIMES]
Definition: pgtz.h:49
bool goahead
Definition: pgtz.h:48

References state::ats, AVGSECSPERYEAR, state::defaulttype, state::goahead, state::goback, i, j, pg_next_dst_boundary(), pg_tz::state, state::timecnt, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, state::types, and YEARSPERREPEAT.

Referenced by DetermineTimeZoneOffsetInternal(), and pg_next_dst_boundary().

◆ pg_timezone_abbrev_is_known()

bool pg_timezone_abbrev_is_known ( const char *  abbrev,
bool *  isfixed,
long int *  gmtoff,
int *  isdst,
const pg_tz tz 
)

Definition at line 1862 of file localtime.c.

1867{
1868 bool result = false;
1869 const struct state *sp = &tz->state;
1870 const char *abbrs;
1871 int abbrind;
1872
1873 /*
1874 * Locate the abbreviation in the zone's abbreviation list. We assume
1875 * there are not duplicates in the list.
1876 */
1877 abbrs = sp->chars;
1878 abbrind = 0;
1879 while (abbrind < sp->charcnt)
1880 {
1881 if (strcmp(abbrev, abbrs + abbrind) == 0)
1882 break;
1883 while (abbrs[abbrind] != '\0')
1884 abbrind++;
1885 abbrind++;
1886 }
1887 if (abbrind >= sp->charcnt)
1888 return false; /* definitely not there */
1889
1890 /*
1891 * Scan the ttinfo array to find uses of the abbreviation.
1892 */
1893 for (int i = 0; i < sp->typecnt; i++)
1894 {
1895 const struct ttinfo *ttisp = &sp->ttis[i];
1896
1897 if (ttisp->tt_desigidx == abbrind)
1898 {
1899 if (!result)
1900 {
1901 /* First usage */
1902 *isfixed = true; /* for the moment */
1903 *gmtoff = ttisp->tt_utoff;
1904 *isdst = ttisp->tt_isdst;
1905 result = true;
1906 }
1907 else
1908 {
1909 /* Second or later usage, does it match? */
1910 if (*gmtoff != ttisp->tt_utoff ||
1911 *isdst != ttisp->tt_isdst)
1912 {
1913 *isfixed = false;
1914 break; /* no point in looking further */
1915 }
1916 }
1917 }
1918 }
1919
1920 return result;
1921}

References state::charcnt, charcnt, state::chars, i, pg_tz::state, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, and state::typecnt.

Referenced by TimeZoneAbbrevIsKnown().

◆ pg_tz_acceptable()

bool pg_tz_acceptable ( pg_tz tz)

Definition at line 2005 of file localtime.c.

2006{
2007 struct pg_tm *tt;
2008 pg_time_t time2000;
2009
2010 /*
2011 * To detect leap-second timekeeping, run pg_localtime for what should be
2012 * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
2013 * other result has to be due to leap seconds.
2014 */
2016 tt = pg_localtime(&time2000, tz);
2017 if (!tt || tt->tm_sec != 0)
2018 return false;
2019
2020 return true;
2021}
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:234
#define SECS_PER_DAY
Definition: timestamp.h:126
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1345
int tm_sec
Definition: pgtime.h:36

References pg_localtime(), POSTGRES_EPOCH_JDATE, SECS_PER_DAY, pg_tm::tm_sec, and UNIX_EPOCH_JDATE.

Referenced by check_log_timezone(), check_timezone(), pg_tzenumerate_next(), score_timezone(), and validate_zone().

◆ timesub()

static struct pg_tm * timesub ( pg_time_t const *  timep,
int_fast32_t  offset,
struct state const *  sp,
struct pg_tm tmp 
)
static

Definition at line 1415 of file localtime.c.

1417{
1418 const struct lsinfo *lp;
1419 pg_time_t tdays;
1420 int idays; /* unsigned would be so 2003 */
1421 int_fast64_t rem;
1422 int y;
1423 const int *ip;
1424 int_fast64_t corr;
1425 bool hit;
1426 int i;
1427
1428 corr = 0;
1429 hit = false;
1430 i = (sp == NULL) ? 0 : sp->leapcnt;
1431 while (--i >= 0)
1432 {
1433 lp = &sp->lsis[i];
1434 if (*timep >= lp->ls_trans)
1435 {
1436 corr = lp->ls_corr;
1437 hit = (*timep == lp->ls_trans
1438 && (i == 0 ? 0 : lp[-1].ls_corr) < corr);
1439 break;
1440 }
1441 }
1442 y = EPOCH_YEAR;
1443 tdays = *timep / SECSPERDAY;
1444 rem = *timep % SECSPERDAY;
1445 while (tdays < 0 || tdays >= year_lengths[isleap(y)])
1446 {
1447 int newy;
1448 pg_time_t tdelta;
1449 int idelta;
1450 int leapdays;
1451
1452 tdelta = tdays / DAYSPERLYEAR;
1453 if (!((!TYPE_SIGNED(pg_time_t) || INT_MIN <= tdelta)
1454 && tdelta <= INT_MAX))
1455 goto out_of_range;
1456 idelta = tdelta;
1457 if (idelta == 0)
1458 idelta = (tdays < 0) ? -1 : 1;
1459 newy = y;
1460 if (increment_overflow(&newy, idelta))
1461 goto out_of_range;
1462 leapdays = leaps_thru_end_of(newy - 1) -
1463 leaps_thru_end_of(y - 1);
1464 tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
1465 tdays -= leapdays;
1466 y = newy;
1467 }
1468
1469 /*
1470 * Given the range, we can now fearlessly cast...
1471 */
1472 idays = tdays;
1473 rem += offset - corr;
1474 while (rem < 0)
1475 {
1476 rem += SECSPERDAY;
1477 --idays;
1478 }
1479 while (rem >= SECSPERDAY)
1480 {
1481 rem -= SECSPERDAY;
1482 ++idays;
1483 }
1484 while (idays < 0)
1485 {
1486 if (increment_overflow(&y, -1))
1487 goto out_of_range;
1488 idays += year_lengths[isleap(y)];
1489 }
1490 while (idays >= year_lengths[isleap(y)])
1491 {
1492 idays -= year_lengths[isleap(y)];
1493 if (increment_overflow(&y, 1))
1494 goto out_of_range;
1495 }
1496 tmp->tm_year = y;
1498 goto out_of_range;
1499 tmp->tm_yday = idays;
1500
1501 /*
1502 * The "extra" mods below avoid overflow problems.
1503 */
1504 tmp->tm_wday = EPOCH_WDAY +
1505 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1507 leaps_thru_end_of(y - 1) -
1509 idays;
1510 tmp->tm_wday %= DAYSPERWEEK;
1511 if (tmp->tm_wday < 0)
1512 tmp->tm_wday += DAYSPERWEEK;
1513 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1514 rem %= SECSPERHOUR;
1515 tmp->tm_min = (int) (rem / SECSPERMIN);
1516
1517 /*
1518 * A positive leap second requires a special representation. This uses
1519 * "... ??:59:60" et seq.
1520 */
1521 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1522 ip = mon_lengths[isleap(y)];
1523 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1524 idays -= ip[tmp->tm_mon];
1525 tmp->tm_mday = (int) (idays + 1);
1526 tmp->tm_isdst = 0;
1527 tmp->tm_gmtoff = offset;
1528 return tmp;
1529
1530out_of_range:
1531 errno = EOVERFLOW;
1532 return NULL;
1533}
#define isleap(y)
Definition: datetime.h:271
static int leaps_thru_end_of(const int y)
Definition: localtime.c:1407
static bool increment_overflow(int *ip, int j)
Definition: localtime.c:1540
static const int year_lengths[2]
Definition: localtime.c:632
static const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:627
while(p+4<=pend)
#define SECSPERDAY
Definition: private.h:100
#define TM_YEAR_BASE
Definition: private.h:124
#define EPOCH_WDAY
Definition: private.h:127
#define EOVERFLOW
Definition: private.h:41
#define EPOCH_YEAR
Definition: private.h:126
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
int tm_yday
Definition: pgtime.h:43
int tm_wday
Definition: pgtime.h:42
long int tm_gmtoff
Definition: pgtime.h:45
static zic_t corr[TZ_MAX_LEAPS]
Definition: zic.c:406

References corr, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, EOVERFLOW, EPOCH_WDAY, EPOCH_YEAR, i, increment_overflow(), isleap, state::leapcnt, leaps_thru_end_of(), lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, mon_lengths, SECSPERDAY, SECSPERHOUR, SECSPERMIN, pg_tm::tm_gmtoff, pg_tm::tm_hour, pg_tm::tm_isdst, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_wday, pg_tm::tm_yday, pg_tm::tm_year, TM_YEAR_BASE, TYPE_SIGNED, while(), y, and year_lengths.

Referenced by gmtsub(), and localsub().

◆ transtime()

static int_fast32_t transtime ( const int  year,
const struct rule *const  rulep,
const int_fast32_t  offset 
)
static

Definition at line 840 of file localtime.c.

842{
843 bool leapyear;
844 int_fast32_t value;
845 int i;
846 int d,
847 m1,
848 yy0,
849 yy1,
850 yy2,
851 dow;
852
854 leapyear = isleap(year);
855 switch (rulep->r_type)
856 {
857
858 case JULIAN_DAY:
859
860 /*
861 * Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
862 * years. In non-leap years, or if the day number is 59 or less,
863 * just add SECSPERDAY times the day number-1 to the time of
864 * January 1, midnight, to get the day.
865 */
866 value = (rulep->r_day - 1) * SECSPERDAY;
867 if (leapyear && rulep->r_day >= 60)
868 value += SECSPERDAY;
869 break;
870
871 case DAY_OF_YEAR:
872
873 /*
874 * n - day of year. Just add SECSPERDAY times the day number to
875 * the time of January 1, midnight, to get the day.
876 */
877 value = rulep->r_day * SECSPERDAY;
878 break;
879
881
882 /*
883 * Mm.n.d - nth "dth day" of month m.
884 */
885
886 /*
887 * Use Zeller's Congruence to get day-of-week of first day of
888 * month.
889 */
890 m1 = (rulep->r_mon + 9) % 12 + 1;
891 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
892 yy1 = yy0 / 100;
893 yy2 = yy0 % 100;
894 dow = ((26 * m1 - 2) / 10 +
895 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
896 if (dow < 0)
897 dow += DAYSPERWEEK;
898
899 /*
900 * "dow" is the day-of-week of the first day of the month. Get the
901 * day-of-month (zero-origin) of the first "dow" day of the month.
902 */
903 d = rulep->r_day - dow;
904 if (d < 0)
905 d += DAYSPERWEEK;
906 for (i = 1; i < rulep->r_week; ++i)
907 {
908 if (d + DAYSPERWEEK >=
909 mon_lengths[leapyear][rulep->r_mon - 1])
910 break;
911 d += DAYSPERWEEK;
912 }
913
914 /*
915 * "d" is the day-of-month (zero-origin) of the day we want.
916 */
917 value = d * SECSPERDAY;
918 for (i = 0; i < rulep->r_mon - 1; ++i)
919 value += mon_lengths[leapyear][i] * SECSPERDAY;
920 break;
921 }
922
923 /*
924 * "value" is the year-relative time of 00:00:00 UT on the day in
925 * question. To get the year-relative time of the specified local time on
926 * that day, add the transition time and the current offset from UT.
927 */
928 return value + rulep->r_time + offset;
929}
static struct @171 value
#define INITIALIZE(x)
Definition: private.h:84

References DAY_OF_YEAR, DAYSPERWEEK, i, INITIALIZE, isleap, JULIAN_DAY, mon_lengths, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, SECSPERDAY, and value.

Referenced by tzparse().

◆ typesequiv()

static bool typesequiv ( struct state const *  sp,
int  a,
int  b 
)
static

Definition at line 603 of file localtime.c.

604{
605 bool result;
606
607 if (sp == NULL ||
608 a < 0 || a >= sp->typecnt ||
609 b < 0 || b >= sp->typecnt)
610 result = false;
611 else
612 {
613 const struct ttinfo *ap = &sp->ttis[a];
614 const struct ttinfo *bp = &sp->ttis[b];
615
616 result = (ap->tt_utoff == bp->tt_utoff
617 && ap->tt_isdst == bp->tt_isdst
618 && ap->tt_ttisstd == bp->tt_ttisstd
619 && ap->tt_ttisut == bp->tt_ttisut
620 && (strcmp(&sp->chars[ap->tt_desigidx],
621 &sp->chars[bp->tt_desigidx])
622 == 0));
623 }
624 return result;
625}
int b
Definition: isn.c:74
int a
Definition: isn.c:73

References a, b, state::chars, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_ttisstd, ttinfo::tt_ttisut, ttinfo::tt_utoff, state::ttis, and state::typecnt.

Referenced by tzloadbody().

◆ tzload()

int tzload ( char const *  name,
char *  canonname,
struct state sp,
bool  doextend 
)

Definition at line 587 of file localtime.c.

588{
589 union local_storage *lsp = malloc(sizeof *lsp);
590
591 if (!lsp)
592 return errno;
593 else
594 {
595 int err = tzloadbody(name, canonname, sp, doextend, lsp);
596
597 free(lsp);
598 return err;
599 }
600}
void err(int eval, const char *fmt,...)
Definition: err.c:43
#define free(a)
Definition: header.h:65
static int tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend, union local_storage *lsp)
Definition: localtime.c:211
const char * name

References err(), free, malloc, name, and tzloadbody().

Referenced by gmtload(), pg_load_tz(), pg_tzenumerate_next(), and pg_tzset().

◆ tzloadbody()

static int tzloadbody ( char const *  name,
char *  canonname,
struct state sp,
bool  doextend,
union local_storage lsp 
)
static

Definition at line 211 of file localtime.c.

213{
214 int i;
215 int fid;
216 int stored;
217 ssize_t nread;
218 union input_buffer *up = &lsp->u.u;
219 int tzheadsize = sizeof(struct tzhead);
220
221 sp->goback = sp->goahead = false;
222
223 if (!name)
224 {
225 name = TZDEFAULT;
226 if (!name)
227 return EINVAL;
228 }
229
230 if (name[0] == ':')
231 ++name;
232
233 fid = pg_open_tzfile(name, canonname);
234 if (fid < 0)
235 return ENOENT; /* pg_open_tzfile may not set errno */
236
237 nread = read(fid, up->buf, sizeof up->buf);
238 if (nread < tzheadsize)
239 {
240 int err = nread < 0 ? errno : EINVAL;
241
242 close(fid);
243 return err;
244 }
245 if (close(fid) < 0)
246 return errno;
247 for (stored = 4; stored <= 8; stored *= 2)
248 {
249 int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
250 int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
251 int_fast64_t prevtr = 0;
252 int_fast32_t prevcorr = 0;
253 int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
254 int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
255 int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
256 int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
257 char const *p = up->buf + tzheadsize;
258
259 /*
260 * Although tzfile(5) currently requires typecnt to be nonzero,
261 * support future formats that may allow zero typecnt in files that
262 * have a TZ string and no transitions.
263 */
264 if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
265 && 0 <= typecnt && typecnt < TZ_MAX_TYPES
266 && 0 <= timecnt && timecnt < TZ_MAX_TIMES
267 && 0 <= charcnt && charcnt < TZ_MAX_CHARS
268 && (ttisstdcnt == typecnt || ttisstdcnt == 0)
269 && (ttisutcnt == typecnt || ttisutcnt == 0)))
270 return EINVAL;
271 if (nread
272 < (tzheadsize /* struct tzhead */
273 + timecnt * stored /* ats */
274 + timecnt /* types */
275 + typecnt * 6 /* ttinfos */
276 + charcnt /* chars */
277 + leapcnt * (stored + 4) /* lsinfos */
278 + ttisstdcnt /* ttisstds */
279 + ttisutcnt)) /* ttisuts */
280 return EINVAL;
281 sp->leapcnt = leapcnt;
282 sp->timecnt = timecnt;
283 sp->typecnt = typecnt;
284 sp->charcnt = charcnt;
285
286 /*
287 * Read transitions, discarding those out of pg_time_t range. But
288 * pretend the last transition before TIME_T_MIN occurred at
289 * TIME_T_MIN.
290 */
291 timecnt = 0;
292 for (i = 0; i < sp->timecnt; ++i)
293 {
294 int_fast64_t at
295 = stored == 4 ? detzcode(p) : detzcode64(p);
296
297 sp->types[i] = at <= TIME_T_MAX;
298 if (sp->types[i])
299 {
300 pg_time_t attime
301 = ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
302 ? TIME_T_MIN : at);
303
304 if (timecnt && attime <= sp->ats[timecnt - 1])
305 {
306 if (attime < sp->ats[timecnt - 1])
307 return EINVAL;
308 sp->types[i - 1] = 0;
309 timecnt--;
310 }
311 sp->ats[timecnt++] = attime;
312 }
313 p += stored;
314 }
315
316 timecnt = 0;
317 for (i = 0; i < sp->timecnt; ++i)
318 {
319 unsigned char typ = *p++;
320
321 if (sp->typecnt <= typ)
322 return EINVAL;
323 if (sp->types[i])
324 sp->types[timecnt++] = typ;
325 }
326 sp->timecnt = timecnt;
327 for (i = 0; i < sp->typecnt; ++i)
328 {
329 struct ttinfo *ttisp;
330 unsigned char isdst,
331 desigidx;
332
333 ttisp = &sp->ttis[i];
334 ttisp->tt_utoff = detzcode(p);
335 p += 4;
336 isdst = *p++;
337 if (!(isdst < 2))
338 return EINVAL;
339 ttisp->tt_isdst = isdst;
340 desigidx = *p++;
341 if (!(desigidx < sp->charcnt))
342 return EINVAL;
343 ttisp->tt_desigidx = desigidx;
344 }
345 for (i = 0; i < sp->charcnt; ++i)
346 sp->chars[i] = *p++;
347 sp->chars[i] = '\0'; /* ensure '\0' at end */
348
349 /* Read leap seconds, discarding those out of pg_time_t range. */
350 leapcnt = 0;
351 for (i = 0; i < sp->leapcnt; ++i)
352 {
353 int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
354 int_fast32_t corr = detzcode(p + stored);
355
356 p += stored + 4;
357 /* Leap seconds cannot occur before the Epoch. */
358 if (tr < 0)
359 return EINVAL;
360 if (tr <= TIME_T_MAX)
361 {
362 /*
363 * Leap seconds cannot occur more than once per UTC month, and
364 * UTC months are at least 28 days long (minus 1 second for a
365 * negative leap second). Each leap second's correction must
366 * differ from the previous one's by 1 second.
367 */
368 if (tr - prevtr < 28 * SECSPERDAY - 1
369 || (corr != prevcorr - 1 && corr != prevcorr + 1))
370 return EINVAL;
371 sp->lsis[leapcnt].ls_trans = prevtr = tr;
372 sp->lsis[leapcnt].ls_corr = prevcorr = corr;
373 leapcnt++;
374 }
375 }
376 sp->leapcnt = leapcnt;
377
378 for (i = 0; i < sp->typecnt; ++i)
379 {
380 struct ttinfo *ttisp;
381
382 ttisp = &sp->ttis[i];
383 if (ttisstdcnt == 0)
384 ttisp->tt_ttisstd = false;
385 else
386 {
387 if (*p != true && *p != false)
388 return EINVAL;
389 ttisp->tt_ttisstd = *p++;
390 }
391 }
392 for (i = 0; i < sp->typecnt; ++i)
393 {
394 struct ttinfo *ttisp;
395
396 ttisp = &sp->ttis[i];
397 if (ttisutcnt == 0)
398 ttisp->tt_ttisut = false;
399 else
400 {
401 if (*p != true && *p != false)
402 return EINVAL;
403 ttisp->tt_ttisut = *p++;
404 }
405 }
406
407 /*
408 * If this is an old file, we're done.
409 */
410 if (up->tzhead.tzh_version[0] == '\0')
411 break;
412 nread -= p - up->buf;
413 memmove(up->buf, p, nread);
414 }
415 if (doextend && nread > 2 &&
416 up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
417 sp->typecnt + 2 <= TZ_MAX_TYPES)
418 {
419 struct state *ts = &lsp->u.st;
420
421 up->buf[nread - 1] = '\0';
422 if (tzparse(&up->buf[1], ts, false))
423 {
424
425 /*
426 * Attempt to reuse existing abbreviations. Without this,
427 * America/Anchorage would be right on the edge after 2037 when
428 * TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT
429 * APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
430 * AKST AKDT). Reusing means sp->charcnt can stay 40 in this
431 * example.
432 */
433 int gotabbr = 0;
434 int charcnt = sp->charcnt;
435
436 for (i = 0; i < ts->typecnt; i++)
437 {
438 char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
439 int j;
440
441 for (j = 0; j < charcnt; j++)
442 if (strcmp(sp->chars + j, tsabbr) == 0)
443 {
444 ts->ttis[i].tt_desigidx = j;
445 gotabbr++;
446 break;
447 }
448 if (!(j < charcnt))
449 {
450 int tsabbrlen = strlen(tsabbr);
451
452 if (j + tsabbrlen < TZ_MAX_CHARS)
453 {
454 strcpy(sp->chars + j, tsabbr);
455 charcnt = j + tsabbrlen + 1;
456 ts->ttis[i].tt_desigidx = j;
457 gotabbr++;
458 }
459 }
460 }
461 if (gotabbr == ts->typecnt)
462 {
463 sp->charcnt = charcnt;
464
465 /*
466 * Ignore any trailing, no-op transitions generated by zic as
467 * they don't help here and can run afoul of bugs in zic 2016j
468 * or earlier.
469 */
470 while (1 < sp->timecnt
471 && (sp->types[sp->timecnt - 1]
472 == sp->types[sp->timecnt - 2]))
473 sp->timecnt--;
474
475 for (i = 0; i < ts->timecnt; i++)
476 if (sp->timecnt == 0
477 || (sp->ats[sp->timecnt - 1]
478 < ts->ats[i] + leapcorr(sp, ts->ats[i])))
479 break;
480 while (i < ts->timecnt
481 && sp->timecnt < TZ_MAX_TIMES)
482 {
483 sp->ats[sp->timecnt]
484 = ts->ats[i] + leapcorr(sp, ts->ats[i]);
485 sp->types[sp->timecnt] = (sp->typecnt
486 + ts->types[i]);
487 sp->timecnt++;
488 i++;
489 }
490 for (i = 0; i < ts->typecnt; i++)
491 sp->ttis[sp->typecnt++] = ts->ttis[i];
492 }
493 }
494 }
495 if (sp->typecnt == 0)
496 return EINVAL;
497 if (sp->timecnt > 1)
498 {
499 for (i = 1; i < sp->timecnt; ++i)
500 if (typesequiv(sp, sp->types[i], sp->types[0]) &&
501 differ_by_repeat(sp->ats[i], sp->ats[0]))
502 {
503 sp->goback = true;
504 break;
505 }
506 for (i = sp->timecnt - 2; i >= 0; --i)
507 if (typesequiv(sp, sp->types[sp->timecnt - 1],
508 sp->types[i]) &&
509 differ_by_repeat(sp->ats[sp->timecnt - 1],
510 sp->ats[i]))
511 {
512 sp->goahead = true;
513 break;
514 }
515 }
516
517 /*
518 * Infer sp->defaulttype from the data. Although this default type is
519 * always zero for data from recent tzdb releases, things are trickier for
520 * data from tzdb 2018e or earlier.
521 *
522 * The first set of heuristics work around bugs in 32-bit data generated
523 * by tzdb 2013c or earlier. The workaround is for zones like
524 * Australia/Macquarie where timestamps before the first transition have a
525 * time type that is not the earliest standard-time type. See:
526 * https://mm.icann.org/pipermail/tz/2013-May/019368.html
527 */
528
529 /*
530 * If type 0 is unused in transitions, it's the type to use for early
531 * times.
532 */
533 for (i = 0; i < sp->timecnt; ++i)
534 if (sp->types[i] == 0)
535 break;
536 i = i < sp->timecnt ? -1 : 0;
537
538 /*
539 * Absent the above, if there are transition times and the first
540 * transition is to a daylight time find the standard type less than and
541 * closest to the type of the first transition.
542 */
543 if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst)
544 {
545 i = sp->types[0];
546 while (--i >= 0)
547 if (!sp->ttis[i].tt_isdst)
548 break;
549 }
550
551 /*
552 * The next heuristics are for data generated by tzdb 2018e or earlier,
553 * for zones like EST5EDT where the first transition is to DST.
554 */
555
556 /*
557 * If no result yet, find the first standard type. If there is none, punt
558 * to type zero.
559 */
560 if (i < 0)
561 {
562 i = 0;
563 while (sp->ttis[i].tt_isdst)
564 if (++i >= sp->typecnt)
565 {
566 i = 0;
567 break;
568 }
569 }
570
571 /*
572 * A simple 'sp->defaulttype = 0;' would suffice here if we didn't have to
573 * worry about 2018e-or-earlier data. Even simpler would be to remove the
574 * defaulttype member and just use 0 in its place.
575 */
576 sp->defaulttype = i;
577
578 return 0;
579}
int pg_open_tzfile(const char *name, char *canonname)
Definition: findtimezone.c:65
for(;;)
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13
static bool differ_by_repeat(const pg_time_t t1, const pg_time_t t0)
Definition: localtime.c:170
static int_fast64_t detzcode64(const char *const codep)
Definition: localtime.c:144
static int_fast64_t leapcorr(struct state const *sp, pg_time_t)
Definition: localtime.c:1575
static int_fast32_t detzcode(const char *const codep)
Definition: localtime.c:118
static bool typesequiv(struct state const *sp, int a, int b)
Definition: localtime.c:603
union input_buffer u
Definition: localtime.c:195
int leapcnt
Definition: pgtz.h:43
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: pgtz.h:54
Definition: tzfile.h:40
char tzh_timecnt[4]
Definition: tzfile.h:47
char tzh_ttisstdcnt[4]
Definition: tzfile.h:45
char tzh_version[1]
Definition: tzfile.h:42
char tzh_charcnt[4]
Definition: tzfile.h:49
char tzh_leapcnt[4]
Definition: tzfile.h:46
char tzh_ttisutcnt[4]
Definition: tzfile.h:44
char tzh_typecnt[4]
Definition: tzfile.h:48
#define TZ_MAX_CHARS
Definition: tzfile.h:105
#define TZ_MAX_TYPES
Definition: tzfile.h:103
#define TZ_MAX_TIMES
Definition: tzfile.h:100
#define TZ_MAX_LEAPS
Definition: tzfile.h:108
#define TZDEFAULT
Definition: tzfile.h:27
char buf[2 *sizeof(struct tzhead)+2 *sizeof(struct state)+4 *TZ_MAX_TIMES]
Definition: localtime.c:185
struct tzhead tzhead
Definition: localtime.c:181
struct local_storage::file_analysis u
static int typecnt
Definition: zic.c:199
static ptrdiff_t timecnt
Definition: zic.c:197
static int leapcnt
Definition: zic.c:182

References state::ats, input_buffer::buf, state::charcnt, charcnt, state::chars, close, corr, state::defaulttype, desigidx, detzcode(), detzcode64(), differ_by_repeat(), err(), for(), state::goahead, state::goback, i, j, state::leapcnt, leapcnt, leapcorr(), lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, name, pg_open_tzfile(), read, SECSPERDAY, local_storage::file_analysis::st, TIME_T_MAX, TIME_T_MIN, state::timecnt, timecnt, ttinfo::tt_desigidx, ttinfo::tt_isdst, ttinfo::tt_ttisstd, ttinfo::tt_ttisut, ttinfo::tt_utoff, state::ttis, TYPE_SIGNED, state::typecnt, typecnt, state::types, typesequiv(), TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, tzhead::tzh_charcnt, tzhead::tzh_leapcnt, tzhead::tzh_timecnt, tzhead::tzh_ttisstdcnt, tzhead::tzh_ttisutcnt, tzhead::tzh_typecnt, tzhead::tzh_version, input_buffer::tzhead, tzparse(), local_storage::file_analysis::u, and local_storage::u.

Referenced by tzload().

◆ tzparse()

bool tzparse ( const char *  name,
struct state sp,
bool  lastditch 
)

Definition at line 937 of file localtime.c.

938{
939 const char *stdname;
940 const char *dstname = NULL;
941 size_t stdlen;
942 size_t dstlen;
943 size_t charcnt;
944 int_fast32_t stdoffset;
945 int_fast32_t dstoffset;
946 char *cp;
947 bool load_ok;
948
949 stdname = name;
950 if (lastditch)
951 {
952 /* Unlike IANA, don't assume name is exactly "GMT" */
953 stdlen = strlen(name); /* length of standard zone name */
954 name += stdlen;
955 stdoffset = 0;
956 }
957 else
958 {
959 if (*name == '<')
960 {
961 name++;
962 stdname = name;
963 name = getqzname(name, '>');
964 if (*name != '>')
965 return false;
966 stdlen = name - stdname;
967 name++;
968 }
969 else
970 {
971 name = getzname(name);
972 stdlen = name - stdname;
973 }
974 if (*name == '\0') /* we allow empty STD abbrev, unlike IANA */
975 return false;
976 name = getoffset(name, &stdoffset);
977 if (name == NULL)
978 return false;
979 }
980 charcnt = stdlen + 1;
981 if (sizeof sp->chars < charcnt)
982 return false;
983
984 /*
985 * The IANA code always tries to tzload(TZDEFRULES) here. We do not want
986 * to do that; it would be bad news in the lastditch case, where we can't
987 * assume pg_open_tzfile() is sane yet. Moreover, if we did load it and
988 * it contains leap-second-dependent info, that would cause problems too.
989 * Finally, IANA has deprecated the TZDEFRULES feature, so it presumably
990 * will die at some point. Desupporting it now seems like good
991 * future-proofing.
992 */
993 load_ok = false;
994 sp->goback = sp->goahead = false; /* simulate failed tzload() */
995 sp->leapcnt = 0; /* intentionally assume no leap seconds */
996
997 if (*name != '\0')
998 {
999 if (*name == '<')
1000 {
1001 dstname = ++name;
1002 name = getqzname(name, '>');
1003 if (*name != '>')
1004 return false;
1005 dstlen = name - dstname;
1006 name++;
1007 }
1008 else
1009 {
1010 dstname = name;
1011 name = getzname(name);
1012 dstlen = name - dstname; /* length of DST abbr. */
1013 }
1014 if (!dstlen)
1015 return false;
1016 charcnt += dstlen + 1;
1017 if (sizeof sp->chars < charcnt)
1018 return false;
1019 if (*name != '\0' && *name != ',' && *name != ';')
1020 {
1021 name = getoffset(name, &dstoffset);
1022 if (name == NULL)
1023 return false;
1024 }
1025 else
1026 dstoffset = stdoffset - SECSPERHOUR;
1027 if (*name == '\0' && !load_ok)
1029 if (*name == ',' || *name == ';')
1030 {
1031 struct rule start;
1032 struct rule end;
1033 int year;
1034 int yearlim;
1035 int timecnt;
1036 pg_time_t janfirst;
1037 int_fast32_t janoffset = 0;
1038 int yearbeg;
1039
1040 ++name;
1041 if ((name = getrule(name, &start)) == NULL)
1042 return false;
1043 if (*name++ != ',')
1044 return false;
1045 if ((name = getrule(name, &end)) == NULL)
1046 return false;
1047 if (*name != '\0')
1048 return false;
1049 sp->typecnt = 2; /* standard time and DST */
1050
1051 /*
1052 * Two transitions per year, from EPOCH_YEAR forward.
1053 */
1054 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1055 init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1056 sp->defaulttype = 0;
1057 timecnt = 0;
1058 janfirst = 0;
1059 yearbeg = EPOCH_YEAR;
1060
1061 do
1062 {
1063 int_fast32_t yearsecs
1064 = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1065
1066 yearbeg--;
1067 if (increment_overflow_time(&janfirst, -yearsecs))
1068 {
1069 janoffset = -yearsecs;
1070 break;
1071 }
1072 } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1073
1074 yearlim = yearbeg + YEARSPERREPEAT + 1;
1075 for (year = yearbeg; year < yearlim; year++)
1076 {
1077 int_fast32_t
1078 starttime = transtime(year, &start, stdoffset),
1079 endtime = transtime(year, &end, dstoffset);
1080 int_fast32_t
1081 yearsecs = (year_lengths[isleap(year)]
1082 * SECSPERDAY);
1083 bool reversed = endtime < starttime;
1084
1085 if (reversed)
1086 {
1087 int_fast32_t swap = starttime;
1088
1089 starttime = endtime;
1090 endtime = swap;
1091 }
1092 if (reversed
1093 || (starttime < endtime
1094 && (endtime - starttime
1095 < (yearsecs
1096 + (stdoffset - dstoffset)))))
1097 {
1098 if (TZ_MAX_TIMES - 2 < timecnt)
1099 break;
1100 sp->ats[timecnt] = janfirst;
1102 (&sp->ats[timecnt],
1103 janoffset + starttime))
1104 sp->types[timecnt++] = !reversed;
1105 sp->ats[timecnt] = janfirst;
1107 (&sp->ats[timecnt],
1108 janoffset + endtime))
1109 {
1110 sp->types[timecnt++] = reversed;
1111 yearlim = year + YEARSPERREPEAT + 1;
1112 }
1113 }
1115 (&janfirst, janoffset + yearsecs))
1116 break;
1117 janoffset = 0;
1118 }
1119 sp->timecnt = timecnt;
1120 if (!timecnt)
1121 {
1122 sp->ttis[0] = sp->ttis[1];
1123 sp->typecnt = 1; /* Perpetual DST. */
1124 }
1125 else if (YEARSPERREPEAT < year - yearbeg)
1126 sp->goback = sp->goahead = true;
1127 }
1128 else
1129 {
1130 int_fast32_t theirstdoffset;
1131 int_fast32_t theirdstoffset;
1132 int_fast32_t theiroffset;
1133 bool isdst;
1134 int i;
1135 int j;
1136
1137 if (*name != '\0')
1138 return false;
1139
1140 /*
1141 * Initial values of theirstdoffset and theirdstoffset.
1142 */
1143 theirstdoffset = 0;
1144 for (i = 0; i < sp->timecnt; ++i)
1145 {
1146 j = sp->types[i];
1147 if (!sp->ttis[j].tt_isdst)
1148 {
1149 theirstdoffset =
1150 -sp->ttis[j].tt_utoff;
1151 break;
1152 }
1153 }
1154 theirdstoffset = 0;
1155 for (i = 0; i < sp->timecnt; ++i)
1156 {
1157 j = sp->types[i];
1158 if (sp->ttis[j].tt_isdst)
1159 {
1160 theirdstoffset =
1161 -sp->ttis[j].tt_utoff;
1162 break;
1163 }
1164 }
1165
1166 /*
1167 * Initially we're assumed to be in standard time.
1168 */
1169 isdst = false;
1170 theiroffset = theirstdoffset;
1171
1172 /*
1173 * Now juggle transition times and types tracking offsets as you
1174 * do.
1175 */
1176 for (i = 0; i < sp->timecnt; ++i)
1177 {
1178 j = sp->types[i];
1179 sp->types[i] = sp->ttis[j].tt_isdst;
1180 if (sp->ttis[j].tt_ttisut)
1181 {
1182 /* No adjustment to transition time */
1183 }
1184 else
1185 {
1186 /*
1187 * If daylight saving time is in effect, and the
1188 * transition time was not specified as standard time, add
1189 * the daylight saving time offset to the transition time;
1190 * otherwise, add the standard time offset to the
1191 * transition time.
1192 */
1193 /*
1194 * Transitions from DST to DDST will effectively disappear
1195 * since POSIX provides for only one DST offset.
1196 */
1197 if (isdst && !sp->ttis[j].tt_ttisstd)
1198 {
1199 sp->ats[i] += dstoffset -
1200 theirdstoffset;
1201 }
1202 else
1203 {
1204 sp->ats[i] += stdoffset -
1205 theirstdoffset;
1206 }
1207 }
1208 theiroffset = -sp->ttis[j].tt_utoff;
1209 if (sp->ttis[j].tt_isdst)
1210 theirdstoffset = theiroffset;
1211 else
1212 theirstdoffset = theiroffset;
1213 }
1214
1215 /*
1216 * Finally, fill in ttis.
1217 */
1218 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1219 init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1220 sp->typecnt = 2;
1221 sp->defaulttype = 0;
1222 }
1223 }
1224 else
1225 {
1226 dstlen = 0;
1227 sp->typecnt = 1; /* only standard time */
1228 sp->timecnt = 0;
1229 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1230 sp->defaulttype = 0;
1231 }
1232 sp->charcnt = charcnt;
1233 cp = sp->chars;
1234 memcpy(cp, stdname, stdlen);
1235 cp += stdlen;
1236 *cp++ = '\0';
1237 if (dstlen != 0)
1238 {
1239 memcpy(cp, dstname, dstlen);
1240 *(cp + dstlen) = '\0';
1241 }
1242 return true;
1243}
return str start
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
static const char * getqzname(const char *strp, const int delim)
Definition: localtime.c:664
static bool increment_overflow_time(pg_time_t *tp, int_fast32_t j)
Definition: localtime.c:1558
static void init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
Definition: localtime.c:108
#define TZDEFRULESTRING
Definition: localtime.c:61
static int_fast32_t transtime(const int year, const struct rule *const rulep, const int_fast32_t offset)
Definition: localtime.c:840
static const char * getzname(const char *strp)
Definition: localtime.c:643
static const char * getrule(const char *strp, struct rule *const rulep)
Definition: localtime.c:779
Definition: localtime.c:73

References state::ats, state::charcnt, charcnt, state::chars, state::defaulttype, EPOCH_YEAR, getoffset(), getqzname(), getrule(), getzname(), state::goahead, state::goback, i, if(), increment_overflow_time(), init_ttinfo(), isleap, j, state::leapcnt, name, SECSPERDAY, SECSPERHOUR, start, state::timecnt, timecnt, transtime(), ttinfo::tt_isdst, ttinfo::tt_ttisstd, ttinfo::tt_ttisut, ttinfo::tt_utoff, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULESTRING, year_lengths, and YEARSPERREPEAT.

Referenced by gmtload(), pg_load_tz(), pg_tzset(), and tzloadbody().

Variable Documentation

◆ gmt

const char gmt[] = "GMT"
static

Definition at line 53 of file localtime.c.

Referenced by gbt_tstz_compress(), and gmtload().

◆ mon_lengths

const int mon_lengths[2][MONSPERYEAR]
static
Initial value:
= {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
}

Definition at line 627 of file localtime.c.

Referenced by timesub(), and transtime().

◆ tm

struct pg_tm tm
static

Definition at line 104 of file localtime.c.

Referenced by abstime2tm(), AdjustFractDays(), AdjustFractSeconds(), AppendTimestampSeconds(), build_time_t(), cache_locale_time(), check_recovery_target_time(), ClearPgTm(), createBackupLabel(), date2timestamptz_safe(), date_in(), date_out(), DCH_to_char(), DecodeDate(), DecodeDateTime(), DecodeInterval(), DecodeISO8601Interval(), DecodeNumber(), DecodeNumberField(), DecodeTime(), DecodeTimeOnly(), DetermineTimeZoneAbbrevOffset(), DetermineTimeZoneAbbrevOffsetTS(), DetermineTimeZoneOffset(), DetermineTimeZoneOffsetInternal(), do_to_timestamp(), dttofmtasc_replace(), EncodeDateOnly(), EncodeDateTime(), EncodeInterval(), EncodeTimeOnly(), executeDateTimeMethod(), gbt_num_compress(), get_timezone_offset(), GetCurrentDateTime(), GetCurrentTimeUsec(), GetEpochTime(), GetSQLCurrentDate(), GetSQLCurrentTime(), GetSQLLocalTime(), identify_system_timezone(), interval2tm(), interval_part_common(), interval_to_char(), interval_trunc(), JsonEncodeDateTime(), llvm_create_jit_instance(), locale_date_order(), main(), make_date(), make_timestamp_internal(), map_sql_value_to_xml_value(), my_strftime(), parse_datetime(), parse_sane_timezone(), pg_gmtime(), pg_localtime(), PGTYPESdate_defmt_asc(), PGTYPESdate_fmt_asc(), PGTYPESdate_from_asc(), PGTYPESdate_to_asc(), PGTYPESdate_today(), PGTYPESinterval_from_asc(), PGTYPESinterval_to_asc(), PGTYPEStimestamp_add_interval(), PGTYPEStimestamp_current(), PGTYPEStimestamp_defmt_scan(), PGTYPEStimestamp_fmt_asc(), PGTYPEStimestamp_from_asc(), PGTYPEStimestamp_to_asc(), pqTraceFormatTimestamp(), ReadHead(), score_timezone(), set_next_rotation_time(), SetEpochTimestamp(), tarOpen(), time2tm(), time_in(), time_out(), time_part_common(), time_t_to_timestamptz(), time_timetz(), timestamp2date_safe(), timestamp2timestamptz_safe(), timestamp2tm(), timestamp_age(), timestamp_in(), timestamp_out(), timestamp_part_common(), timestamp_pl_interval(), timestamp_recv(), timestamp_time(), timestamp_to_char(), timestamp_trunc(), timestamp_zone(), timestamptz2date_safe(), timestamptz2timestamp_safe(), timestamptz_age(), timestamptz_in(), timestamptz_out(), timestamptz_part_common(), timestamptz_pl_interval_internal(), timestamptz_recv(), timestamptz_time(), timestamptz_timetz(), timestamptz_to_char(), timestamptz_to_str(), timestamptz_trunc_internal(), timestamptz_zone(), timetz2tm(), timetz_in(), timetz_out(), timetz_part_common(), timetz_zone(), tm2interval(), tm2time(), tm2timestamp(), tm2timetz(), to_date(), to_timestamp(), typenameTypeMod(), ValidateDate(), WriteHead(), and writezone().

◆ wildabbr

const char wildabbr[] = WILDABBR
static

Definition at line 51 of file localtime.c.

Referenced by gmtsub().

◆ year_lengths

const int year_lengths[2]
static
Initial value:

Definition at line 632 of file localtime.c.

Referenced by timesub(), and tzparse().