diff options
Diffstat (limited to 'src/include/datatype/timestamp.h')
-rw-r--r-- | src/include/datatype/timestamp.h | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/include/datatype/timestamp.h b/src/include/datatype/timestamp.h new file mode 100644 index 00000000000..fa68dd9e190 --- /dev/null +++ b/src/include/datatype/timestamp.h @@ -0,0 +1,163 @@ +/*------------------------------------------------------------------------- + * + * 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-2011, 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 + +#include <math.h> +#include <limits.h> +#include <float.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 + * + * We have two implementations, one that uses int64 values with units of + * microseconds, and one that uses double values with units of seconds. + * + * TimeOffset and fsec_t are convenience typedefs for temporary variables + * that are of different types in the two cases. Do not use fsec_t in values + * stored on-disk, since it is not the same size in both implementations. + * Also, fsec_t is only meant for *fractional* seconds; beware of overflow + * if the value you need to store could be many seconds. + */ + +#ifdef HAVE_INT64_TIMESTAMP + +typedef int64 Timestamp; +typedef int64 TimestampTz; +typedef int64 TimeOffset; +typedef int32 fsec_t; /* fractional seconds (in microseconds) */ +#else + +typedef double Timestamp; +typedef double TimestampTz; +typedef double TimeOffset; +typedef double fsec_t; /* fractional seconds (in seconds) */ +#endif + +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; + + +#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) + +/* + * DT_NOBEGIN represents timestamp -infinity; DT_NOEND represents +infinity + */ +#ifdef HAVE_INT64_TIMESTAMP +#define DT_NOBEGIN (-INT64CONST(0x7fffffffffffffff) - 1) +#define DT_NOEND (INT64CONST(0x7fffffffffffffff)) +#else /* !HAVE_INT64_TIMESTAMP */ +#ifdef HUGE_VAL +#define DT_NOBEGIN (-HUGE_VAL) +#define DT_NOEND (HUGE_VAL) +#else +#define DT_NOBEGIN (-DBL_MAX) +#define DT_NOEND (DBL_MAX) +#endif +#endif /* HAVE_INT64_TIMESTAMP */ + +#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)) + + +/* + * Julian date support. + * + * IS_VALID_JULIAN checks the minimum date exactly, but is a bit sloppy + * about the maximum, since it's far enough out to not be especially + * interesting. + */ + +#define JULIAN_MINYEAR (-4713) +#define JULIAN_MINMONTH (11) +#define JULIAN_MINDAY (24) +#define JULIAN_MAXYEAR (5874898) + +#define IS_VALID_JULIAN(y,m,d) \ + (((y) > JULIAN_MINYEAR \ + || ((y) == JULIAN_MINYEAR && \ + ((m) > JULIAN_MINMONTH \ + || ((m) == JULIAN_MINMONTH && (d) >= JULIAN_MINDAY)))) \ + && (y) < JULIAN_MAXYEAR) + +#define JULIAN_MAX (2147483494) /* == date2j(JULIAN_MAXYEAR, 1, 1) */ + +/* 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) */ + +#endif /* DATATYPE_TIMESTAMP_H */ |