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 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 statetzdefrules_s = NULL
 
static int tzdefrules_loaded = 0
 
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 68 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 72 of file localtime.c.

73 {
74  JULIAN_DAY, /* Jn = Julian day */
75  DAY_OF_YEAR, /* n = day of year */
76  MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
77 };

Function Documentation

◆ detzcode()

static int32 detzcode ( const char *const  codep)
static

Definition at line 122 of file localtime.c.

References i, and TWOS_COMPLEMENT.

Referenced by tzloadbody().

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

◆ detzcode64()

static int64 detzcode64 ( const char *const  codep)
static

Definition at line 148 of file localtime.c.

References i, and TWOS_COMPLEMENT.

Referenced by tzloadbody().

149 {
150  uint64 result;
151  int i;
152  int64 one = 1;
153  int64 halfmaxval = one << (64 - 2);
154  int64 maxval = halfmaxval - 1 + halfmaxval;
155  int64 minval = -TWOS_COMPLEMENT(int64) -maxval;
156 
157  result = codep[0] & 0x7f;
158  for (i = 1; i < 8; ++i)
159  result = (result << 8) | (codep[i] & 0xff);
160 
161  if (codep[0] & 0x80)
162  {
163  /*
164  * Do two's-complement negation even on non-two's-complement machines.
165  * If the result would be minval - 1, return minval.
166  */
167  result -= !TWOS_COMPLEMENT(int64) &&result != 0;
168  result += minval;
169  }
170  return result;
171 }
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 174 of file localtime.c.

References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, and TYPE_SIGNED.

Referenced by tzloadbody().

175 {
177  return 0;
178  return t1 - t0 == SECSPERREPEAT;
179 }
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 682 of file localtime.c.

References is_digit.

Referenced by getrule(), and getsecs().

683 {
684  char c;
685  int num;
686 
687  if (strp == NULL || !is_digit(c = *strp))
688  return NULL;
689  num = 0;
690  do
691  {
692  num = num * 10 + (c - '0');
693  if (num > max)
694  return NULL; /* illegal value */
695  c = *++strp;
696  } while (is_digit(c));
697  if (num < min)
698  return NULL; /* illegal value */
699  *nump = num;
700  return strp;
701 }
#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 753 of file localtime.c.

References getsecs().

Referenced by getrule(), and tzparse().

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

◆ getqzname()

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

Definition at line 665 of file localtime.c.

Referenced by tzparse().

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

◆ getrule()

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

Definition at line 780 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().

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

◆ getsecs()

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

Definition at line 712 of file localtime.c.

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

Referenced by getoffset().

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

◆ getzname()

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

Definition at line 644 of file localtime.c.

References is_digit.

Referenced by tzparse().

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

◆ gmtload()

static void gmtload ( struct state *const  sp)
static

Definition at line 1276 of file localtime.c.

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

Referenced by gmtsub().

1277 {
1278  if (tzload(gmt, NULL, sp, true) != 0)
1279  tzparse(gmt, sp, true);
1280 }
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:588
bool tzparse(const char *name, struct state *sp, bool lastditch)
Definition: localtime.c:938
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 1388 of file localtime.c.

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

Referenced by localsub(), and pg_gmtime().

1390 {
1391  struct pg_tm *result;
1392 
1393  /* GMT timezone state data is kept here */
1394  static struct state *gmtptr = NULL;
1395 
1396  if (gmtptr == NULL)
1397  {
1398  /* Allocate on first use */
1399  gmtptr = (struct state *) malloc(sizeof(struct state));
1400  if (gmtptr == NULL)
1401  return NULL; /* errno should be set by malloc */
1402  gmtload(gmtptr);
1403  }
1404 
1405  result = timesub(timep, offset, gmtptr, tmp);
1406 
1407  /*
1408  * Could get fancy here and deliver something such as "+xx" or "-xx" if
1409  * offset is non-zero, but this is no time for a treasure hunt.
1410  */
1411  if (offset != 0)
1412  tmp->tm_zone = wildabbr;
1413  else
1414  tmp->tm_zone = gmtptr->chars;
1415 
1416  return result;
1417 }
Definition: pgtime.h:25
static void gmtload(struct state *const sp)
Definition: localtime.c:1276
#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:1445

◆ increment_overflow()

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

Definition at line 1570 of file localtime.c.

References i.

Referenced by timesub().

1571 {
1572  int const i = *ip;
1573 
1574  /*----------
1575  * If i >= 0 there can only be overflow if i + j > INT_MAX
1576  * or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1577  * If i < 0 there can only be overflow if i + j < INT_MIN
1578  * or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1579  *----------
1580  */
1581  if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1582  return true;
1583  *ip += j;
1584  return false;
1585 }
int i

◆ increment_overflow_time()

static bool increment_overflow_time ( pg_time_t tp,
int32  j 
)
static

Definition at line 1588 of file localtime.c.

References TIME_T_MAX, TIME_T_MIN, and TYPE_SIGNED.

Referenced by tzparse().

1589 {
1590  /*----------
1591  * This is like
1592  * 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1593  * except that it does the right thing even if *tp + j would overflow.
1594  *----------
1595  */
1596  if (!(j < 0
1597  ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1598  : *tp <= TIME_T_MAX - j))
1599  return true;
1600  *tp += j;
1601  return false;
1602 }
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 112 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().

113 {
114  s->tt_utoff = utoff;
115  s->tt_isdst = isdst;
116  s->tt_desigidx = desigidx;
117  s->tt_ttisstd = false;
118  s->tt_ttisut = false;
119 }
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:392

◆ leaps_thru_end_of()

static int leaps_thru_end_of ( const int  y)
static

Definition at line 1437 of file localtime.c.

References leaps_thru_end_of_nonneg().

Referenced by timesub().

1438 {
1439  return (y < 0
1440  ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1442 }
static int leaps_thru_end_of_nonneg(int y)
Definition: localtime.c:1431

◆ leaps_thru_end_of_nonneg()

static int leaps_thru_end_of_nonneg ( int  y)
static

Definition at line 1431 of file localtime.c.

Referenced by leaps_thru_end_of().

1432 {
1433  return y / 4 - y / 100 + y / 400;
1434 }

◆ localsub()

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

Definition at line 1290 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().

1292 {
1293  const struct ttinfo *ttisp;
1294  int i;
1295  struct pg_tm *result;
1296  const pg_time_t t = *timep;
1297 
1298  if (sp == NULL)
1299  return gmtsub(timep, 0, tmp);
1300  if ((sp->goback && t < sp->ats[0]) ||
1301  (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1302  {
1303  pg_time_t newt = t;
1304  pg_time_t seconds;
1305  pg_time_t years;
1306 
1307  if (t < sp->ats[0])
1308  seconds = sp->ats[0] - t;
1309  else
1310  seconds = t - sp->ats[sp->timecnt - 1];
1311  --seconds;
1312  years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
1313  seconds = years * AVGSECSPERYEAR;
1314  if (t < sp->ats[0])
1315  newt += seconds;
1316  else
1317  newt -= seconds;
1318  if (newt < sp->ats[0] ||
1319  newt > sp->ats[sp->timecnt - 1])
1320  return NULL; /* "cannot happen" */
1321  result = localsub(sp, &newt, tmp);
1322  if (result)
1323  {
1324  int64 newy;
1325 
1326  newy = result->tm_year;
1327  if (t < sp->ats[0])
1328  newy -= years;
1329  else
1330  newy += years;
1331  if (!(INT_MIN <= newy && newy <= INT_MAX))
1332  return NULL;
1333  result->tm_year = newy;
1334  }
1335  return result;
1336  }
1337  if (sp->timecnt == 0 || t < sp->ats[0])
1338  {
1339  i = sp->defaulttype;
1340  }
1341  else
1342  {
1343  int lo = 1;
1344  int hi = sp->timecnt;
1345 
1346  while (lo < hi)
1347  {
1348  int mid = (lo + hi) >> 1;
1349 
1350  if (t < sp->ats[mid])
1351  hi = mid;
1352  else
1353  lo = mid + 1;
1354  }
1355  i = (int) sp->types[lo - 1];
1356  }
1357  ttisp = &sp->ttis[i];
1358 
1359  /*
1360  * To get (wrong) behavior that's compatible with System V Release 2.0
1361  * you'd replace the statement below with t += ttisp->tt_utoff;
1362  * timesub(&t, 0L, sp, tmp);
1363  */
1364  result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1365  if (result)
1366  {
1367  result->tm_isdst = ttisp->tt_isdst;
1368  result->tm_zone = unconstify(char *, &sp->chars[ttisp->tt_desigidx]);
1369  }
1370  return result;
1371 }
#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:1290
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:1163
#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:1445
static struct pg_tm * gmtsub(pg_time_t const *, int32, struct pg_tm *)
Definition: localtime.c:1388

◆ pg_get_timezone_name()

const char* pg_get_timezone_name ( pg_tz tz)

Definition at line 1890 of file localtime.c.

References pg_tz::TZname.

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

1891 {
1892  if (tz)
1893  return tz->TZname;
1894  return NULL;
1895 }
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 1866 of file localtime.c.

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

Referenced by DecodeTimeOnly(), and TimestampTimestampTzRequiresRewrite().

1867 {
1868  /*
1869  * The zone could have more than one ttinfo, if it's historically used
1870  * more than one abbreviation. We return true as long as they all have
1871  * the same gmtoff.
1872  */
1873  const struct state *sp;
1874  int i;
1875 
1876  sp = &tz->state;
1877  for (i = 1; i < sp->typecnt; i++)
1878  {
1879  if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
1880  return false;
1881  }
1882  *gmtoff = sp->ttis[0].tt_utoff;
1883  return true;
1884 }
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 1420 of file localtime.c.

References gmtsub(), and tm.

Referenced by GetEpochTime().

1421 {
1422  return gmtsub(timep, 0, &tm);
1423 }
static struct pg_tm tm
Definition: localtime.c:108
static struct pg_tm * gmtsub(pg_time_t const *, int32, struct pg_tm *)
Definition: localtime.c:1388

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

1777 {
1778  const struct state *sp;
1779  const char *abbrs;
1780  const struct ttinfo *ttisp;
1781  int abbrind;
1782  int cutoff;
1783  int i;
1784  const pg_time_t t = *timep;
1785 
1786  sp = &tz->state;
1787 
1788  /*
1789  * Locate the abbreviation in the zone's abbreviation list. We assume
1790  * there are not duplicates in the list.
1791  */
1792  abbrs = sp->chars;
1793  abbrind = 0;
1794  while (abbrind < sp->charcnt)
1795  {
1796  if (strcmp(abbrev, abbrs + abbrind) == 0)
1797  break;
1798  while (abbrs[abbrind] != '\0')
1799  abbrind++;
1800  abbrind++;
1801  }
1802  if (abbrind >= sp->charcnt)
1803  return false; /* not there! */
1804 
1805  /*
1806  * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1807  * (goback/goahead zones). Finding the newest or oldest meaning of the
1808  * abbreviation should get us what we want, since extrapolation would just
1809  * be repeating the newest or oldest meanings.
1810  *
1811  * Use binary search to locate the first transition > cutoff time.
1812  */
1813  {
1814  int lo = 0;
1815  int hi = sp->timecnt;
1816 
1817  while (lo < hi)
1818  {
1819  int mid = (lo + hi) >> 1;
1820 
1821  if (t < sp->ats[mid])
1822  hi = mid;
1823  else
1824  lo = mid + 1;
1825  }
1826  cutoff = lo;
1827  }
1828 
1829  /*
1830  * Scan backwards to find the latest interval using the given abbrev
1831  * before the cutoff time.
1832  */
1833  for (i = cutoff - 1; i >= 0; 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  /*
1845  * Not there, so scan forwards to find the first one after.
1846  */
1847  for (i = cutoff; i < sp->timecnt; i++)
1848  {
1849  ttisp = &sp->ttis[sp->types[i]];
1850  if (ttisp->tt_desigidx == abbrind)
1851  {
1852  *gmtoff = ttisp->tt_utoff;
1853  *isdst = ttisp->tt_isdst;
1854  return true;
1855  }
1856  }
1857 
1858  return false; /* hm, not actually used in any interval? */
1859 }
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:174
int i

◆ pg_localtime()

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

Definition at line 1375 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().

1376 {
1377  return localsub(&tz->state, timep, &tm);
1378 }
static struct pg_tm * localsub(struct state const *sp, pg_time_t const *timep, struct pg_tm *const tmp)
Definition: localtime.c:1290
static struct pg_tm tm
Definition: localtime.c:108
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 1625 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().

1632 {
1633  const struct state *sp;
1634  const struct ttinfo *ttisp;
1635  int i;
1636  int j;
1637  const pg_time_t t = *timep;
1638 
1639  sp = &tz->state;
1640  if (sp->timecnt == 0)
1641  {
1642  /* non-DST zone, use lowest-numbered standard type */
1643  i = 0;
1644  while (sp->ttis[i].tt_isdst)
1645  if (++i >= sp->typecnt)
1646  {
1647  i = 0;
1648  break;
1649  }
1650  ttisp = &sp->ttis[i];
1651  *before_gmtoff = ttisp->tt_utoff;
1652  *before_isdst = ttisp->tt_isdst;
1653  return 0;
1654  }
1655  if ((sp->goback && t < sp->ats[0]) ||
1656  (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1657  {
1658  /* For values outside the transition table, extrapolate */
1659  pg_time_t newt = t;
1660  pg_time_t seconds;
1661  pg_time_t tcycles;
1662  int64 icycles;
1663  int result;
1664 
1665  if (t < sp->ats[0])
1666  seconds = sp->ats[0] - t;
1667  else
1668  seconds = t - sp->ats[sp->timecnt - 1];
1669  --seconds;
1670  tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1671  ++tcycles;
1672  icycles = tcycles;
1673  if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1674  return -1;
1675  seconds = icycles;
1676  seconds *= YEARSPERREPEAT;
1677  seconds *= AVGSECSPERYEAR;
1678  if (t < sp->ats[0])
1679  newt += seconds;
1680  else
1681  newt -= seconds;
1682  if (newt < sp->ats[0] ||
1683  newt > sp->ats[sp->timecnt - 1])
1684  return -1; /* "cannot happen" */
1685 
1686  result = pg_next_dst_boundary(&newt, before_gmtoff,
1687  before_isdst,
1688  boundary,
1689  after_gmtoff,
1690  after_isdst,
1691  tz);
1692  if (t < sp->ats[0])
1693  *boundary -= seconds;
1694  else
1695  *boundary += seconds;
1696  return result;
1697  }
1698 
1699  if (t >= sp->ats[sp->timecnt - 1])
1700  {
1701  /* No known transition > t, so use last known segment's type */
1702  i = sp->types[sp->timecnt - 1];
1703  ttisp = &sp->ttis[i];
1704  *before_gmtoff = ttisp->tt_utoff;
1705  *before_isdst = ttisp->tt_isdst;
1706  return 0;
1707  }
1708  if (t < sp->ats[0])
1709  {
1710  /* For "before", use lowest-numbered standard type */
1711  i = 0;
1712  while (sp->ttis[i].tt_isdst)
1713  if (++i >= sp->typecnt)
1714  {
1715  i = 0;
1716  break;
1717  }
1718  ttisp = &sp->ttis[i];
1719  *before_gmtoff = ttisp->tt_utoff;
1720  *before_isdst = ttisp->tt_isdst;
1721  *boundary = sp->ats[0];
1722  /* And for "after", use the first segment's type */
1723  i = sp->types[0];
1724  ttisp = &sp->ttis[i];
1725  *after_gmtoff = ttisp->tt_utoff;
1726  *after_isdst = ttisp->tt_isdst;
1727  return 1;
1728  }
1729  /* Else search to find the boundary following t */
1730  {
1731  int lo = 1;
1732  int hi = sp->timecnt - 1;
1733 
1734  while (lo < hi)
1735  {
1736  int mid = (lo + hi) >> 1;
1737 
1738  if (t < sp->ats[mid])
1739  hi = mid;
1740  else
1741  lo = mid + 1;
1742  }
1743  i = lo;
1744  }
1745  j = sp->types[i - 1];
1746  ttisp = &sp->ttis[j];
1747  *before_gmtoff = ttisp->tt_utoff;
1748  *before_isdst = ttisp->tt_isdst;
1749  *boundary = sp->ats[i];
1750  j = sp->types[i];
1751  ttisp = &sp->ttis[j];
1752  *after_gmtoff = ttisp->tt_utoff;
1753  *after_isdst = ttisp->tt_isdst;
1754  return 1;
1755 }
#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:1625
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 1905 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().

1906 {
1907  struct pg_tm *tt;
1908  pg_time_t time2000;
1909 
1910  /*
1911  * To detect leap-second timekeeping, run pg_localtime for what should be
1912  * GMT midnight, 2000-01-01. Insist that the tm_sec value be zero; any
1913  * other result has to be due to leap seconds.
1914  */
1916  tt = pg_localtime(&time2000, tz);
1917  if (!tt || tt->tm_sec != 0)
1918  return false;
1919 
1920  return true;
1921 }
struct pg_tm * pg_localtime(const pg_time_t *timep, const pg_tz *tz)
Definition: localtime.c:1375
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 1445 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().

1447 {
1448  const struct lsinfo *lp;
1449  pg_time_t tdays;
1450  int idays; /* unsigned would be so 2003 */
1451  int64 rem;
1452  int y;
1453  const int *ip;
1454  int64 corr;
1455  bool hit;
1456  int i;
1457 
1458  corr = 0;
1459  hit = false;
1460  i = (sp == NULL) ? 0 : sp->leapcnt;
1461  while (--i >= 0)
1462  {
1463  lp = &sp->lsis[i];
1464  if (*timep >= lp->ls_trans)
1465  {
1466  corr = lp->ls_corr;
1467  hit = (*timep == lp->ls_trans
1468  && (i == 0 ? 0 : lp[-1].ls_corr) < corr);
1469  break;
1470  }
1471  }
1472  y = EPOCH_YEAR;
1473  tdays = *timep / SECSPERDAY;
1474  rem = *timep % SECSPERDAY;
1475  while (tdays < 0 || tdays >= year_lengths[isleap(y)])
1476  {
1477  int newy;
1478  pg_time_t tdelta;
1479  int idelta;
1480  int leapdays;
1481 
1482  tdelta = tdays / DAYSPERLYEAR;
1483  if (!((!TYPE_SIGNED(pg_time_t) ||INT_MIN <= tdelta)
1484  && tdelta <= INT_MAX))
1485  goto out_of_range;
1486  idelta = tdelta;
1487  if (idelta == 0)
1488  idelta = (tdays < 0) ? -1 : 1;
1489  newy = y;
1490  if (increment_overflow(&newy, idelta))
1491  goto out_of_range;
1492  leapdays = leaps_thru_end_of(newy - 1) -
1493  leaps_thru_end_of(y - 1);
1494  tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
1495  tdays -= leapdays;
1496  y = newy;
1497  }
1498 
1499  /*
1500  * Given the range, we can now fearlessly cast...
1501  */
1502  idays = tdays;
1503  rem += offset - corr;
1504  while (rem < 0)
1505  {
1506  rem += SECSPERDAY;
1507  --idays;
1508  }
1509  while (rem >= SECSPERDAY)
1510  {
1511  rem -= SECSPERDAY;
1512  ++idays;
1513  }
1514  while (idays < 0)
1515  {
1516  if (increment_overflow(&y, -1))
1517  goto out_of_range;
1518  idays += year_lengths[isleap(y)];
1519  }
1520  while (idays >= year_lengths[isleap(y)])
1521  {
1522  idays -= year_lengths[isleap(y)];
1523  if (increment_overflow(&y, 1))
1524  goto out_of_range;
1525  }
1526  tmp->tm_year = y;
1528  goto out_of_range;
1529  tmp->tm_yday = idays;
1530 
1531  /*
1532  * The "extra" mods below avoid overflow problems.
1533  */
1534  tmp->tm_wday = EPOCH_WDAY +
1535  ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1537  leaps_thru_end_of(y - 1) -
1539  idays;
1540  tmp->tm_wday %= DAYSPERWEEK;
1541  if (tmp->tm_wday < 0)
1542  tmp->tm_wday += DAYSPERWEEK;
1543  tmp->tm_hour = (int) (rem / SECSPERHOUR);
1544  rem %= SECSPERHOUR;
1545  tmp->tm_min = (int) (rem / SECSPERMIN);
1546 
1547  /*
1548  * A positive leap second requires a special representation. This uses
1549  * "... ??:59:60" et seq.
1550  */
1551  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1552  ip = mon_lengths[isleap(y)];
1553  for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1554  idays -= ip[tmp->tm_mon];
1555  tmp->tm_mday = (int) (idays + 1);
1556  tmp->tm_isdst = 0;
1557  tmp->tm_gmtoff = offset;
1558  return tmp;
1559 
1560 out_of_range:
1561  errno = EOVERFLOW;
1562  return NULL;
1563 }
#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:397
#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:628
#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:1437
static const int year_lengths[2]
Definition: localtime.c:633
static bool increment_overflow(int *, int)
Definition: localtime.c:1570
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 841 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().

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

◆ typesequiv()

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

Definition at line 604 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().

605 {
606  bool result;
607 
608  if (sp == NULL ||
609  a < 0 || a >= sp->typecnt ||
610  b < 0 || b >= sp->typecnt)
611  result = false;
612  else
613  {
614  const struct ttinfo *ap = &sp->ttis[a];
615  const struct ttinfo *bp = &sp->ttis[b];
616 
617  result = (ap->tt_utoff == bp->tt_utoff
618  && ap->tt_isdst == bp->tt_isdst
619  && ap->tt_ttisstd == bp->tt_ttisstd
620  && ap->tt_ttisut == bp->tt_ttisut
621  && (strcmp(&sp->chars[ap->tt_desigidx],
622  &sp->chars[bp->tt_desigidx])
623  == 0));
624  }
625  return result;
626 }
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 588 of file localtime.c.

References free, malloc, and tzloadbody().

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

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

◆ tzloadbody()

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

Definition at line 215 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, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, memmove, 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().

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

◆ tzparse()

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

Definition at line 938 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, malloc, 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, TZDEFRULES, tzdefrules_loaded, TZDEFRULESTRING, tzload(), year_lengths, and YEARSPERREPEAT.

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

939 {
940  const char *stdname;
941  const char *dstname = NULL;
942  size_t stdlen;
943  size_t dstlen;
944  size_t charcnt;
945  int32 stdoffset;
946  int32 dstoffset;
947  char *cp;
948  bool load_ok;
949 
950  stdname = name;
951  if (lastditch)
952  {
953  /* Unlike IANA, don't assume name is exactly "GMT" */
954  stdlen = strlen(name); /* length of standard zone name */
955  name += stdlen;
956  stdoffset = 0;
957  }
958  else
959  {
960  if (*name == '<')
961  {
962  name++;
963  stdname = name;
964  name = getqzname(name, '>');
965  if (*name != '>')
966  return false;
967  stdlen = name - stdname;
968  name++;
969  }
970  else
971  {
972  name = getzname(name);
973  stdlen = name - stdname;
974  }
975  if (*name == '\0') /* we allow empty STD abbrev, unlike IANA */
976  return false;
977  name = getoffset(name, &stdoffset);
978  if (name == NULL)
979  return false;
980  }
981  charcnt = stdlen + 1;
982  if (sizeof sp->chars < charcnt)
983  return false;
984 
985  /*
986  * The IANA code always tries tzload(TZDEFRULES) here. We do not want to
987  * do that; it would be bad news in the lastditch case, where we can't
988  * assume pg_open_tzfile() is sane yet. Moreover, the only reason to do
989  * it unconditionally is to absorb the TZDEFRULES zone's leap second info,
990  * which we don't want to do anyway. Without that, we only need to load
991  * TZDEFRULES if the zone name specifies DST but doesn't incorporate a
992  * POSIX-style transition date rule, which is not a common case.
993  */
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')
1028  {
1029  /*
1030  * The POSIX zone name does not provide a transition-date rule.
1031  * Here we must load the TZDEFRULES zone, if possible, to serve as
1032  * source data for the transition dates. Unlike the IANA code, we
1033  * try to cache the data so it's only loaded once.
1034  */
1035  if (tzdefrules_loaded == 0)
1036  {
1037  /* Allocate on first use */
1038  if (tzdefrules_s == NULL)
1039  tzdefrules_s = (struct state *) malloc(sizeof(struct state));
1040  if (tzdefrules_s != NULL)
1041  {
1042  if (tzload(TZDEFRULES, NULL, tzdefrules_s, false) == 0)
1043  tzdefrules_loaded = 1;
1044  else
1045  tzdefrules_loaded = -1;
1046  /* In any case, we ignore leap-second data from the file */
1047  tzdefrules_s->leapcnt = 0;
1048  }
1049  }
1050  load_ok = (tzdefrules_loaded > 0);
1051  if (load_ok)
1052  memcpy(sp, tzdefrules_s, sizeof(struct state));
1053  else
1054  {
1055  /* If we can't load TZDEFRULES, fall back to hard-wired rule */
1057  }
1058  }
1059  if (*name == ',' || *name == ';')
1060  {
1061  struct rule start;
1062  struct rule end;
1063  int year;
1064  int yearlim;
1065  int timecnt;
1066  pg_time_t janfirst;
1067  int32 janoffset = 0;
1068  int yearbeg;
1069 
1070  ++name;
1071  if ((name = getrule(name, &start)) == NULL)
1072  return false;
1073  if (*name++ != ',')
1074  return false;
1075  if ((name = getrule(name, &end)) == NULL)
1076  return false;
1077  if (*name != '\0')
1078  return false;
1079  sp->typecnt = 2; /* standard time and DST */
1080 
1081  /*
1082  * Two transitions per year, from EPOCH_YEAR forward.
1083  */
1084  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1085  init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1086  sp->defaulttype = 0;
1087  timecnt = 0;
1088  janfirst = 0;
1089  yearbeg = EPOCH_YEAR;
1090 
1091  do
1092  {
1093  int32 yearsecs
1094  = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1095 
1096  yearbeg--;
1097  if (increment_overflow_time(&janfirst, -yearsecs))
1098  {
1099  janoffset = -yearsecs;
1100  break;
1101  }
1102  } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1103 
1104  yearlim = yearbeg + YEARSPERREPEAT + 1;
1105  for (year = yearbeg; year < yearlim; year++)
1106  {
1107  int32
1108  starttime = transtime(year, &start, stdoffset),
1109  endtime = transtime(year, &end, dstoffset);
1110  int32
1111  yearsecs = (year_lengths[isleap(year)]
1112  * SECSPERDAY);
1113  bool reversed = endtime < starttime;
1114 
1115  if (reversed)
1116  {
1117  int32 swap = starttime;
1118 
1119  starttime = endtime;
1120  endtime = swap;
1121  }
1122  if (reversed
1123  || (starttime < endtime
1124  && (endtime - starttime
1125  < (yearsecs
1126  + (stdoffset - dstoffset)))))
1127  {
1128  if (TZ_MAX_TIMES - 2 < timecnt)
1129  break;
1130  sp->ats[timecnt] = janfirst;
1132  (&sp->ats[timecnt],
1133  janoffset + starttime))
1134  sp->types[timecnt++] = !reversed;
1135  sp->ats[timecnt] = janfirst;
1137  (&sp->ats[timecnt],
1138  janoffset + endtime))
1139  {
1140  sp->types[timecnt++] = reversed;
1141  yearlim = year + YEARSPERREPEAT + 1;
1142  }
1143  }
1145  (&janfirst, janoffset + yearsecs))
1146  break;
1147  janoffset = 0;
1148  }
1149  sp->timecnt = timecnt;
1150  if (!timecnt)
1151  {
1152  sp->ttis[0] = sp->ttis[1];
1153  sp->typecnt = 1; /* Perpetual DST. */
1154  }
1155  else if (YEARSPERREPEAT < year - yearbeg)
1156  sp->goback = sp->goahead = true;
1157  }
1158  else
1159  {
1160  int32 theirstdoffset;
1161  int32 theirdstoffset;
1162  int32 theiroffset;
1163  bool isdst;
1164  int i;
1165  int j;
1166 
1167  if (*name != '\0')
1168  return false;
1169 
1170  /*
1171  * Initial values of theirstdoffset and theirdstoffset.
1172  */
1173  theirstdoffset = 0;
1174  for (i = 0; i < sp->timecnt; ++i)
1175  {
1176  j = sp->types[i];
1177  if (!sp->ttis[j].tt_isdst)
1178  {
1179  theirstdoffset =
1180  -sp->ttis[j].tt_utoff;
1181  break;
1182  }
1183  }
1184  theirdstoffset = 0;
1185  for (i = 0; i < sp->timecnt; ++i)
1186  {
1187  j = sp->types[i];
1188  if (sp->ttis[j].tt_isdst)
1189  {
1190  theirdstoffset =
1191  -sp->ttis[j].tt_utoff;
1192  break;
1193  }
1194  }
1195 
1196  /*
1197  * Initially we're assumed to be in standard time.
1198  */
1199  isdst = false;
1200  theiroffset = theirstdoffset;
1201 
1202  /*
1203  * Now juggle transition times and types tracking offsets as you
1204  * do.
1205  */
1206  for (i = 0; i < sp->timecnt; ++i)
1207  {
1208  j = sp->types[i];
1209  sp->types[i] = sp->ttis[j].tt_isdst;
1210  if (sp->ttis[j].tt_ttisut)
1211  {
1212  /* No adjustment to transition time */
1213  }
1214  else
1215  {
1216  /*
1217  * If daylight saving time is in effect, and the
1218  * transition time was not specified as standard time, add
1219  * the daylight saving time offset to the transition time;
1220  * otherwise, add the standard time offset to the
1221  * transition time.
1222  */
1223  /*
1224  * Transitions from DST to DDST will effectively disappear
1225  * since POSIX provides for only one DST offset.
1226  */
1227  if (isdst && !sp->ttis[j].tt_ttisstd)
1228  {
1229  sp->ats[i] += dstoffset -
1230  theirdstoffset;
1231  }
1232  else
1233  {
1234  sp->ats[i] += stdoffset -
1235  theirstdoffset;
1236  }
1237  }
1238  theiroffset = -sp->ttis[j].tt_utoff;
1239  if (sp->ttis[j].tt_isdst)
1240  theirdstoffset = theiroffset;
1241  else
1242  theirstdoffset = theiroffset;
1243  }
1244 
1245  /*
1246  * Finally, fill in ttis.
1247  */
1248  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1249  init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1250  sp->typecnt = 2;
1251  sp->defaulttype = 0;
1252  }
1253  }
1254  else
1255  {
1256  dstlen = 0;
1257  sp->typecnt = 1; /* only standard time */
1258  sp->timecnt = 0;
1259  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1260  sp->defaulttype = 0;
1261  }
1262  sp->charcnt = charcnt;
1263  cp = sp->chars;
1264  memcpy(cp, stdname, stdlen);
1265  cp += stdlen;
1266  *cp++ = '\0';
1267  if (dstlen != 0)
1268  {
1269  memcpy(cp, dstname, dstlen);
1270  *(cp + dstlen) = '\0';
1271  }
1272  return true;
1273 }
#define swap(a, b)
Definition: qsort.c:94
int64 pg_time_t
Definition: pgtime.h:23
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:588
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:665
#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:68
Definition: localtime.c:79
signed int int32
Definition: c.h:346
bool tt_ttisut
Definition: pgtz.h:32
#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
bool tt_isdst
Definition: pgtz.h:29
static const char * getoffset(const char *strp, int32 *const offsetp)
Definition: localtime.c:753
static const char * getrule(const char *strp, struct rule *const rulep)
Definition: localtime.c:780
static struct state * tzdefrules_s
Definition: localtime.c:59
#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 int tzdefrules_loaded
Definition: localtime.c:60
static void init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
Definition: localtime.c:112
Definition: regguts.h:298
#define TZDEFRULES
Definition: tzfile.h:28
static ptrdiff_t timecnt
Definition: zic.c:193
int timecnt
Definition: pgtz.h:44
static int charcnt
Definition: zic.c:174
bool tt_ttisstd
Definition: pgtz.h:31
const char * name
Definition: encode.c:521
#define YEARSPERREPEAT
Definition: private.h:99
static bool increment_overflow_time(pg_time_t *, int32)
Definition: localtime.c:1588
static const int year_lengths[2]
Definition: localtime.c:633
static int32 transtime(const int year, const struct rule *const rulep, const int32 offset)
Definition: localtime.c:841
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:644

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

Referenced by timesub(), and transtime().

◆ tm

struct pg_tm tm
static

Definition at line 108 of file localtime.c.

Referenced by build_time_t(), cache_locale_time(), check_recovery_target_time(), createBackupLabel(), date2timestamptz(), date_in(), date_out(), gbt_num_compress(), GetSQLCurrentDate(), GetSQLCurrentTime(), GetSQLLocalTime(), identify_system_timezone(), interval_in(), interval_out(), interval_part(), interval_trunc(), JsonEncodeDateTime(), locale_date_order(), pg_gmtime(), pg_localtime(), 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(), 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().

◆ tzdefrules_loaded

int tzdefrules_loaded = 0
static

Definition at line 60 of file localtime.c.

Referenced by tzparse().

◆ tzdefrules_s

struct state* tzdefrules_s = NULL
static

Definition at line 59 of file localtime.c.

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

Referenced by timesub(), and tzparse().