1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
|
/*-------------------------------------------------------------------------
*
* timestamp.h
* Timestamp and Interval typedefs and related macros.
*
* Note: this file must be includable in both frontend and backend contexts.
*
* Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/datatype/timestamp.h
*
*-------------------------------------------------------------------------
*/
#ifndef DATATYPE_TIMESTAMP_H
#define DATATYPE_TIMESTAMP_H
/*
* Timestamp represents absolute time.
*
* Interval represents delta time. Keep track of months (and years), days,
* and hours/minutes/seconds separately since the elapsed time spanned is
* unknown until instantiated relative to an absolute time.
*
* Note that Postgres uses "time interval" to mean a bounded interval,
* consisting of a beginning and ending time, not a time span - thomas 97/03/20
*
* Timestamps, as well as the h/m/s fields of intervals, are stored as
* int64 values with units of microseconds. (Once upon a time they were
* double values with units of seconds.)
*
* TimeOffset and fsec_t are convenience typedefs for temporary variables.
* Do not use fsec_t in values stored on-disk.
* Also, fsec_t is only meant for *fractional* seconds; beware of overflow
* if the value you need to store could be many seconds.
*/
typedef int64 Timestamp;
typedef int32 fsec_t; /* fractional seconds (in microseconds) */
typedef int64 TimestampTz;
typedef int64 TimeOffset;
typedef struct
{
TimeOffset time; /* all time units other than days, months and
* years */
int32 day; /* days, after time for alignment */
int32 month; /* months and years, after time for alignment */
} Interval;
/* Limits on the "precision" option (typmod) for these data types */
#define MAX_TIMESTAMP_PRECISION 6
#define MAX_INTERVAL_PRECISION 6
/*
* Round off to MAX_TIMESTAMP_PRECISION decimal places.
* Note: this is also used for rounding off intervals.
*/
#define TS_PREC_INV 1000000.0
#define TSROUND(j) (rint(((double) (j)) * TS_PREC_INV) / TS_PREC_INV)
/*
* Assorted constants for datetime-related calculations
*/
#define DAYS_PER_YEAR 365.25 /* assumes leap year every four years */
#define MONTHS_PER_YEAR 12
/*
* DAYS_PER_MONTH is very imprecise. The more accurate value is
* 365.2425/12 = 30.436875, or '30 days 10:29:06'. Right now we only
* return an integral number of days, but someday perhaps we should
* also return a 'time' value to be used as well. ISO 8601 suggests
* 30 days.
*/
#define DAYS_PER_MONTH 30 /* assumes exactly 30 days per month */
#define HOURS_PER_DAY 24 /* assume no daylight savings time changes */
/*
* This doesn't adjust for uneven daylight savings time intervals or leap
* seconds, and it crudely estimates leap years. A more accurate value
* for days per years is 365.2422.
*/
#define SECS_PER_YEAR (36525 * 864) /* avoid floating-point computation */
#define SECS_PER_DAY 86400
#define SECS_PER_HOUR 3600
#define SECS_PER_MINUTE 60
#define MINS_PER_HOUR 60
#define USECS_PER_DAY INT64CONST(86400000000)
#define USECS_PER_HOUR INT64CONST(3600000000)
#define USECS_PER_MINUTE INT64CONST(60000000)
#define USECS_PER_SEC INT64CONST(1000000)
/*
* We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
* Currently, the record holders for wackiest offsets in actual use are zones
* Asia/Manila, at -15:56:00 until 1844, and America/Metlakatla, at +15:13:42
* until 1867. If we were to reject such values we would fail to dump and
* restore old timestamptz values with these zone settings.
*/
#define MAX_TZDISP_HOUR 15 /* maximum allowed hour part */
#define TZDISP_LIMIT ((MAX_TZDISP_HOUR + 1) * SECS_PER_HOUR)
/*
* DT_NOBEGIN represents timestamp -infinity; DT_NOEND represents +infinity
*/
#define DT_NOBEGIN PG_INT64_MIN
#define DT_NOEND PG_INT64_MAX
#define TIMESTAMP_NOBEGIN(j) \
do {(j) = DT_NOBEGIN;} while (0)
#define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
#define TIMESTAMP_NOEND(j) \
do {(j) = DT_NOEND;} while (0)
#define TIMESTAMP_IS_NOEND(j) ((j) == DT_NOEND)
#define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
/*
* Infinite intervals are represented by setting all fields to the minimum or
* maximum integer values.
*/
#define INTERVAL_NOBEGIN(i) \
do { \
(i)->time = PG_INT64_MIN; \
(i)->day = PG_INT32_MIN; \
(i)->month = PG_INT32_MIN; \
} while (0)
#define INTERVAL_IS_NOBEGIN(i) \
((i)->month == PG_INT32_MIN && (i)->day == PG_INT32_MIN && (i)->time == PG_INT64_MIN)
#define INTERVAL_NOEND(i) \
do { \
(i)->time = PG_INT64_MAX; \
(i)->day = PG_INT32_MAX; \
(i)->month = PG_INT32_MAX; \
} while (0)
#define INTERVAL_IS_NOEND(i) \
((i)->month == PG_INT32_MAX && (i)->day == PG_INT32_MAX && (i)->time == PG_INT64_MAX)
#define INTERVAL_NOT_FINITE(i) (INTERVAL_IS_NOBEGIN(i) || INTERVAL_IS_NOEND(i))
/*
* Julian date support.
*
* date2j() and j2date() nominally handle the Julian date range 0..INT_MAX,
* or 4714-11-24 BC to 5874898-06-03 AD. In practice, date2j() will work and
* give correct negative Julian dates for dates before 4714-11-24 BC as well.
* We rely on it to do so back to 4714-11-01 BC. Allowing at least one day's
* slop is necessary so that timestamp rotation doesn't produce dates that
* would be rejected on input. For example, '4714-11-24 00:00 GMT BC' is a
* legal timestamptz value, but in zones east of Greenwich it would print as
* sometime in the afternoon of 4714-11-23 BC; if we couldn't process such a
* date we'd have a dump/reload failure. So the idea is for IS_VALID_JULIAN
* to accept a slightly wider range of dates than we really support, and
* then we apply the exact checks in IS_VALID_DATE or IS_VALID_TIMESTAMP,
* after timezone rotation if any. To save a few cycles, we can make
* IS_VALID_JULIAN check only to the month boundary, since its exact cutoffs
* are not very critical in this scheme.
*
* It is correct that JULIAN_MINYEAR is -4713, not -4714; it is defined to
* allow easy comparison to tm_year values, in which we follow the convention
* that tm_year <= 0 represents abs(tm_year)+1 BC.
*/
#define JULIAN_MINYEAR (-4713)
#define JULIAN_MINMONTH (11)
#define JULIAN_MINDAY (24)
#define JULIAN_MAXYEAR (5874898)
#define JULIAN_MAXMONTH (6)
#define JULIAN_MAXDAY (3)
#define IS_VALID_JULIAN(y,m,d) \
(((y) > JULIAN_MINYEAR || \
((y) == JULIAN_MINYEAR && ((m) >= JULIAN_MINMONTH))) && \
((y) < JULIAN_MAXYEAR || \
((y) == JULIAN_MAXYEAR && ((m) < JULIAN_MAXMONTH))))
/* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */
#define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
/*
* Range limits for dates and timestamps.
*
* We have traditionally allowed Julian day zero as a valid datetime value,
* so that is the lower bound for both dates and timestamps.
*
* The upper limit for dates is 5874897-12-31, which is a bit less than what
* the Julian-date code can allow. For timestamps, the upper limit is
* 294276-12-31. The int64 overflow limit would be a few days later; again,
* leaving some slop avoids worries about corner-case overflow, and provides
* a simpler user-visible definition.
*/
/* First allowed date, and first disallowed date, in Julian-date form */
#define DATETIME_MIN_JULIAN (0)
#define DATE_END_JULIAN (2147483494) /* == date2j(JULIAN_MAXYEAR, 1, 1) */
#define TIMESTAMP_END_JULIAN (109203528) /* == date2j(294277, 1, 1) */
/* Timestamp limits */
#define MIN_TIMESTAMP INT64CONST(-211813488000000000)
/* == (DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
#define END_TIMESTAMP INT64CONST(9223371331200000000)
/* == (TIMESTAMP_END_JULIAN - POSTGRES_EPOCH_JDATE) * USECS_PER_DAY */
/* Range-check a date (given in Postgres, not Julian, numbering) */
#define IS_VALID_DATE(d) \
((DATETIME_MIN_JULIAN - POSTGRES_EPOCH_JDATE) <= (d) && \
(d) < (DATE_END_JULIAN - POSTGRES_EPOCH_JDATE))
/* Range-check a timestamp */
#define IS_VALID_TIMESTAMP(t) (MIN_TIMESTAMP <= (t) && (t) < END_TIMESTAMP)
#endif /* DATATYPE_TIMESTAMP_H */
|