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 *, int32, struct pg_tm *)
 
static bool increment_overflow (int *, int)
 
static bool increment_overflow_time (pg_time_t *, int32)
 
static int64 leapcorr (struct state const *, pg_time_t)
 
static struct pg_tmtimesub (pg_time_t const *, int32, struct state const *, struct pg_tm *)
 
static bool typesequiv (struct state const *, int, int)
 
static void init_ttinfo (struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
 
static int32 detzcode (const char *const codep)
 
static int64 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 (const char *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, int32 *const secsp)
 
static const char * getoffset (const char *strp, int32 *const offsetp)
 
static const char * getrule (const char *strp, struct rule *const rulep)
 
static int32 transtime (const int year, const struct rule *const rulep, const int32 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_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.

Referenced by tzparse().

◆ 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 };

Function Documentation

◆ detzcode()

static int32 detzcode ( const char *const  codep)
static

Definition at line 116 of file localtime.c.

References i, and TWOS_COMPLEMENT.

Referenced by tzloadbody().

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

◆ detzcode64()

static int64 detzcode64 ( const char *const  codep)
static

Definition at line 142 of file localtime.c.

References i, and TWOS_COMPLEMENT.

Referenced by tzloadbody().

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

◆ differ_by_repeat()

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

Definition at line 168 of file localtime.c.

References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, and TYPE_SIGNED.

Referenced by tzloadbody().

169 {
171  return 0;
172  return t1 - t0 == SECSPERREPEAT;
173 }
int64 pg_time_t
Definition: pgtime.h:23
#define SECSPERREPEAT_BITS
Definition: private.h:161
#define TYPE_BIT(type)
Definition: private.h:60
#define SECSPERREPEAT
Definition: private.h:159
#define TYPE_SIGNED(type)
Definition: private.h:61

◆ getnum()

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

Definition at line 678 of file localtime.c.

References is_digit.

Referenced by getrule(), and getsecs().

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

◆ getoffset()

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

Definition at line 749 of file localtime.c.

References getsecs().

Referenced by getrule(), and tzparse().

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

◆ getqzname()

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

Definition at line 661 of file localtime.c.

Referenced by tzparse().

662 {
663  int c;
664 
665  while ((c = *strp) != '\0' && c != delim)
666  ++strp;
667  return strp;
668 }
char * c

◆ getrule()

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

Definition at line 776 of file localtime.c.

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().

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

◆ getsecs()

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

Definition at line 708 of file localtime.c.

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

Referenced by getoffset().

709 {
710  int num;
711 
712  /*
713  * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
714  * "M10.4.6/26", which does not conform to Posix, but which specifies the
715  * equivalent of "02:00 on the first Sunday on or after 23 Oct".
716  */
717  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
718  if (strp == NULL)
719  return NULL;
720  *secsp = num * (int32) SECSPERHOUR;
721  if (*strp == ':')
722  {
723  ++strp;
724  strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
725  if (strp == NULL)
726  return NULL;
727  *secsp += num * SECSPERMIN;
728  if (*strp == ':')
729  {
730  ++strp;
731  /* 'SECSPERMIN' allows for leap seconds. */
732  strp = getnum(strp, &num, 0, SECSPERMIN);
733  if (strp == NULL)
734  return NULL;
735  *secsp += num;
736  }
737  }
738  return strp;
739 }
#define SECSPERMIN
Definition: private.h:101
#define SECSPERHOUR
Definition: private.h:107
#define HOURSPERDAY
Definition: private.h:103
signed int int32
Definition: c.h:363
#define DAYSPERWEEK
Definition: private.h:104
static const char * getnum(const char *strp, int *const nump, const int min, const int max)
Definition: localtime.c:678
#define MINSPERHOUR
Definition: private.h:102

◆ getzname()

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

Definition at line 640 of file localtime.c.

References is_digit.

Referenced by tzparse().

641 {
642  char c;
643 
644  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
645  c != '+')
646  ++strp;
647  return strp;
648 }
#define is_digit(c)
Definition: private.h:45
char * c

◆ gmtload()

static void gmtload ( struct state *const  sp)
static

Definition at line 1243 of file localtime.c.

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

Referenced by gmtsub().

1244 {
1245  if (tzload(gmt, NULL, sp, true) != 0)
1246  tzparse(gmt, sp, true);
1247 }
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:584
bool tzparse(const char *name, struct state *sp, bool lastditch)
Definition: localtime.c:934
static const char gmt[]
Definition: localtime.c:53

◆ gmtsub()

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

Definition at line 1355 of file localtime.c.

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

Referenced by localsub(), and pg_gmtime().

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

◆ increment_overflow()

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

Definition at line 1537 of file localtime.c.

References i.

Referenced by timesub().

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

◆ increment_overflow_time()

static bool increment_overflow_time ( pg_time_t tp,
int32  j 
)
static

Definition at line 1555 of file localtime.c.

References TIME_T_MAX, TIME_T_MIN, and TYPE_SIGNED.

Referenced by tzparse().

1556 {
1557  /*----------
1558  * This is like
1559  * 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1560  * except that it does the right thing even if *tp + j would overflow.
1561  *----------
1562  */
1563  if (!(j < 0
1564  ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1565  : *tp <= TIME_T_MAX - j))
1566  return true;
1567  *tp += j;
1568  return false;
1569 }
int64 pg_time_t
Definition: pgtime.h:23
#define TIME_T_MAX
Definition: private.h:77
#define TIME_T_MIN
Definition: private.h:76
#define TYPE_SIGNED(type)
Definition: private.h:61

◆ init_ttinfo()

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

Definition at line 106 of file localtime.c.

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

Referenced by tzparse().

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

◆ leapcorr()

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

Definition at line 1572 of file localtime.c.

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

Referenced by tzloadbody().

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

◆ leaps_thru_end_of()

static int leaps_thru_end_of ( const int  y)
static

Definition at line 1404 of file localtime.c.

References leaps_thru_end_of_nonneg().

Referenced by timesub().

1405 {
1406  return (y < 0
1407  ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1409 }
static int leaps_thru_end_of_nonneg(int y)
Definition: localtime.c:1398

◆ leaps_thru_end_of_nonneg()

static int leaps_thru_end_of_nonneg ( int  y)
static

Definition at line 1398 of file localtime.c.

Referenced by leaps_thru_end_of().

1399 {
1400  return y / 4 - y / 100 + y / 400;
1401 }

◆ localsub()

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

Definition at line 1257 of file localtime.c.

References state::ats, AVGSECSPERYEAR, state::chars, state::defaulttype, gmtsub(), state::goahead, state::goback, i, 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 pg_localtime().

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

◆ pg_get_timezone_name()

const char* pg_get_timezone_name ( pg_tz tz)

Definition at line 1873 of file localtime.c.

References pg_tz::TZname.

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

1874 {
1875  if (tz)
1876  return tz->TZname;
1877  return NULL;
1878 }
char TZname[TZ_STRLEN_MAX+1]
Definition: pgtz.h:68

◆ pg_get_timezone_offset()

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

Definition at line 1849 of file localtime.c.

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

Referenced by DecodeTimeOnly(), and TimestampTimestampTzRequiresRewrite().

1850 {
1851  /*
1852  * The zone could have more than one ttinfo, if it's historically used
1853  * more than one abbreviation. We return true as long as they all have
1854  * the same gmtoff.
1855  */
1856  const struct state *sp;
1857  int i;
1858 
1859  sp = &tz->state;
1860  for (i = 1; i < sp->typecnt; i++)
1861  {
1862  if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
1863  return false;
1864  }
1865  *gmtoff = sp->ttis[0].tt_utoff;
1866  return true;
1867 }
int32 tt_utoff
Definition: pgtz.h:28
struct state state
Definition: pgtz.h:69
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
Definition: regguts.h:298
int i
int typecnt
Definition: pgtz.h:45

◆ pg_gmtime()

struct pg_tm* pg_gmtime ( const pg_time_t timep)

Definition at line 1387 of file localtime.c.

References gmtsub(), and tm.

Referenced by AddFileToBackupManifest(), and GetEpochTime().

1388 {
1389  return gmtsub(timep, 0, &tm);
1390 }
static struct pg_tm tm
Definition: localtime.c:102
static struct pg_tm * gmtsub(pg_time_t const *, int32, struct pg_tm *)
Definition: localtime.c:1355

◆ 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 1755 of file localtime.c.

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

Referenced by DetermineTimeZoneAbbrevOffsetInternal().

1760 {
1761  const struct state *sp;
1762  const char *abbrs;
1763  const struct ttinfo *ttisp;
1764  int abbrind;
1765  int cutoff;
1766  int i;
1767  const pg_time_t t = *timep;
1768 
1769  sp = &tz->state;
1770 
1771  /*
1772  * Locate the abbreviation in the zone's abbreviation list. We assume
1773  * there are not duplicates in the list.
1774  */
1775  abbrs = sp->chars;
1776  abbrind = 0;
1777  while (abbrind < sp->charcnt)
1778  {
1779  if (strcmp(abbrev, abbrs + abbrind) == 0)
1780  break;
1781  while (abbrs[abbrind] != '\0')
1782  abbrind++;
1783  abbrind++;
1784  }
1785  if (abbrind >= sp->charcnt)
1786  return false; /* not there! */
1787 
1788  /*
1789  * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1790  * (goback/goahead zones). Finding the newest or oldest meaning of the
1791  * abbreviation should get us what we want, since extrapolation would just
1792  * be repeating the newest or oldest meanings.
1793  *
1794  * Use binary search to locate the first transition > cutoff time.
1795  */
1796  {
1797  int lo = 0;
1798  int hi = sp->timecnt;
1799 
1800  while (lo < hi)
1801  {
1802  int mid = (lo + hi) >> 1;
1803 
1804  if (t < sp->ats[mid])
1805  hi = mid;
1806  else
1807  lo = mid + 1;
1808  }
1809  cutoff = lo;
1810  }
1811 
1812  /*
1813  * Scan backwards to find the latest interval using the given abbrev
1814  * before the cutoff time.
1815  */
1816  for (i = cutoff - 1; i >= 0; i--)
1817  {
1818  ttisp = &sp->ttis[sp->types[i]];
1819  if (ttisp->tt_desigidx == abbrind)
1820  {
1821  *gmtoff = ttisp->tt_utoff;
1822  *isdst = ttisp->tt_isdst;
1823  return true;
1824  }
1825  }
1826 
1827  /*
1828  * Not there, so scan forwards to find the first one after.
1829  */
1830  for (i = cutoff; i < sp->timecnt; i++)
1831  {
1832  ttisp = &sp->ttis[sp->types[i]];
1833  if (ttisp->tt_desigidx == abbrind)
1834  {
1835  *gmtoff = ttisp->tt_utoff;
1836  *isdst = ttisp->tt_isdst;
1837  return true;
1838  }
1839  }
1840 
1841  return false; /* hm, not actually used in any interval? */
1842 }
int64 pg_time_t
Definition: pgtime.h:23
int charcnt
Definition: pgtz.h:46
Definition: pgtz.h:26
int32 tt_utoff
Definition: pgtz.h:28
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, 4),(2 *(TZ_STRLEN_MAX+1)))]
Definition: pgtz.h:53
bool tt_isdst
Definition: pgtz.h:29
int tt_desigidx
Definition: pgtz.h:30
struct state state
Definition: pgtz.h:69
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
unsigned char types[TZ_MAX_TIMES]
Definition: pgtz.h:50
Definition: regguts.h:298
int timecnt
Definition: pgtz.h:44
static int charcnt
Definition: zic.c:173
int i

◆ pg_localtime()

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

Definition at line 1342 of file localtime.c.

References localsub(), pg_tz::state, and tm.

Referenced by do_pg_start_backup(), do_pg_stop_backup(), log_line_prefix(), logfile_getname(), pg_tz_acceptable(), score_timezone(), set_next_rotation_time(), setup_formatted_log_time(), setup_formatted_start_time(), str_time(), timeofday(), timestamp2tm(), and timetz_zone().

1343 {
1344  return localsub(&tz->state, timep, &tm);
1345 }
static struct pg_tm * localsub(struct state const *sp, pg_time_t const *timep, struct pg_tm *const tmp)
Definition: localtime.c:1257
static struct pg_tm tm
Definition: localtime.c:102
struct state state
Definition: pgtz.h:69

◆ 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 1608 of file localtime.c.

References state::ats, AVGSECSPERYEAR, state::goahead, state::goback, i, pg_tz::state, state::timecnt, ttinfo::tt_isdst, ttinfo::tt_utoff, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by DetermineTimeZoneOffsetInternal().

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

◆ pg_tz_acceptable()

bool pg_tz_acceptable ( pg_tz tz)

Definition at line 1888 of file localtime.c.

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().

1889 {
1890  struct pg_tm *tt;
1891  pg_time_t time2000;
1892 
1893  /*
1894  * To detect leap-second timekeeping, run pg_localtime for what should be
1895  * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
1896  * other result has to be due to leap seconds.
1897  */
1899  tt = pg_localtime(&time2000, tz);
1900  if (!tt || tt->tm_sec != 0)
1901  return false;
1902 
1903  return true;
1904 }
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1342
int64 pg_time_t
Definition: pgtime.h:23
Definition: pgtime.h:25
#define SECS_PER_DAY
Definition: timestamp.h:86
#define UNIX_EPOCH_JDATE
Definition: timestamp.h:162
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:163
int tm_sec
Definition: pgtime.h:27

◆ timesub()

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

Definition at line 1412 of file localtime.c.

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, and year_lengths.

Referenced by gmtsub(), and localsub().

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

◆ transtime()

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

Definition at line 837 of file localtime.c.

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().

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

◆ typesequiv()

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

Definition at line 600 of file localtime.c.

References 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().

601 {
602  bool result;
603 
604  if (sp == NULL ||
605  a < 0 || a >= sp->typecnt ||
606  b < 0 || b >= sp->typecnt)
607  result = false;
608  else
609  {
610  const struct ttinfo *ap = &sp->ttis[a];
611  const struct ttinfo *bp = &sp->ttis[b];
612 
613  result = (ap->tt_utoff == bp->tt_utoff
614  && ap->tt_isdst == bp->tt_isdst
615  && ap->tt_ttisstd == bp->tt_ttisstd
616  && ap->tt_ttisut == bp->tt_ttisut
617  && (strcmp(&sp->chars[ap->tt_desigidx],
618  &sp->chars[bp->tt_desigidx])
619  == 0));
620  }
621  return result;
622 }
Definition: pgtz.h:26
int32 tt_utoff
Definition: pgtz.h:28
bool tt_ttisut
Definition: pgtz.h:32
bool tt_isdst
Definition: pgtz.h:29
int tt_desigidx
Definition: pgtz.h:30
bool tt_ttisstd
Definition: pgtz.h:31

◆ tzload()

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

Definition at line 584 of file localtime.c.

References free, malloc, and tzloadbody().

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

585 {
586  union local_storage *lsp = malloc(sizeof *lsp);
587 
588  if (!lsp)
589  return errno;
590  else
591  {
592  int err = tzloadbody(name, canonname, sp, doextend, lsp);
593 
594  free(lsp);
595  return err;
596  }
597 }
static int tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend, union local_storage *lsp)
Definition: localtime.c:209
#define malloc(a)
Definition: header.h:50
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:561

◆ tzloadbody()

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

Definition at line 209 of file localtime.c.

References state::ats, input_buffer::buf, state::charcnt, charcnt, state::chars, close, corr, state::defaulttype, desigidx, detzcode(), detzcode64(), differ_by_repeat(), state::goahead, state::goback, i, 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().

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

◆ tzparse()

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

Definition at line 934 of file localtime.c.

References state::ats, state::charcnt, charcnt, state::chars, state::defaulttype, EPOCH_YEAR, getoffset(), getqzname(), getrule(), getzname(), state::goahead, state::goback, i, increment_overflow_time(), init_ttinfo(), isleap, state::leapcnt, name, SECSPERDAY, SECSPERHOUR, swap, 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().

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

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 624 of file localtime.c.

Referenced by timesub(), and transtime().

◆ tm

struct pg_tm tm
static

Definition at line 102 of file localtime.c.

Referenced by build_time_t(), cache_locale_time(), check_recovery_target_time(), createBackupLabel(), date2timestamptz_opt_overflow(), date_in(), date_out(), gbt_num_compress(), GetSQLCurrentTime(), GetSQLLocalTime(), identify_system_timezone(), interval_in(), interval_out(), interval_part(), interval_trunc(), JsonEncodeDateTime(), locale_date_order(), pg_gmtime(), pg_localtime(), pg_timezone_names(), PGLC_localeconv(), 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(), ReadHead(), scan_available_timezones(), score_timezone(), set_next_rotation_time(), SetEpochTimestamp(), tarOpen(), time_in(), time_out(), time_part(), time_timetz(), timestamp2timestamptz_opt_overflow(), timestamp_age(), timestamp_date(), timestamp_in(), timestamp_out(), timestamp_part(), timestamp_pl_interval(), timestamp_recv(), timestamp_time(), timestamp_trunc(), timestamptz2timestamp(), timestamptz_age(), timestamptz_date(), timestamptz_in(), timestamptz_out(), timestamptz_part(), timestamptz_pl_interval(), timestamptz_recv(), timestamptz_time(), timestamptz_timetz(), timestamptz_to_str(), timestamptz_trunc_internal(), timetz_in(), timetz_out(), timetz_part(), timetz_zone(), typenameTypeMod(), 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:
= {
}
#define DAYSPERNYEAR
Definition: private.h:105
#define DAYSPERLYEAR
Definition: private.h:106

Definition at line 629 of file localtime.c.

Referenced by timesub(), and tzparse().