Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Functions | Variables

timestamp.c File Reference

#include "postgres.h"
#include <ctype.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <sys/time.h>
#include "access/hash.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "parser/scansup.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
Include dependency graph for timestamp.c:

Go to the source code of this file.

Data Structures

struct  generate_series_timestamp_fctx
struct  generate_series_timestamptz_fctx

Defines

#define TIMESTAMP_GT(t1, t2)   DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))
#define TIMESTAMP_LT(t1, t2)   DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2))

Functions

static TimeOffset time2t (const int hour, const int min, const int sec, const fsec_t fsec)
static void EncodeSpecialTimestamp (Timestamp dt, char *str)
static Timestamp dt2local (Timestamp dt, int timezone)
static void AdjustTimestampForTypmod (Timestamp *time, int32 typmod)
static void AdjustIntervalForTypmod (Interval *interval, int32 typmod)
static TimestampTz timestamp2timestamptz (Timestamp timestamp)
static int32 anytimestamp_typmodin (bool istz, ArrayType *ta)
static char * anytimestamp_typmodout (bool istz, int32 typmod)
Datum timestamp_in (PG_FUNCTION_ARGS)
Datum timestamp_out (PG_FUNCTION_ARGS)
Datum timestamp_recv (PG_FUNCTION_ARGS)
Datum timestamp_send (PG_FUNCTION_ARGS)
Datum timestamptypmodin (PG_FUNCTION_ARGS)
Datum timestamptypmodout (PG_FUNCTION_ARGS)
Datum timestamp_transform (PG_FUNCTION_ARGS)
Datum timestamp_scale (PG_FUNCTION_ARGS)
Datum timestamptz_in (PG_FUNCTION_ARGS)
Datum timestamptz_out (PG_FUNCTION_ARGS)
Datum timestamptz_recv (PG_FUNCTION_ARGS)
Datum timestamptz_send (PG_FUNCTION_ARGS)
Datum timestamptztypmodin (PG_FUNCTION_ARGS)
Datum timestamptztypmodout (PG_FUNCTION_ARGS)
Datum timestamptz_scale (PG_FUNCTION_ARGS)
Datum interval_in (PG_FUNCTION_ARGS)
Datum interval_out (PG_FUNCTION_ARGS)
Datum interval_recv (PG_FUNCTION_ARGS)
Datum interval_send (PG_FUNCTION_ARGS)
Datum intervaltypmodin (PG_FUNCTION_ARGS)
Datum intervaltypmodout (PG_FUNCTION_ARGS)
Datum interval_transform (PG_FUNCTION_ARGS)
Datum interval_scale (PG_FUNCTION_ARGS)
Datum now (PG_FUNCTION_ARGS)
Datum statement_timestamp (PG_FUNCTION_ARGS)
Datum clock_timestamp (PG_FUNCTION_ARGS)
Datum pg_postmaster_start_time (PG_FUNCTION_ARGS)
Datum pg_conf_load_time (PG_FUNCTION_ARGS)
TimestampTz GetCurrentTimestamp (void)
int64 GetCurrentIntegerTimestamp (void)
TimestampTz IntegerTimestampToTimestampTz (int64 timestamp)
void TimestampDifference (TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
bool TimestampDifferenceExceeds (TimestampTz start_time, TimestampTz stop_time, int msec)
TimestampTz time_t_to_timestamptz (pg_time_t tm)
pg_time_t timestamptz_to_time_t (TimestampTz t)
const char * timestamptz_to_str (TimestampTz t)
void dt2time (Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
int timestamp2tm (Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
int tm2timestamp (struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
int interval2tm (Interval span, struct pg_tm *tm, fsec_t *fsec)
int tm2interval (struct pg_tm *tm, fsec_t fsec, Interval *span)
Datum timestamp_finite (PG_FUNCTION_ARGS)
Datum interval_finite (PG_FUNCTION_ARGS)
void GetEpochTime (struct pg_tm *tm)
Timestamp SetEpochTimestamp (void)
int timestamp_cmp_internal (Timestamp dt1, Timestamp dt2)
Datum timestamp_eq (PG_FUNCTION_ARGS)
Datum timestamp_ne (PG_FUNCTION_ARGS)
Datum timestamp_lt (PG_FUNCTION_ARGS)
Datum timestamp_gt (PG_FUNCTION_ARGS)
Datum timestamp_le (PG_FUNCTION_ARGS)
Datum timestamp_ge (PG_FUNCTION_ARGS)
Datum timestamp_cmp (PG_FUNCTION_ARGS)
static int timestamp_fastcmp (Datum x, Datum y, SortSupport ssup)
Datum timestamp_sortsupport (PG_FUNCTION_ARGS)
Datum timestamp_hash (PG_FUNCTION_ARGS)
Datum timestamp_eq_timestamptz (PG_FUNCTION_ARGS)
Datum timestamp_ne_timestamptz (PG_FUNCTION_ARGS)
Datum timestamp_lt_timestamptz (PG_FUNCTION_ARGS)
Datum timestamp_gt_timestamptz (PG_FUNCTION_ARGS)
Datum timestamp_le_timestamptz (PG_FUNCTION_ARGS)
Datum timestamp_ge_timestamptz (PG_FUNCTION_ARGS)
Datum timestamp_cmp_timestamptz (PG_FUNCTION_ARGS)
Datum timestamptz_eq_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_ne_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_lt_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_gt_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_le_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_ge_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_cmp_timestamp (PG_FUNCTION_ARGS)
static TimeOffset interval_cmp_value (const Interval *interval)
static int interval_cmp_internal (Interval *interval1, Interval *interval2)
Datum interval_eq (PG_FUNCTION_ARGS)
Datum interval_ne (PG_FUNCTION_ARGS)
Datum interval_lt (PG_FUNCTION_ARGS)
Datum interval_gt (PG_FUNCTION_ARGS)
Datum interval_le (PG_FUNCTION_ARGS)
Datum interval_ge (PG_FUNCTION_ARGS)
Datum interval_cmp (PG_FUNCTION_ARGS)
Datum interval_hash (PG_FUNCTION_ARGS)
Datum overlaps_timestamp (PG_FUNCTION_ARGS)
Datum timestamp_smaller (PG_FUNCTION_ARGS)
Datum timestamp_larger (PG_FUNCTION_ARGS)
Datum timestamp_mi (PG_FUNCTION_ARGS)
Datum interval_justify_interval (PG_FUNCTION_ARGS)
Datum interval_justify_hours (PG_FUNCTION_ARGS)
Datum interval_justify_days (PG_FUNCTION_ARGS)
Datum timestamp_pl_interval (PG_FUNCTION_ARGS)
Datum timestamp_mi_interval (PG_FUNCTION_ARGS)
Datum timestamptz_pl_interval (PG_FUNCTION_ARGS)
Datum timestamptz_mi_interval (PG_FUNCTION_ARGS)
Datum interval_um (PG_FUNCTION_ARGS)
Datum interval_smaller (PG_FUNCTION_ARGS)
Datum interval_larger (PG_FUNCTION_ARGS)
Datum interval_pl (PG_FUNCTION_ARGS)
Datum interval_mi (PG_FUNCTION_ARGS)
Datum interval_mul (PG_FUNCTION_ARGS)
Datum mul_d_interval (PG_FUNCTION_ARGS)
Datum interval_div (PG_FUNCTION_ARGS)
Datum interval_accum (PG_FUNCTION_ARGS)
Datum interval_avg (PG_FUNCTION_ARGS)
Datum timestamp_age (PG_FUNCTION_ARGS)
Datum timestamptz_age (PG_FUNCTION_ARGS)
Datum timestamp_trunc (PG_FUNCTION_ARGS)
Datum timestamptz_trunc (PG_FUNCTION_ARGS)
Datum interval_trunc (PG_FUNCTION_ARGS)
int isoweek2j (int year, int week)
void isoweek2date (int woy, int *year, int *mon, int *mday)
void isoweekdate2date (int isoweek, int wday, int *year, int *mon, int *mday)
int date2isoweek (int year, int mon, int mday)
int date2isoyear (int year, int mon, int mday)
int date2isoyearday (int year, int mon, int mday)
Datum timestamp_part (PG_FUNCTION_ARGS)
Datum timestamptz_part (PG_FUNCTION_ARGS)
Datum interval_part (PG_FUNCTION_ARGS)
Datum timestamp_zone (PG_FUNCTION_ARGS)
Datum timestamp_izone (PG_FUNCTION_ARGS)
Datum timestamp_timestamptz (PG_FUNCTION_ARGS)
Datum timestamptz_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_zone (PG_FUNCTION_ARGS)
Datum timestamptz_izone (PG_FUNCTION_ARGS)
Datum generate_series_timestamp (PG_FUNCTION_ARGS)
Datum generate_series_timestamptz (PG_FUNCTION_ARGS)

Variables

TimestampTz PgStartTime
TimestampTz PgReloadTime

Define Documentation

#define TIMESTAMP_GT (   t1,
  t2 
)    DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))

Referenced by overlaps_timestamp().

#define TIMESTAMP_LT (   t1,
  t2 
)    DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2))

Referenced by overlaps_timestamp().


Function Documentation

static void AdjustIntervalForTypmod ( Interval interval,
int32  typmod 
) [static]

Definition at line 1009 of file timestamp.c.

References DAY, Interval::day, elog, ereport, errcode(), errmsg(), ERROR, HOUR, INT64CONST, INTERVAL_FULL_PRECISION, INTERVAL_FULL_RANGE, INTERVAL_MASK, INTERVAL_PRECISION, INTERVAL_RANGE, MAX_INTERVAL_PRECISION, MINUTE, MONTH, Interval::month, MONTHS_PER_YEAR, range(), rint(), SECOND, SECS_PER_HOUR, SECS_PER_MINUTE, Interval::time, USECS_PER_HOUR, USECS_PER_MINUTE, and YEAR.

Referenced by interval_in(), interval_recv(), and interval_scale().

{
#ifdef HAVE_INT64_TIMESTAMP
    static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
        INT64CONST(1000000),
        INT64CONST(100000),
        INT64CONST(10000),
        INT64CONST(1000),
        INT64CONST(100),
        INT64CONST(10),
        INT64CONST(1)
    };

    static const int64 IntervalOffsets[MAX_INTERVAL_PRECISION + 1] = {
        INT64CONST(500000),
        INT64CONST(50000),
        INT64CONST(5000),
        INT64CONST(500),
        INT64CONST(50),
        INT64CONST(5),
        INT64CONST(0)
    };
#else
    static const double IntervalScales[MAX_INTERVAL_PRECISION + 1] = {
        1,
        10,
        100,
        1000,
        10000,
        100000,
        1000000
    };
#endif

    /*
     * Unspecified range and precision? Then not necessary to adjust. Setting
     * typmod to -1 is the convention for all data types.
     */
    if (typmod >= 0)
    {
        int         range = INTERVAL_RANGE(typmod);
        int         precision = INTERVAL_PRECISION(typmod);

        /*
         * Our interpretation of intervals with a limited set of fields is
         * that fields to the right of the last one specified are zeroed out,
         * but those to the left of it remain valid.  Thus for example there
         * is no operational difference between INTERVAL YEAR TO MONTH and
         * INTERVAL MONTH.  In some cases we could meaningfully enforce that
         * higher-order fields are zero; for example INTERVAL DAY could reject
         * nonzero "month" field.  However that seems a bit pointless when we
         * can't do it consistently.  (We cannot enforce a range limit on the
         * highest expected field, since we do not have any equivalent of
         * SQL's <interval leading field precision>.)  If we ever decide to
         * revisit this, interval_transform will likely require adjusting.
         *
         * Note: before PG 8.4 we interpreted a limited set of fields as
         * actually causing a "modulo" operation on a given value, potentially
         * losing high-order as well as low-order information.  But there is
         * no support for such behavior in the standard, and it seems fairly
         * undesirable on data consistency grounds anyway.  Now we only
         * perform truncation or rounding of low-order fields.
         */
        if (range == INTERVAL_FULL_RANGE)
        {
            /* Do nothing... */
        }
        else if (range == INTERVAL_MASK(YEAR))
        {
            interval->month = (interval->month / MONTHS_PER_YEAR) * MONTHS_PER_YEAR;
            interval->day = 0;
            interval->time = 0;
        }
        else if (range == INTERVAL_MASK(MONTH))
        {
            interval->day = 0;
            interval->time = 0;
        }
        /* YEAR TO MONTH */
        else if (range == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))
        {
            interval->day = 0;
            interval->time = 0;
        }
        else if (range == INTERVAL_MASK(DAY))
        {
            interval->time = 0;
        }
        else if (range == INTERVAL_MASK(HOUR))
        {
#ifdef HAVE_INT64_TIMESTAMP
            interval->time = (interval->time / USECS_PER_HOUR) *
                USECS_PER_HOUR;
#else
            interval->time = ((int) (interval->time / SECS_PER_HOUR)) * (double) SECS_PER_HOUR;
#endif
        }
        else if (range == INTERVAL_MASK(MINUTE))
        {
#ifdef HAVE_INT64_TIMESTAMP
            interval->time = (interval->time / USECS_PER_MINUTE) *
                USECS_PER_MINUTE;
#else
            interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;
#endif
        }
        else if (range == INTERVAL_MASK(SECOND))
        {
            /* fractional-second rounding will be dealt with below */
        }
        /* DAY TO HOUR */
        else if (range == (INTERVAL_MASK(DAY) |
                           INTERVAL_MASK(HOUR)))
        {
#ifdef HAVE_INT64_TIMESTAMP
            interval->time = (interval->time / USECS_PER_HOUR) *
                USECS_PER_HOUR;
#else
            interval->time = ((int) (interval->time / SECS_PER_HOUR)) * (double) SECS_PER_HOUR;
#endif
        }
        /* DAY TO MINUTE */
        else if (range == (INTERVAL_MASK(DAY) |
                           INTERVAL_MASK(HOUR) |
                           INTERVAL_MASK(MINUTE)))
        {
#ifdef HAVE_INT64_TIMESTAMP
            interval->time = (interval->time / USECS_PER_MINUTE) *
                USECS_PER_MINUTE;
#else
            interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;
#endif
        }
        /* DAY TO SECOND */
        else if (range == (INTERVAL_MASK(DAY) |
                           INTERVAL_MASK(HOUR) |
                           INTERVAL_MASK(MINUTE) |
                           INTERVAL_MASK(SECOND)))
        {
            /* fractional-second rounding will be dealt with below */
        }
        /* HOUR TO MINUTE */
        else if (range == (INTERVAL_MASK(HOUR) |
                           INTERVAL_MASK(MINUTE)))
        {
#ifdef HAVE_INT64_TIMESTAMP
            interval->time = (interval->time / USECS_PER_MINUTE) *
                USECS_PER_MINUTE;
#else
            interval->time = ((int) (interval->time / SECS_PER_MINUTE)) * (double) SECS_PER_MINUTE;
#endif
        }
        /* HOUR TO SECOND */
        else if (range == (INTERVAL_MASK(HOUR) |
                           INTERVAL_MASK(MINUTE) |
                           INTERVAL_MASK(SECOND)))
        {
            /* fractional-second rounding will be dealt with below */
        }
        /* MINUTE TO SECOND */
        else if (range == (INTERVAL_MASK(MINUTE) |
                           INTERVAL_MASK(SECOND)))
        {
            /* fractional-second rounding will be dealt with below */
        }
        else
            elog(ERROR, "unrecognized interval typmod: %d", typmod);

        /* Need to adjust subsecond precision? */
        if (precision != INTERVAL_FULL_PRECISION)
        {
            if (precision < 0 || precision > MAX_INTERVAL_PRECISION)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                   errmsg("interval(%d) precision must be between %d and %d",
                          precision, 0, MAX_INTERVAL_PRECISION)));

            /*
             * Note: this round-to-nearest code is not completely consistent
             * about rounding values that are exactly halfway between integral
             * values.  On most platforms, rint() will implement
             * round-to-nearest-even, but the integer code always rounds up
             * (away from zero).  Is it worth trying to be consistent?
             */
#ifdef HAVE_INT64_TIMESTAMP
            if (interval->time >= INT64CONST(0))
            {
                interval->time = ((interval->time +
                                   IntervalOffsets[precision]) /
                                  IntervalScales[precision]) *
                    IntervalScales[precision];
            }
            else
            {
                interval->time = -(((-interval->time +
                                     IntervalOffsets[precision]) /
                                    IntervalScales[precision]) *
                                   IntervalScales[precision]);
            }
#else
            interval->time = rint(((double) interval->time) *
                                  IntervalScales[precision]) /
                IntervalScales[precision];
#endif
        }
    }
}

static void AdjustTimestampForTypmod ( Timestamp time,
int32  typmod 
) [static]

Definition at line 341 of file timestamp.c.

References ereport, errcode(), errmsg(), ERROR, INT64CONST, MAX_TIMESTAMP_PRECISION, rint(), and TIMESTAMP_NOT_FINITE.

Referenced by timestamp_in(), timestamp_recv(), timestamp_scale(), timestamptz_in(), timestamptz_recv(), and timestamptz_scale().

{
#ifdef HAVE_INT64_TIMESTAMP
    static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
        INT64CONST(1000000),
        INT64CONST(100000),
        INT64CONST(10000),
        INT64CONST(1000),
        INT64CONST(100),
        INT64CONST(10),
        INT64CONST(1)
    };

    static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
        INT64CONST(500000),
        INT64CONST(50000),
        INT64CONST(5000),
        INT64CONST(500),
        INT64CONST(50),
        INT64CONST(5),
        INT64CONST(0)
    };
#else
    static const double TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
        1,
        10,
        100,
        1000,
        10000,
        100000,
        1000000
    };
#endif

    if (!TIMESTAMP_NOT_FINITE(*time)
        && (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
    {
        if (typmod < 0 || typmod > MAX_TIMESTAMP_PRECISION)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                  errmsg("timestamp(%d) precision must be between %d and %d",
                         typmod, 0, MAX_TIMESTAMP_PRECISION)));

        /*
         * Note: this round-to-nearest code is not completely consistent about
         * rounding values that are exactly halfway between integral values.
         * On most platforms, rint() will implement round-to-nearest-even, but
         * the integer code always rounds up (away from zero).  Is it worth
         * trying to be consistent?
         */
#ifdef HAVE_INT64_TIMESTAMP
        if (*time >= INT64CONST(0))
        {
            *time = ((*time + TimestampOffsets[typmod]) / TimestampScales[typmod]) *
                TimestampScales[typmod];
        }
        else
        {
            *time = -((((-*time) + TimestampOffsets[typmod]) / TimestampScales[typmod])
                      * TimestampScales[typmod]);
        }
#else
        *time = rint((double) *time * TimestampScales[typmod]) / TimestampScales[typmod];
#endif
    }
}

static int32 anytimestamp_typmodin ( bool  istz,
ArrayType ta 
) [static]

Definition at line 78 of file timestamp.c.

References ArrayGetIntegerTypmods(), ereport, errcode(), errmsg(), ERROR, MAX_TIMESTAMP_PRECISION, and WARNING.

Referenced by timestamptypmodin(), and timestamptztypmodin().

{
    int32       typmod;
    int32      *tl;
    int         n;

    tl = ArrayGetIntegerTypmods(ta, &n);

    /*
     * we're not too tense about good error message here because grammar
     * shouldn't allow wrong number of modifiers for TIMESTAMP
     */
    if (n != 1)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("invalid type modifier")));

    if (*tl < 0)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("TIMESTAMP(%d)%s precision must not be negative",
                        *tl, (istz ? " WITH TIME ZONE" : ""))));
    if (*tl > MAX_TIMESTAMP_PRECISION)
    {
        ereport(WARNING,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
           errmsg("TIMESTAMP(%d)%s precision reduced to maximum allowed, %d",
                  *tl, (istz ? " WITH TIME ZONE" : ""),
                  MAX_TIMESTAMP_PRECISION)));
        typmod = MAX_TIMESTAMP_PRECISION;
    }
    else
        typmod = *tl;

    return typmod;
}

static char* anytimestamp_typmodout ( bool  istz,
int32  typmod 
) [static]

Definition at line 117 of file timestamp.c.

References palloc(), and snprintf().

Referenced by timestamptypmodout(), and timestamptztypmodout().

{
    char       *res = (char *) palloc(64);
    const char *tz = istz ? " with time zone" : " without time zone";

    if (typmod >= 0)
        snprintf(res, 64, "(%d)%s", (int) typmod, tz);
    else
        snprintf(res, 64, "%s", tz);

    return res;
}

Datum clock_timestamp ( PG_FUNCTION_ARGS   ) 
int date2isoweek ( int  year,
int  mon,
int  mday 
)

Definition at line 3847 of file timestamp.c.

References date2j(), and j2day().

Referenced by DCH_to_char(), timestamp_part(), timestamp_trunc(), timestamptz_part(), and timestamptz_trunc().

{
    float8      result;
    int         day0,
                day4,
                dayn;

    /* current day */
    dayn = date2j(year, mon, mday);

    /* fourth day of current year */
    day4 = date2j(year, 1, 4);

    /* day0 == offset to first day of week (Monday) */
    day0 = j2day(day4 - 1);

    /*
     * We need the first week containing a Thursday, otherwise this day falls
     * into the previous year for purposes of counting weeks
     */
    if (dayn < day4 - day0)
    {
        day4 = date2j(year - 1, 1, 4);

        /* day0 == offset to first day of week (Monday) */
        day0 = j2day(day4 - 1);
    }

    result = (dayn - (day4 - day0)) / 7 + 1;

    /*
     * Sometimes the last few days in a year will fall into the first week of
     * the next year, so check for this.
     */
    if (result >= 52)
    {
        day4 = date2j(year + 1, 1, 4);

        /* day0 == offset to first day of week (Monday) */
        day0 = j2day(day4 - 1);

        if (dayn >= day4 - day0)
            result = (dayn - (day4 - day0)) / 7 + 1;
    }

    return (int) result;
}

int date2isoyear ( int  year,
int  mon,
int  mday 
)

Definition at line 3901 of file timestamp.c.

References date2j(), and j2day().

Referenced by date2isoyearday(), DCH_to_char(), timestamp_part(), and timestamptz_part().

{
    float8      result;
    int         day0,
                day4,
                dayn;

    /* current day */
    dayn = date2j(year, mon, mday);

    /* fourth day of current year */
    day4 = date2j(year, 1, 4);

    /* day0 == offset to first day of week (Monday) */
    day0 = j2day(day4 - 1);

    /*
     * We need the first week containing a Thursday, otherwise this day falls
     * into the previous year for purposes of counting weeks
     */
    if (dayn < day4 - day0)
    {
        day4 = date2j(year - 1, 1, 4);

        /* day0 == offset to first day of week (Monday) */
        day0 = j2day(day4 - 1);

        year--;
    }

    result = (dayn - (day4 - day0)) / 7 + 1;

    /*
     * Sometimes the last few days in a year will fall into the first week of
     * the next year, so check for this.
     */
    if (result >= 52)
    {
        day4 = date2j(year + 1, 1, 4);

        /* day0 == offset to first day of week (Monday) */
        day0 = j2day(day4 - 1);

        if (dayn >= day4 - day0)
            year++;
    }

    return year;
}

int date2isoyearday ( int  year,
int  mon,
int  mday 
)

Definition at line 3958 of file timestamp.c.

References date2isoyear(), date2j(), and isoweek2j().

Referenced by DCH_to_char().

{
    return date2j(year, mon, mday) - isoweek2j(date2isoyear(year, mon, mday), 1) + 1;
}

static Timestamp dt2local ( Timestamp  dt,
int  timezone 
) [static]

Definition at line 1784 of file timestamp.c.

Referenced by timestamp_izone(), timestamp_zone(), timestamptz_izone(), timestamptz_zone(), and tm2timestamp().

{
#ifdef HAVE_INT64_TIMESTAMP
    dt -= (tz * USECS_PER_SEC);
#else
    dt -= tz;
#endif
    return dt;
}

void dt2time ( Timestamp  jd,
int *  hour,
int *  min,
int *  sec,
fsec_t fsec 
)

Definition at line 1468 of file timestamp.c.

Referenced by DecodeDateTime(), DecodeTimeOnly(), and timestamp2tm().

{
    TimeOffset  time;

    time = jd;

#ifdef HAVE_INT64_TIMESTAMP
    *hour = time / USECS_PER_HOUR;
    time -= (*hour) * USECS_PER_HOUR;
    *min = time / USECS_PER_MINUTE;
    time -= (*min) * USECS_PER_MINUTE;
    *sec = time / USECS_PER_SEC;
    *fsec = time - (*sec * USECS_PER_SEC);
#else
    *hour = time / SECS_PER_HOUR;
    time -= (*hour) * SECS_PER_HOUR;
    *min = time / SECS_PER_MINUTE;
    time -= (*min) * SECS_PER_MINUTE;
    *sec = time;
    *fsec = time - *sec;
#endif
}   /* dt2time() */

static void EncodeSpecialTimestamp ( Timestamp  dt,
char *  str 
) [static]

Definition at line 1222 of file timestamp.c.

References EARLY, elog, ERROR, LATE, TIMESTAMP_IS_NOBEGIN, and TIMESTAMP_IS_NOEND.

Referenced by timestamp_out(), timestamptz_out(), and timestamptz_to_str().

{
    if (TIMESTAMP_IS_NOBEGIN(dt))
        strcpy(str, EARLY);
    else if (TIMESTAMP_IS_NOEND(dt))
        strcpy(str, LATE);
    else    /* shouldn't happen */
        elog(ERROR, "invalid argument for EncodeSpecialTimestamp");
}

Datum generate_series_timestamp ( PG_FUNCTION_ARGS   ) 

Definition at line 4803 of file timestamp.c.

References generate_series_timestamp_fctx::current, DatumGetTimestamp, DirectFunctionCall2, ereport, errcode(), errmsg(), ERROR, generate_series_timestamp_fctx::finish, interval_cmp_internal(), MemoryContextSwitchTo(), MemSet, FuncCallContext::multi_call_memory_ctx, palloc(), PG_GETARG_INTERVAL_P, PG_GETARG_TIMESTAMP, PointerGetDatum, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, generate_series_timestamp_fctx::step, generate_series_timestamp_fctx::step_sign, timestamp_cmp_internal(), timestamp_pl_interval(), TimestampGetDatum, and FuncCallContext::user_fctx.

{
    FuncCallContext *funcctx;
    generate_series_timestamp_fctx *fctx;
    Timestamp   result;

    /* stuff done only on the first call of the function */
    if (SRF_IS_FIRSTCALL())
    {
        Timestamp   start = PG_GETARG_TIMESTAMP(0);
        Timestamp   finish = PG_GETARG_TIMESTAMP(1);
        Interval   *step = PG_GETARG_INTERVAL_P(2);
        MemoryContext oldcontext;
        Interval    interval_zero;

        /* create a function context for cross-call persistence */
        funcctx = SRF_FIRSTCALL_INIT();

        /*
         * switch to memory context appropriate for multiple function calls
         */
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

        /* allocate memory for user context */
        fctx = (generate_series_timestamp_fctx *)
            palloc(sizeof(generate_series_timestamp_fctx));

        /*
         * Use fctx to keep state from call to call. Seed current with the
         * original start value
         */
        fctx->current = start;
        fctx->finish = finish;
        fctx->step = *step;

        /* Determine sign of the interval */
        MemSet(&interval_zero, 0, sizeof(Interval));
        fctx->step_sign = interval_cmp_internal(&fctx->step, &interval_zero);

        if (fctx->step_sign == 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("step size cannot equal zero")));

        funcctx->user_fctx = fctx;
        MemoryContextSwitchTo(oldcontext);
    }

    /* stuff done on every call of the function */
    funcctx = SRF_PERCALL_SETUP();

    /*
     * get the saved state and use current as the result for this iteration
     */
    fctx = funcctx->user_fctx;
    result = fctx->current;

    if (fctx->step_sign > 0 ?
        timestamp_cmp_internal(result, fctx->finish) <= 0 :
        timestamp_cmp_internal(result, fctx->finish) >= 0)
    {
        /* increment current in preparation for next iteration */
        fctx->current = DatumGetTimestamp(
                                   DirectFunctionCall2(timestamp_pl_interval,
                                            TimestampGetDatum(fctx->current),
                                              PointerGetDatum(&fctx->step)));

        /* do when there is more left to send */
        SRF_RETURN_NEXT(funcctx, TimestampGetDatum(result));
    }
    else
    {
        /* do when there is no more left */
        SRF_RETURN_DONE(funcctx);
    }
}

Datum generate_series_timestamptz ( PG_FUNCTION_ARGS   ) 

Definition at line 4884 of file timestamp.c.

References generate_series_timestamptz_fctx::current, DatumGetTimestampTz, DirectFunctionCall2, ereport, errcode(), errmsg(), ERROR, generate_series_timestamptz_fctx::finish, interval_cmp_internal(), MemoryContextSwitchTo(), MemSet, FuncCallContext::multi_call_memory_ctx, palloc(), PG_GETARG_INTERVAL_P, PG_GETARG_TIMESTAMPTZ, PointerGetDatum, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, generate_series_timestamptz_fctx::step, generate_series_timestamptz_fctx::step_sign, timestamp_cmp_internal(), timestamptz_pl_interval(), TimestampTzGetDatum, and FuncCallContext::user_fctx.

{
    FuncCallContext *funcctx;
    generate_series_timestamptz_fctx *fctx;
    TimestampTz result;

    /* stuff done only on the first call of the function */
    if (SRF_IS_FIRSTCALL())
    {
        TimestampTz start = PG_GETARG_TIMESTAMPTZ(0);
        TimestampTz finish = PG_GETARG_TIMESTAMPTZ(1);
        Interval   *step = PG_GETARG_INTERVAL_P(2);
        MemoryContext oldcontext;
        Interval    interval_zero;

        /* create a function context for cross-call persistence */
        funcctx = SRF_FIRSTCALL_INIT();

        /*
         * switch to memory context appropriate for multiple function calls
         */
        oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

        /* allocate memory for user context */
        fctx = (generate_series_timestamptz_fctx *)
            palloc(sizeof(generate_series_timestamptz_fctx));

        /*
         * Use fctx to keep state from call to call. Seed current with the
         * original start value
         */
        fctx->current = start;
        fctx->finish = finish;
        fctx->step = *step;

        /* Determine sign of the interval */
        MemSet(&interval_zero, 0, sizeof(Interval));
        fctx->step_sign = interval_cmp_internal(&fctx->step, &interval_zero);

        if (fctx->step_sign == 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("step size cannot equal zero")));

        funcctx->user_fctx = fctx;
        MemoryContextSwitchTo(oldcontext);
    }

    /* stuff done on every call of the function */
    funcctx = SRF_PERCALL_SETUP();

    /*
     * get the saved state and use current as the result for this iteration
     */
    fctx = funcctx->user_fctx;
    result = fctx->current;

    if (fctx->step_sign > 0 ?
        timestamp_cmp_internal(result, fctx->finish) <= 0 :
        timestamp_cmp_internal(result, fctx->finish) >= 0)
    {
        /* increment current in preparation for next iteration */
        fctx->current = DatumGetTimestampTz(
                                 DirectFunctionCall2(timestamptz_pl_interval,
                                          TimestampTzGetDatum(fctx->current),
                                              PointerGetDatum(&fctx->step)));

        /* do when there is more left to send */
        SRF_RETURN_NEXT(funcctx, TimestampTzGetDatum(result));
    }
    else
    {
        /* do when there is no more left */
        SRF_RETURN_DONE(funcctx);
    }
}

int64 GetCurrentIntegerTimestamp ( void   ) 

Definition at line 1297 of file timestamp.c.

References gettimeofday(), NULL, POSTGRES_EPOCH_JDATE, and UNIX_EPOCH_JDATE.

Referenced by WalSndKeepalive(), XLogSend(), XLogWalRcvSendHSFeedback(), and XLogWalRcvSendReply().

{
    int64 result;
    struct timeval tp;

    gettimeofday(&tp, NULL);

    result = (int64) tp.tv_sec -
        ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);

    result = (result * USECS_PER_SEC) + tp.tv_usec;

    return result;
}

TimestampTz GetCurrentTimestamp ( void   ) 

Definition at line 1269 of file timestamp.c.

References gettimeofday(), NULL, POSTGRES_EPOCH_JDATE, and UNIX_EPOCH_JDATE.

Referenced by assign_backendlist_entry(), asyncQueueFillWarning(), autovac_refresh_stats(), AutoVacLauncherMain(), backend_read_statsfile(), BackendInitialize(), check_log_duration(), CheckPointBuffers(), CleanupBackgroundWorker(), clock_timestamp(), CreateCheckPoint(), CreateRestartPoint(), DetermineSleepTime(), disable_timeout(), disable_timeouts(), do_analyze_rel(), do_start_worker(), enable_timeout_after(), enable_timeout_at(), enable_timeouts(), GetCurrentTransactionStopTimestamp(), GetReplicationApplyDelay(), handle_sig_alarm(), launcher_determine_sleep(), lazy_vacuum_rel(), log_disconnections(), LogCheckpointEnd(), md5_crypt_verify(), pgstat_bestart(), pgstat_read_statsfiles(), pgstat_recv_inquiry(), pgstat_recv_resetsharedcounter(), pgstat_recv_resetsinglecounter(), pgstat_report_activity(), pgstat_report_analyze(), pgstat_report_autovac(), pgstat_report_vacuum(), pgstat_write_statsfiles(), PostgresMain(), PostmasterMain(), PrepareTransaction(), ProcessRepliesIfAny(), ProcessWalSndrMessage(), ProcSleep(), rebuild_database_list(), RecordTransactionAbort(), RecordTransactionAbortPrepared(), RecordTransactionCommitPrepared(), reset_dbentry_counters(), ResolveRecoveryConflictWithBufferPin(), ResolveRecoveryConflictWithVirtualXIDs(), SetCurrentStatementStartTimestamp(), SetCurrentTransactionStopTimestamp(), StartOneBackgroundWorker(), StartupXLOG(), WaitExceedsMaxStandbyDelay(), WaitForWALToBecomeAvailable(), WalReceiverMain(), WalSndLoop(), XLogFileRead(), XLogRestorePoint(), XLogWalRcvSendHSFeedback(), and XLogWalRcvSendReply().

{
    TimestampTz result;
    struct timeval tp;

    gettimeofday(&tp, NULL);

    result = (TimestampTz) tp.tv_sec -
        ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);

#ifdef HAVE_INT64_TIMESTAMP
    result = (result * USECS_PER_SEC) + tp.tv_usec;
#else
    result = result + (tp.tv_usec / 1000000.0);
#endif

    return result;
}

void GetEpochTime ( struct pg_tm tm  ) 

Definition at line 1820 of file timestamp.c.

References epoch, pg_gmtime(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, and pg_tm::tm_year.

Referenced by date_in(), PGTYPESdate_from_asc(), and SetEpochTimestamp().

{
    struct pg_tm *t0;
    pg_time_t   epoch = 0;

    t0 = pg_gmtime(&epoch);

    tm->tm_year = t0->tm_year;
    tm->tm_mon = t0->tm_mon;
    tm->tm_mday = t0->tm_mday;
    tm->tm_hour = t0->tm_hour;
    tm->tm_min = t0->tm_min;
    tm->tm_sec = t0->tm_sec;

    tm->tm_year += 1900;
    tm->tm_mon++;
}

TimestampTz IntegerTimestampToTimestampTz ( int64  timestamp  ) 

Definition at line 1321 of file timestamp.c.

Referenced by XLogWalRcvProcessMsg().

{
    TimestampTz result;

    result = timestamp / USECS_PER_SEC;
    result += (timestamp % USECS_PER_SEC) / 1000000.0;

    return result;
}

int interval2tm ( Interval  span,
struct pg_tm tm,
fsec_t fsec 
)

Definition at line 1714 of file timestamp.c.

References Interval::day, Interval::month, SECS_PER_HOUR, SECS_PER_MINUTE, Interval::time, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, TMODULO, and TSROUND.

Referenced by interval_out(), interval_part(), interval_to_char(), interval_trunc(), and PGTYPESinterval_to_asc().

{
    TimeOffset  time;
    TimeOffset  tfrac;

    tm->tm_year = span.month / MONTHS_PER_YEAR;
    tm->tm_mon = span.month % MONTHS_PER_YEAR;
    tm->tm_mday = span.day;
    time = span.time;

#ifdef HAVE_INT64_TIMESTAMP
    tfrac = time / USECS_PER_HOUR;
    time -= tfrac * USECS_PER_HOUR;
    tm->tm_hour = tfrac;        /* could overflow ... */
    tfrac = time / USECS_PER_MINUTE;
    time -= tfrac * USECS_PER_MINUTE;
    tm->tm_min = tfrac;
    tfrac = time / USECS_PER_SEC;
    *fsec = time - (tfrac * USECS_PER_SEC);
    tm->tm_sec = tfrac;
#else
recalc:
    TMODULO(time, tfrac, (double) SECS_PER_HOUR);
    tm->tm_hour = tfrac;        /* could overflow ... */
    TMODULO(time, tfrac, (double) SECS_PER_MINUTE);
    tm->tm_min = tfrac;
    TMODULO(time, tfrac, 1.0);
    tm->tm_sec = tfrac;
    time = TSROUND(time);
    /* roundoff may need to propagate to higher-order fields */
    if (time >= 1.0)
    {
        time = ceil(span.time);
        goto recalc;
    }
    *fsec = time;
#endif

    return 0;
}

Datum interval_accum ( PG_FUNCTION_ARGS   ) 

Definition at line 3062 of file timestamp.c.

References construct_array(), DatumGetIntervalP, DatumGetPointer, deconstruct_array(), DirectFunctionCall2, elog, ERROR, interval_pl(), INTERVALOID, IntervalPGetDatum, NULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_INTERVAL_P, and PG_RETURN_ARRAYTYPE_P.

{
    ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    Interval   *newval = PG_GETARG_INTERVAL_P(1);
    Datum      *transdatums;
    int         ndatums;
    Interval    sumX,
                N;
    Interval   *newsum;
    ArrayType  *result;

    deconstruct_array(transarray,
                      INTERVALOID, sizeof(Interval), false, 'd',
                      &transdatums, NULL, &ndatums);
    if (ndatums != 2)
        elog(ERROR, "expected 2-element interval array");

    /*
     * XXX memcpy, instead of just extracting a pointer, to work around buggy
     * array code: it won't ensure proper alignment of Interval objects on
     * machines where double requires 8-byte alignment. That should be fixed,
     * but in the meantime...
     *
     * Note: must use DatumGetPointer here, not DatumGetIntervalP, else some
     * compilers optimize into double-aligned load/store anyway.
     */
    memcpy((void *) &sumX, DatumGetPointer(transdatums[0]), sizeof(Interval));
    memcpy((void *) &N, DatumGetPointer(transdatums[1]), sizeof(Interval));

    newsum = DatumGetIntervalP(DirectFunctionCall2(interval_pl,
                                                   IntervalPGetDatum(&sumX),
                                                 IntervalPGetDatum(newval)));
    N.time += 1;

    transdatums[0] = IntervalPGetDatum(newsum);
    transdatums[1] = IntervalPGetDatum(&N);

    result = construct_array(transdatums, 2,
                             INTERVALOID, sizeof(Interval), false, 'd');

    PG_RETURN_ARRAYTYPE_P(result);
}

Datum interval_avg ( PG_FUNCTION_ARGS   ) 

Definition at line 3106 of file timestamp.c.

References DatumGetPointer, deconstruct_array(), DirectFunctionCall2, elog, ERROR, Float8GetDatum(), interval_div(), INTERVALOID, IntervalPGetDatum, NULL, PG_GETARG_ARRAYTYPE_P, and PG_RETURN_NULL.

{
    ArrayType  *transarray = PG_GETARG_ARRAYTYPE_P(0);
    Datum      *transdatums;
    int         ndatums;
    Interval    sumX,
                N;

    deconstruct_array(transarray,
                      INTERVALOID, sizeof(Interval), false, 'd',
                      &transdatums, NULL, &ndatums);
    if (ndatums != 2)
        elog(ERROR, "expected 2-element interval array");

    /*
     * XXX memcpy, instead of just extracting a pointer, to work around buggy
     * array code: it won't ensure proper alignment of Interval objects on
     * machines where double requires 8-byte alignment. That should be fixed,
     * but in the meantime...
     *
     * Note: must use DatumGetPointer here, not DatumGetIntervalP, else some
     * compilers optimize into double-aligned load/store anyway.
     */
    memcpy((void *) &sumX, DatumGetPointer(transdatums[0]), sizeof(Interval));
    memcpy((void *) &N, DatumGetPointer(transdatums[1]), sizeof(Interval));

    /* SQL defines AVG of no values to be NULL */
    if (N.time == 0)
        PG_RETURN_NULL();

    return DirectFunctionCall2(interval_div,
                               IntervalPGetDatum(&sumX),
                               Float8GetDatum(N.time));
}

Datum interval_cmp ( PG_FUNCTION_ARGS   ) 

Definition at line 2251 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_INT32.

Referenced by gbt_intvkey_cmp().

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);

    PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));
}

static int interval_cmp_internal ( Interval interval1,
Interval interval2 
) [static]

Definition at line 2188 of file timestamp.c.

References interval_cmp_value().

Referenced by generate_series_timestamp(), generate_series_timestamptz(), interval_cmp(), interval_eq(), interval_ge(), interval_gt(), interval_larger(), interval_le(), interval_lt(), interval_ne(), and interval_smaller().

{
    TimeOffset  span1 = interval_cmp_value(interval1);
    TimeOffset  span2 = interval_cmp_value(interval2);

    return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0);
}

static TimeOffset interval_cmp_value ( const Interval interval  )  [inline, static]

Definition at line 2170 of file timestamp.c.

References Interval::day, DAYS_PER_MONTH, HOURS_PER_DAY, INT64CONST, Interval::month, SECS_PER_DAY, SECS_PER_HOUR, and Interval::time.

Referenced by interval_cmp_internal(), and interval_hash().

{
    TimeOffset  span;

    span = interval->time;

#ifdef HAVE_INT64_TIMESTAMP
    span += interval->month * INT64CONST(30) * USECS_PER_DAY;
    span += interval->day * INT64CONST(24) * USECS_PER_HOUR;
#else
    span += interval->month * ((double) DAYS_PER_MONTH * SECS_PER_DAY);
    span += interval->day * ((double) HOURS_PER_DAY * SECS_PER_HOUR);
#endif

    return span;
}

Datum interval_div ( PG_FUNCTION_ARGS   ) 

Definition at line 3006 of file timestamp.c.

References Abs, Interval::day, DAYS_PER_MONTH, ereport, errcode(), errmsg(), ERROR, Interval::month, palloc(), PG_GETARG_FLOAT8, PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, rint(), SECS_PER_DAY, Interval::time, TSROUND, and USECS_PER_SEC.

Referenced by interval_avg().

{
    Interval   *span = PG_GETARG_INTERVAL_P(0);
    float8      factor = PG_GETARG_FLOAT8(1);
    double      month_remainder_days,
                sec_remainder;
    int32       orig_month = span->month,
                orig_day = span->day;
    Interval   *result;

    result = (Interval *) palloc(sizeof(Interval));

    if (factor == 0.0)
        ereport(ERROR,
                (errcode(ERRCODE_DIVISION_BY_ZERO),
                 errmsg("division by zero")));

    result->month = (int32) (span->month / factor);
    result->day = (int32) (span->day / factor);

    /*
     * Fractional months full days into days.  See comment in interval_mul().
     */
    month_remainder_days = (orig_month / factor - result->month) * DAYS_PER_MONTH;
    month_remainder_days = TSROUND(month_remainder_days);
    sec_remainder = (orig_day / factor - result->day +
           month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
    sec_remainder = TSROUND(sec_remainder);
    if (Abs(sec_remainder) >= SECS_PER_DAY)
    {
        result->day += (int) (sec_remainder / SECS_PER_DAY);
        sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
    }

    /* cascade units down */
    result->day += (int32) month_remainder_days;
#ifdef HAVE_INT64_TIMESTAMP
    result->time = rint(span->time / factor + sec_remainder * USECS_PER_SEC);
#else
    /* See TSROUND comment in interval_mul(). */
    result->time = span->time / factor + sec_remainder;
#endif

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_eq ( PG_FUNCTION_ARGS   ) 

Definition at line 2197 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_BOOL.

Referenced by gbt_intveq().

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);

    PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) == 0);
}

Datum interval_finite ( PG_FUNCTION_ARGS   ) 

Definition at line 1809 of file timestamp.c.

References PG_RETURN_BOOL.

{
    PG_RETURN_BOOL(true);
}

Datum interval_ge ( PG_FUNCTION_ARGS   ) 

Definition at line 2242 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_BOOL.

Referenced by gbt_intvge().

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);

    PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);
}

Datum interval_gt ( PG_FUNCTION_ARGS   ) 

Definition at line 2224 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_BOOL.

Referenced by gbt_intvgt().

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);

    PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) > 0);
}

Datum interval_hash ( PG_FUNCTION_ARGS   ) 
Datum interval_in ( PG_FUNCTION_ARGS   ) 

Definition at line 609 of file timestamp.c.

References AdjustIntervalForTypmod(), DateTimeParseError(), DecodeInterval(), DecodeISO8601Interval(), DTERR_BAD_FORMAT, DTERR_FIELD_OVERFLOW, DTK_DELTA, DTK_INVALID, elog, ereport, errcode(), errmsg(), ERROR, INTERVAL_RANGE, MAXDATEFIELDS, palloc(), ParseDateTime(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_INTERVAL_P, tm, tm2interval(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, and pg_tm::tm_year.

Referenced by check_timezone(), and flatten_set_variable_args().

{
    char       *str = PG_GETARG_CSTRING(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       typmod = PG_GETARG_INT32(2);
    Interval   *result;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;
    int         dtype;
    int         nf;
    int         range;
    int         dterr;
    char       *field[MAXDATEFIELDS];
    int         ftype[MAXDATEFIELDS];
    char        workbuf[256];

    tm->tm_year = 0;
    tm->tm_mon = 0;
    tm->tm_mday = 0;
    tm->tm_hour = 0;
    tm->tm_min = 0;
    tm->tm_sec = 0;
    fsec = 0;

    if (typmod >= 0)
        range = INTERVAL_RANGE(typmod);
    else
        range = INTERVAL_FULL_RANGE;

    dterr = ParseDateTime(str, workbuf, sizeof(workbuf), field,
                          ftype, MAXDATEFIELDS, &nf);
    if (dterr == 0)
        dterr = DecodeInterval(field, ftype, nf, range,
                               &dtype, tm, &fsec);

    /* if those functions think it's a bad format, try ISO8601 style */
    if (dterr == DTERR_BAD_FORMAT)
        dterr = DecodeISO8601Interval(str,
                                      &dtype, tm, &fsec);

    if (dterr != 0)
    {
        if (dterr == DTERR_FIELD_OVERFLOW)
            dterr = DTERR_INTERVAL_OVERFLOW;
        DateTimeParseError(dterr, str, "interval");
    }

    result = (Interval *) palloc(sizeof(Interval));

    switch (dtype)
    {
        case DTK_DELTA:
            if (tm2interval(tm, fsec, result) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("interval out of range")));
            break;

        case DTK_INVALID:
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
              errmsg("date/time value \"%s\" is no longer supported", str)));
            break;

        default:
            elog(ERROR, "unexpected dtype %d while parsing interval \"%s\"",
                 dtype, str);
    }

    AdjustIntervalForTypmod(result, typmod);

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_justify_days ( PG_FUNCTION_ARGS   ) 

Definition at line 2617 of file timestamp.c.

References Interval::day, Interval::month, palloc(), PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, and Interval::time.

{
    Interval   *span = PG_GETARG_INTERVAL_P(0);
    Interval   *result;
    int32       wholemonth;

    result = (Interval *) palloc(sizeof(Interval));
    result->month = span->month;
    result->day = span->day;
    result->time = span->time;

    wholemonth = result->day / DAYS_PER_MONTH;
    result->day -= wholemonth * DAYS_PER_MONTH;
    result->month += wholemonth;

    if (result->month > 0 && result->day < 0)
    {
        result->day += DAYS_PER_MONTH;
        result->month--;
    }
    else if (result->month < 0 && result->day > 0)
    {
        result->day -= DAYS_PER_MONTH;
        result->month++;
    }

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_justify_hours ( PG_FUNCTION_ARGS   ) 

Definition at line 2570 of file timestamp.c.

References Interval::day, Interval::month, palloc(), PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, SECS_PER_DAY, Interval::time, TMODULO, and USECS_PER_DAY.

Referenced by timestamp_mi().

{
    Interval   *span = PG_GETARG_INTERVAL_P(0);
    Interval   *result;
    TimeOffset  wholeday;

    result = (Interval *) palloc(sizeof(Interval));
    result->month = span->month;
    result->day = span->day;
    result->time = span->time;

#ifdef HAVE_INT64_TIMESTAMP
    TMODULO(result->time, wholeday, USECS_PER_DAY);
#else
    TMODULO(result->time, wholeday, (double) SECS_PER_DAY);
#endif
    result->day += wholeday;    /* could overflow... */

    if (result->day > 0 && result->time < 0)
    {
#ifdef HAVE_INT64_TIMESTAMP
        result->time += USECS_PER_DAY;
#else
        result->time += (double) SECS_PER_DAY;
#endif
        result->day--;
    }
    else if (result->day < 0 && result->time > 0)
    {
#ifdef HAVE_INT64_TIMESTAMP
        result->time -= USECS_PER_DAY;
#else
        result->time -= (double) SECS_PER_DAY;
#endif
        result->day++;
    }

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_justify_interval ( PG_FUNCTION_ARGS   ) 

Definition at line 2503 of file timestamp.c.

References Interval::day, Interval::month, palloc(), PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, SECS_PER_DAY, Interval::time, TMODULO, and USECS_PER_DAY.

{
    Interval   *span = PG_GETARG_INTERVAL_P(0);
    Interval   *result;
    TimeOffset  wholeday;
    int32       wholemonth;

    result = (Interval *) palloc(sizeof(Interval));
    result->month = span->month;
    result->day = span->day;
    result->time = span->time;

#ifdef HAVE_INT64_TIMESTAMP
    TMODULO(result->time, wholeday, USECS_PER_DAY);
#else
    TMODULO(result->time, wholeday, (double) SECS_PER_DAY);
#endif
    result->day += wholeday;    /* could overflow... */

    wholemonth = result->day / DAYS_PER_MONTH;
    result->day -= wholemonth * DAYS_PER_MONTH;
    result->month += wholemonth;

    if (result->month > 0 &&
        (result->day < 0 || (result->day == 0 && result->time < 0)))
    {
        result->day += DAYS_PER_MONTH;
        result->month--;
    }
    else if (result->month < 0 &&
             (result->day > 0 || (result->day == 0 && result->time > 0)))
    {
        result->day -= DAYS_PER_MONTH;
        result->month++;
    }

    if (result->day > 0 && result->time < 0)
    {
#ifdef HAVE_INT64_TIMESTAMP
        result->time += USECS_PER_DAY;
#else
        result->time += (double) SECS_PER_DAY;
#endif
        result->day--;
    }
    else if (result->day < 0 && result->time > 0)
    {
#ifdef HAVE_INT64_TIMESTAMP
        result->time -= USECS_PER_DAY;
#else
        result->time -= (double) SECS_PER_DAY;
#endif
        result->day++;
    }

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_larger ( PG_FUNCTION_ARGS   ) 

Definition at line 2882 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_INTERVAL_P.

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);
    Interval   *result;

    if (interval_cmp_internal(interval1, interval2) > 0)
        result = interval1;
    else
        result = interval2;
    PG_RETURN_INTERVAL_P(result);
}

Datum interval_le ( PG_FUNCTION_ARGS   ) 

Definition at line 2233 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_BOOL.

Referenced by gbt_intvle().

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);

    PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) <= 0);
}

Datum interval_lt ( PG_FUNCTION_ARGS   ) 

Definition at line 2215 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_BOOL.

Referenced by abs_interval(), and gbt_intvlt().

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);

    PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) < 0);
}

Datum interval_mi ( PG_FUNCTION_ARGS   ) 

Definition at line 2912 of file timestamp.c.

References Interval::day, Interval::month, palloc(), PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, and Interval::time.

Referenced by interval_dist().

{
    Interval   *span1 = PG_GETARG_INTERVAL_P(0);
    Interval   *span2 = PG_GETARG_INTERVAL_P(1);
    Interval   *result;

    result = (Interval *) palloc(sizeof(Interval));

    result->month = span1->month - span2->month;
    result->day = span1->day - span2->day;
    result->time = span1->time - span2->time;

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_mul ( PG_FUNCTION_ARGS   ) 

Definition at line 2934 of file timestamp.c.

References Abs, Interval::day, DAYS_PER_MONTH, Interval::month, palloc(), PG_GETARG_FLOAT8, PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, rint(), SECS_PER_DAY, Interval::time, TSROUND, and USECS_PER_SEC.

Referenced by mul_d_interval().

{
    Interval   *span = PG_GETARG_INTERVAL_P(0);
    float8      factor = PG_GETARG_FLOAT8(1);
    double      month_remainder_days,
                sec_remainder;
    int32       orig_month = span->month,
                orig_day = span->day;
    Interval   *result;

    result = (Interval *) palloc(sizeof(Interval));

    result->month = (int32) (span->month * factor);
    result->day = (int32) (span->day * factor);

    /*
     * The above correctly handles the whole-number part of the month and day
     * products, but we have to do something with any fractional part
     * resulting when the factor is nonintegral.  We cascade the fractions
     * down to lower units using the conversion factors DAYS_PER_MONTH and
     * SECS_PER_DAY.  Note we do NOT cascade up, since we are not forced to do
     * so by the representation.  The user can choose to cascade up later,
     * using justify_hours and/or justify_days.
     */

    /*
     * Fractional months full days into days.
     *
     * Floating point calculation are inherently inprecise, so these
     * calculations are crafted to produce the most reliable result possible.
     * TSROUND() is needed to more accurately produce whole numbers where
     * appropriate.
     */
    month_remainder_days = (orig_month * factor - result->month) * DAYS_PER_MONTH;
    month_remainder_days = TSROUND(month_remainder_days);
    sec_remainder = (orig_day * factor - result->day +
           month_remainder_days - (int) month_remainder_days) * SECS_PER_DAY;
    sec_remainder = TSROUND(sec_remainder);

    /*
     * Might have 24:00:00 hours due to rounding, or >24 hours because of time
     * cascade from months and days.  It might still be >24 if the combination
     * of cascade and the seconds factor operation itself.
     */
    if (Abs(sec_remainder) >= SECS_PER_DAY)
    {
        result->day += (int) (sec_remainder / SECS_PER_DAY);
        sec_remainder -= (int) (sec_remainder / SECS_PER_DAY) * SECS_PER_DAY;
    }

    /* cascade units down */
    result->day += (int32) month_remainder_days;
#ifdef HAVE_INT64_TIMESTAMP
    result->time = rint(span->time * factor + sec_remainder * USECS_PER_SEC);
#else
    result->time = span->time * factor + sec_remainder;
#endif

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_ne ( PG_FUNCTION_ARGS   ) 

Definition at line 2206 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_BOOL.

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);

    PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) != 0);
}

Datum interval_out ( PG_FUNCTION_ARGS   ) 

Definition at line 691 of file timestamp.c.

References buf, elog, EncodeInterval(), ERROR, interval2tm(), IntervalStyle, MAXDATELEN, PG_GETARG_INTERVAL_P, PG_RETURN_CSTRING, pstrdup(), and tm.

Referenced by flatten_set_variable_args(), show_timezone(), timestamp_izone(), timestamptz_izone(), and timetz_izone().

{
    Interval   *span = PG_GETARG_INTERVAL_P(0);
    char       *result;
    struct pg_tm tt,
               *tm = &tt;
    fsec_t      fsec;
    char        buf[MAXDATELEN + 1];

    if (interval2tm(*span, tm, &fsec) != 0)
        elog(ERROR, "could not convert interval to tm");

    EncodeInterval(tm, fsec, IntervalStyle, buf);

    result = pstrdup(buf);
    PG_RETURN_CSTRING(result);
}

Datum interval_part ( PG_FUNCTION_ARGS   ) 

Definition at line 4390 of file timestamp.c.

References Interval::day, DAYS_PER_MONTH, DAYS_PER_YEAR, DecodeSpecial(), DecodeUnits(), downcase_truncate_identifier(), DTK_CENTURY, DTK_DAY, DTK_DECADE, DTK_EPOCH, DTK_HOUR, DTK_MICROSEC, DTK_MILLENNIUM, DTK_MILLISEC, DTK_MINUTE, DTK_MONTH, DTK_QUARTER, DTK_SECOND, DTK_YEAR, elog, ereport, errcode(), errmsg(), ERROR, interval2tm(), Interval::month, PG_GETARG_INTERVAL_P, PG_GETARG_TEXT_PP, PG_RETURN_FLOAT8, RESERV, SECS_PER_DAY, Interval::time, tm, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, UNITS, UNKNOWN_FIELD, val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

{
    text       *units = PG_GETARG_TEXT_PP(0);
    Interval   *interval = PG_GETARG_INTERVAL_P(1);
    float8      result;
    int         type,
                val;
    char       *lowunits;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;

    lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
                                            VARSIZE_ANY_EXHDR(units),
                                            false);

    type = DecodeUnits(0, lowunits, &val);
    if (type == UNKNOWN_FIELD)
        type = DecodeSpecial(0, lowunits, &val);

    if (type == UNITS)
    {
        if (interval2tm(*interval, tm, &fsec) == 0)
        {
            switch (val)
            {
                case DTK_MICROSEC:
#ifdef HAVE_INT64_TIMESTAMP
                    result = tm->tm_sec * 1000000.0 + fsec;
#else
                    result = (tm->tm_sec + fsec) * 1000000;
#endif
                    break;

                case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
                    result = tm->tm_sec * 1000.0 + fsec / 1000.0;
#else
                    result = (tm->tm_sec + fsec) * 1000;
#endif
                    break;

                case DTK_SECOND:
#ifdef HAVE_INT64_TIMESTAMP
                    result = tm->tm_sec + fsec / 1000000.0;
#else
                    result = tm->tm_sec + fsec;
#endif
                    break;

                case DTK_MINUTE:
                    result = tm->tm_min;
                    break;

                case DTK_HOUR:
                    result = tm->tm_hour;
                    break;

                case DTK_DAY:
                    result = tm->tm_mday;
                    break;

                case DTK_MONTH:
                    result = tm->tm_mon;
                    break;

                case DTK_QUARTER:
                    result = (tm->tm_mon / 3) + 1;
                    break;

                case DTK_YEAR:
                    result = tm->tm_year;
                    break;

                case DTK_DECADE:
                    /* caution: C division may have negative remainder */
                    result = tm->tm_year / 10;
                    break;

                case DTK_CENTURY:
                    /* caution: C division may have negative remainder */
                    result = tm->tm_year / 100;
                    break;

                case DTK_MILLENNIUM:
                    /* caution: C division may have negative remainder */
                    result = tm->tm_year / 1000;
                    break;

                default:
                    ereport(ERROR,
                            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                             errmsg("interval units \"%s\" not supported",
                                    lowunits)));
                    result = 0;
            }

        }
        else
        {
            elog(ERROR, "could not convert interval to tm");
            result = 0;
        }
    }
    else if (type == RESERV && val == DTK_EPOCH)
    {
#ifdef HAVE_INT64_TIMESTAMP
        result = interval->time / 1000000.0;
#else
        result = interval->time;
#endif
        result += ((double) DAYS_PER_YEAR * SECS_PER_DAY) * (interval->month / MONTHS_PER_YEAR);
        result += ((double) DAYS_PER_MONTH * SECS_PER_DAY) * (interval->month % MONTHS_PER_YEAR);
        result += ((double) SECS_PER_DAY) * interval->day;
    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("interval units \"%s\" not recognized",
                        lowunits)));
        result = 0;
    }

    PG_RETURN_FLOAT8(result);
}

Datum interval_pl ( PG_FUNCTION_ARGS   ) 

Definition at line 2896 of file timestamp.c.

References Interval::day, Interval::month, palloc(), PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, and Interval::time.

Referenced by interval_accum().

{
    Interval   *span1 = PG_GETARG_INTERVAL_P(0);
    Interval   *span2 = PG_GETARG_INTERVAL_P(1);
    Interval   *result;

    result = (Interval *) palloc(sizeof(Interval));

    result->month = span1->month + span2->month;
    result->day = span1->day + span2->day;
    result->time = span1->time + span2->time;

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_recv ( PG_FUNCTION_ARGS   ) 

Definition at line 713 of file timestamp.c.

References AdjustIntervalForTypmod(), buf, Interval::day, Interval::month, palloc(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_INTERVAL_P, pq_getmsgfloat8(), pq_getmsgint(), pq_getmsgint64(), and Interval::time.

{
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       typmod = PG_GETARG_INT32(2);
    Interval   *interval;

    interval = (Interval *) palloc(sizeof(Interval));

#ifdef HAVE_INT64_TIMESTAMP
    interval->time = pq_getmsgint64(buf);
#else
    interval->time = pq_getmsgfloat8(buf);
#endif
    interval->day = pq_getmsgint(buf, sizeof(interval->day));
    interval->month = pq_getmsgint(buf, sizeof(interval->month));

    AdjustIntervalForTypmod(interval, typmod);

    PG_RETURN_INTERVAL_P(interval);
}

Datum interval_scale ( PG_FUNCTION_ARGS   ) 

Definition at line 990 of file timestamp.c.

References AdjustIntervalForTypmod(), palloc(), PG_GETARG_INT32, PG_GETARG_INTERVAL_P, and PG_RETURN_INTERVAL_P.

{
    Interval   *interval = PG_GETARG_INTERVAL_P(0);
    int32       typmod = PG_GETARG_INT32(1);
    Interval   *result;

    result = palloc(sizeof(Interval));
    *result = *interval;

    AdjustIntervalForTypmod(result, typmod);

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_send ( PG_FUNCTION_ARGS   ) 

Definition at line 742 of file timestamp.c.

References buf, Interval::day, Interval::month, PG_GETARG_INTERVAL_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendfloat8(), pq_sendint(), pq_sendint64(), and Interval::time.

{
    Interval   *interval = PG_GETARG_INTERVAL_P(0);
    StringInfoData buf;

    pq_begintypsend(&buf);
#ifdef HAVE_INT64_TIMESTAMP
    pq_sendint64(&buf, interval->time);
#else
    pq_sendfloat8(&buf, interval->time);
#endif
    pq_sendint(&buf, interval->day, sizeof(interval->day));
    pq_sendint(&buf, interval->month, sizeof(interval->month));
    PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}

Datum interval_smaller ( PG_FUNCTION_ARGS   ) 

Definition at line 2867 of file timestamp.c.

References interval_cmp_internal(), PG_GETARG_INTERVAL_P, and PG_RETURN_INTERVAL_P.

{
    Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
    Interval   *interval2 = PG_GETARG_INTERVAL_P(1);
    Interval   *result;

    /* use interval_cmp_internal to be sure this agrees with comparisons */
    if (interval_cmp_internal(interval1, interval2) < 0)
        result = interval1;
    else
        result = interval2;
    PG_RETURN_INTERVAL_P(result);
}

Datum interval_transform ( PG_FUNCTION_ARGS   ) 

Definition at line 932 of file timestamp.c.

References FuncExpr::args, Assert, DatumGetInt32, exprTypmod(), fls(), INTERVAL_PRECISION, INTERVAL_RANGE, IsA, linitial, list_length(), lsecond, MAX_INTERVAL_PRECISION, PG_GETARG_POINTER, PG_RETURN_POINTER, relabel_to_typmod(), and SECOND.

{
    FuncExpr   *expr = (FuncExpr *) PG_GETARG_POINTER(0);
    Node       *ret = NULL;
    Node       *typmod;

    Assert(IsA(expr, FuncExpr));
    Assert(list_length(expr->args) >= 2);

    typmod = (Node *) lsecond(expr->args);

    if (IsA(typmod, Const) &&!((Const *) typmod)->constisnull)
    {
        Node       *source = (Node *) linitial(expr->args);
        int32       old_typmod = exprTypmod(source);
        int32       new_typmod = DatumGetInt32(((Const *) typmod)->constvalue);
        int         old_range;
        int         old_precis;
        int         new_range = INTERVAL_RANGE(new_typmod);
        int         new_precis = INTERVAL_PRECISION(new_typmod);
        int         new_range_fls;
        int         old_range_fls;

        if (old_typmod < 0)
        {
            old_range = INTERVAL_FULL_RANGE;
            old_precis = INTERVAL_FULL_PRECISION;
        }
        else
        {
            old_range = INTERVAL_RANGE(old_typmod);
            old_precis = INTERVAL_PRECISION(old_typmod);
        }

        /*
         * Temporally-smaller fields occupy higher positions in the range
         * bitmap.  Since only the temporally-smallest bit matters for length
         * coercion purposes, we compare the last-set bits in the ranges.
         * Precision, which is to say, sub-second precision, only affects
         * ranges that include SECOND.
         */
        new_range_fls = fls(new_range);
        old_range_fls = fls(old_range);
        if (new_typmod < 0 ||
            ((new_range_fls >= SECOND || new_range_fls >= old_range_fls) &&
           (old_range_fls < SECOND || new_precis >= MAX_INTERVAL_PRECISION ||
            new_precis >= old_precis)))
            ret = relabel_to_typmod(source, new_typmod);
    }

    PG_RETURN_POINTER(ret);
}

Datum interval_trunc ( PG_FUNCTION_ARGS   ) 

Definition at line 3692 of file timestamp.c.

References DecodeUnits(), downcase_truncate_identifier(), DTK_CENTURY, DTK_DAY, DTK_DECADE, DTK_HOUR, DTK_MICROSEC, DTK_MILLENNIUM, DTK_MILLISEC, DTK_MINUTE, DTK_MONTH, DTK_QUARTER, DTK_SECOND, DTK_WEEK, DTK_YEAR, elog, ereport, errcode(), errmsg(), ERROR, interval2tm(), palloc(), PG_GETARG_INTERVAL_P, PG_GETARG_TEXT_PP, PG_RETURN_INTERVAL_P, tm, tm2interval(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, UNITS, val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

{
    text       *units = PG_GETARG_TEXT_PP(0);
    Interval   *interval = PG_GETARG_INTERVAL_P(1);
    Interval   *result;
    int         type,
                val;
    char       *lowunits;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;

    result = (Interval *) palloc(sizeof(Interval));

    lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
                                            VARSIZE_ANY_EXHDR(units),
                                            false);

    type = DecodeUnits(0, lowunits, &val);

    if (type == UNITS)
    {
        if (interval2tm(*interval, tm, &fsec) == 0)
        {
            switch (val)
            {
                    /* fall through */
                case DTK_MILLENNIUM:
                    /* caution: C division may have negative remainder */
                    tm->tm_year = (tm->tm_year / 1000) * 1000;
                case DTK_CENTURY:
                    /* caution: C division may have negative remainder */
                    tm->tm_year = (tm->tm_year / 100) * 100;
                case DTK_DECADE:
                    /* caution: C division may have negative remainder */
                    tm->tm_year = (tm->tm_year / 10) * 10;
                case DTK_YEAR:
                    tm->tm_mon = 0;
                case DTK_QUARTER:
                    tm->tm_mon = 3 * (tm->tm_mon / 3);
                case DTK_MONTH:
                    tm->tm_mday = 0;
                case DTK_DAY:
                    tm->tm_hour = 0;
                case DTK_HOUR:
                    tm->tm_min = 0;
                case DTK_MINUTE:
                    tm->tm_sec = 0;
                case DTK_SECOND:
                    fsec = 0;
                    break;

                case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
                    fsec = (fsec / 1000) * 1000;
#else
                    fsec = floor(fsec * 1000) / 1000;
#endif
                    break;
                case DTK_MICROSEC:
#ifndef HAVE_INT64_TIMESTAMP
                    fsec = floor(fsec * 1000000) / 1000000;
#endif
                    break;

                default:
                    if (val == DTK_WEEK)
                        ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("interval units \"%s\" not supported "
                                    "because months usually have fractional weeks",
                                        lowunits)));
                    else
                        ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("interval units \"%s\" not supported",
                                        lowunits)));
            }

            if (tm2interval(tm, fsec, result) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("interval out of range")));
        }
        else
            elog(ERROR, "could not convert interval to tm");
    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("interval units \"%s\" not recognized",
                        lowunits)));
    }

    PG_RETURN_INTERVAL_P(result);
}

Datum interval_um ( PG_FUNCTION_ARGS   ) 

Definition at line 2851 of file timestamp.c.

References Interval::day, Interval::month, palloc(), PG_GETARG_INTERVAL_P, PG_RETURN_INTERVAL_P, and Interval::time.

Referenced by abs_interval().

{
    Interval   *interval = PG_GETARG_INTERVAL_P(0);
    Interval   *result;

    result = (Interval *) palloc(sizeof(Interval));

    result->time = -interval->time;
    result->day = -interval->day;
    result->month = -interval->month;

    PG_RETURN_INTERVAL_P(result);
}

Datum intervaltypmodin ( PG_FUNCTION_ARGS   ) 

Definition at line 771 of file timestamp.c.

References ArrayGetIntegerTypmods(), DAY, ereport, errcode(), errmsg(), ERROR, HOUR, INTERVAL_FULL_PRECISION, INTERVAL_FULL_RANGE, INTERVAL_MASK, INTERVAL_TYPMOD, MAX_INTERVAL_PRECISION, MINUTE, MONTH, PG_GETARG_ARRAYTYPE_P, PG_RETURN_INT32, SECOND, WARNING, and YEAR.

{
    ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);
    int32      *tl;
    int         n;
    int32       typmod;

    tl = ArrayGetIntegerTypmods(ta, &n);

    /*
     * tl[0] - interval range (fields bitmask)  tl[1] - precision (optional)
     *
     * Note we must validate tl[0] even though it's normally guaranteed
     * correct by the grammar --- consider SELECT 'foo'::"interval"(1000).
     */
    if (n > 0)
    {
        switch (tl[0])
        {
            case INTERVAL_MASK(YEAR):
            case INTERVAL_MASK(MONTH):
            case INTERVAL_MASK(DAY):
            case INTERVAL_MASK(HOUR):
            case INTERVAL_MASK(MINUTE):
            case INTERVAL_MASK(SECOND):
            case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
            case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
            case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
            case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
            case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
            case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
            case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
            case INTERVAL_FULL_RANGE:
                /* all OK */
                break;
            default:
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("invalid INTERVAL type modifier")));
        }
    }

    if (n == 1)
    {
        if (tl[0] != INTERVAL_FULL_RANGE)
            typmod = INTERVAL_TYPMOD(INTERVAL_FULL_PRECISION, tl[0]);
        else
            typmod = -1;
    }
    else if (n == 2)
    {
        if (tl[1] < 0)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("INTERVAL(%d) precision must not be negative",
                            tl[1])));
        if (tl[1] > MAX_INTERVAL_PRECISION)
        {
            ereport(WARNING,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
              errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
                     tl[1], MAX_INTERVAL_PRECISION)));
            typmod = INTERVAL_TYPMOD(MAX_INTERVAL_PRECISION, tl[0]);
        }
        else
            typmod = INTERVAL_TYPMOD(tl[1], tl[0]);
    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("invalid INTERVAL type modifier")));
        typmod = 0;             /* keep compiler quiet */
    }

    PG_RETURN_INT32(typmod);
}

Datum intervaltypmodout ( PG_FUNCTION_ARGS   ) 

Definition at line 850 of file timestamp.c.

References DAY, elog, ERROR, HOUR, INTERVAL_FULL_PRECISION, INTERVAL_FULL_RANGE, INTERVAL_MASK, INTERVAL_PRECISION, INTERVAL_RANGE, MINUTE, MONTH, palloc(), PG_GETARG_INT32, PG_RETURN_CSTRING, SECOND, snprintf(), and YEAR.

{
    int32       typmod = PG_GETARG_INT32(0);
    char       *res = (char *) palloc(64);
    int         fields;
    int         precision;
    const char *fieldstr;

    if (typmod < 0)
    {
        *res = '\0';
        PG_RETURN_CSTRING(res);
    }

    fields = INTERVAL_RANGE(typmod);
    precision = INTERVAL_PRECISION(typmod);

    switch (fields)
    {
        case INTERVAL_MASK(YEAR):
            fieldstr = " year";
            break;
        case INTERVAL_MASK(MONTH):
            fieldstr = " month";
            break;
        case INTERVAL_MASK(DAY):
            fieldstr = " day";
            break;
        case INTERVAL_MASK(HOUR):
            fieldstr = " hour";
            break;
        case INTERVAL_MASK(MINUTE):
            fieldstr = " minute";
            break;
        case INTERVAL_MASK(SECOND):
            fieldstr = " second";
            break;
        case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
            fieldstr = " year to month";
            break;
        case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
            fieldstr = " day to hour";
            break;
        case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
            fieldstr = " day to minute";
            break;
        case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
            fieldstr = " day to second";
            break;
        case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
            fieldstr = " hour to minute";
            break;
        case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
            fieldstr = " hour to second";
            break;
        case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
            fieldstr = " minute to second";
            break;
        case INTERVAL_FULL_RANGE:
            fieldstr = "";
            break;
        default:
            elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
            fieldstr = "";
            break;
    }

    if (precision != INTERVAL_FULL_PRECISION)
        snprintf(res, 64, "%s(%d)", fieldstr, precision);
    else
        snprintf(res, 64, "%s", fieldstr);

    PG_RETURN_CSTRING(res);
}

void isoweek2date ( int  woy,
int *  year,
int *  mon,
int *  mday 
)

Definition at line 3816 of file timestamp.c.

References isoweek2j(), and j2date().

Referenced by do_to_timestamp(), timestamp_trunc(), and timestamptz_trunc().

{
    j2date(isoweek2j(*year, woy), year, mon, mday);
}

int isoweek2j ( int  year,
int  week 
)

Definition at line 3796 of file timestamp.c.

References date2j(), and j2day().

Referenced by date2isoyearday(), do_to_timestamp(), isoweek2date(), and isoweekdate2date().

{
    int         day0,
                day4;

    /* fourth day of current year */
    day4 = date2j(year, 1, 4);

    /* day0 == offset to first day of week (Monday) */
    day0 = j2day(day4 - 1);

    return ((week - 1) * 7) + (day4 - day0);
}

void isoweekdate2date ( int  isoweek,
int  wday,
int *  year,
int *  mon,
int *  mday 
)

Definition at line 3829 of file timestamp.c.

References isoweek2j(), and j2date().

Referenced by do_to_timestamp().

{
    int         jday;

    jday = isoweek2j(*year, isoweek);
    /* convert Gregorian week start (Sunday=1) to ISO week start (Monday=1) */
    if (wday > 1)
        jday += wday - 2;
    else
        jday += 6;
    j2date(jday, year, mon, mday);
}

Datum mul_d_interval ( PG_FUNCTION_ARGS   ) 

Definition at line 2996 of file timestamp.c.

References DirectFunctionCall2, interval_mul(), and PG_GETARG_DATUM.

{
    /* Args are float8 and Interval *, but leave them as generic Datum */
    Datum       factor = PG_GETARG_DATUM(0);
    Datum       span = PG_GETARG_DATUM(1);

    return DirectFunctionCall2(interval_mul, span, factor);
}

Datum now ( PG_FUNCTION_ARGS   ) 
Datum overlaps_timestamp ( PG_FUNCTION_ARGS   ) 

Definition at line 2286 of file timestamp.c.

References PG_ARGISNULL, PG_GETARG_DATUM, PG_RETURN_BOOL, PG_RETURN_NULL, TIMESTAMP_GT, and TIMESTAMP_LT.

{
    /*
     * The arguments are Timestamps, but we leave them as generic Datums to
     * avoid unnecessary conversions between value and reference forms --- not
     * to mention possible dereferences of null pointers.
     */
    Datum       ts1 = PG_GETARG_DATUM(0);
    Datum       te1 = PG_GETARG_DATUM(1);
    Datum       ts2 = PG_GETARG_DATUM(2);
    Datum       te2 = PG_GETARG_DATUM(3);
    bool        ts1IsNull = PG_ARGISNULL(0);
    bool        te1IsNull = PG_ARGISNULL(1);
    bool        ts2IsNull = PG_ARGISNULL(2);
    bool        te2IsNull = PG_ARGISNULL(3);

#define TIMESTAMP_GT(t1,t2) \
    DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))
#define TIMESTAMP_LT(t1,t2) \
    DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2))

    /*
     * If both endpoints of interval 1 are null, the result is null (unknown).
     * If just one endpoint is null, take ts1 as the non-null one. Otherwise,
     * take ts1 as the lesser endpoint.
     */
    if (ts1IsNull)
    {
        if (te1IsNull)
            PG_RETURN_NULL();
        /* swap null for non-null */
        ts1 = te1;
        te1IsNull = true;
    }
    else if (!te1IsNull)
    {
        if (TIMESTAMP_GT(ts1, te1))
        {
            Datum       tt = ts1;

            ts1 = te1;
            te1 = tt;
        }
    }

    /* Likewise for interval 2. */
    if (ts2IsNull)
    {
        if (te2IsNull)
            PG_RETURN_NULL();
        /* swap null for non-null */
        ts2 = te2;
        te2IsNull = true;
    }
    else if (!te2IsNull)
    {
        if (TIMESTAMP_GT(ts2, te2))
        {
            Datum       tt = ts2;

            ts2 = te2;
            te2 = tt;
        }
    }

    /*
     * At this point neither ts1 nor ts2 is null, so we can consider three
     * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2
     */
    if (TIMESTAMP_GT(ts1, ts2))
    {
        /*
         * This case is ts1 < te2 OR te1 < te2, which may look redundant but
         * in the presence of nulls it's not quite completely so.
         */
        if (te2IsNull)
            PG_RETURN_NULL();
        if (TIMESTAMP_LT(ts1, te2))
            PG_RETURN_BOOL(true);
        if (te1IsNull)
            PG_RETURN_NULL();

        /*
         * If te1 is not null then we had ts1 <= te1 above, and we just found
         * ts1 >= te2, hence te1 >= te2.
         */
        PG_RETURN_BOOL(false);
    }
    else if (TIMESTAMP_LT(ts1, ts2))
    {
        /* This case is ts2 < te1 OR te2 < te1 */
        if (te1IsNull)
            PG_RETURN_NULL();
        if (TIMESTAMP_LT(ts2, te1))
            PG_RETURN_BOOL(true);
        if (te2IsNull)
            PG_RETURN_NULL();

        /*
         * If te2 is not null then we had ts2 <= te2 above, and we just found
         * ts2 >= te1, hence te2 >= te1.
         */
        PG_RETURN_BOOL(false);
    }
    else
    {
        /*
         * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a
         * rather silly way of saying "true if both are nonnull, else null".
         */
        if (te1IsNull || te2IsNull)
            PG_RETURN_NULL();
        PG_RETURN_BOOL(true);
    }

#undef TIMESTAMP_GT
#undef TIMESTAMP_LT
}

Datum pg_conf_load_time ( PG_FUNCTION_ARGS   ) 

Definition at line 1257 of file timestamp.c.

References PG_RETURN_TIMESTAMPTZ, and PgReloadTime.

Datum pg_postmaster_start_time ( PG_FUNCTION_ARGS   ) 

Definition at line 1251 of file timestamp.c.

References PG_RETURN_TIMESTAMPTZ, and PgStartTime.

Timestamp SetEpochTimestamp ( void   ) 

Definition at line 1839 of file timestamp.c.

References GetEpochTime(), NULL, tm, and tm2timestamp().

Referenced by dttofmtasc_replace(), PGTYPEStimestamp_from_asc(), timestamp_in(), timestamp_part(), timestamptz_in(), and timestamptz_part().

{
    Timestamp   dt;
    struct pg_tm tt,
               *tm = &tt;

    GetEpochTime(tm);
    /* we don't bother to test for failure ... */
    tm2timestamp(tm, 0, NULL, &dt);

    return dt;
}   /* SetEpochTimestamp() */

Datum statement_timestamp ( PG_FUNCTION_ARGS   ) 
static TimeOffset time2t ( const int  hour,
const int  min,
const int  sec,
const fsec_t  fsec 
) [static]

Definition at line 1774 of file timestamp.c.

References MINS_PER_HOUR, SECS_PER_MINUTE, and USECS_PER_SEC.

Referenced by tm2timestamp().

{
#ifdef HAVE_INT64_TIMESTAMP
    return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
#else
    return (((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec + fsec;
#endif
}

TimestampTz time_t_to_timestamptz ( pg_time_t  tm  ) 

Definition at line 1399 of file timestamp.c.

References POSTGRES_EPOCH_JDATE, and UNIX_EPOCH_JDATE.

Referenced by pg_stat_file().

{
    TimestampTz result;

    result = (TimestampTz) tm -
        ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);

#ifdef HAVE_INT64_TIMESTAMP
    result *= USECS_PER_SEC;
#endif

    return result;
}

static TimestampTz timestamp2timestamptz ( Timestamp  timestamp  )  [static]
int timestamp2tm ( Timestamp  dt,
int *  tzp,
struct pg_tm tm,
fsec_t fsec,
const char **  tzn,
pg_tz attimezone 
)

Definition at line 1505 of file timestamp.c.

References CTimeZone, dt2time(), HasCTZSet, INT64CONST, j2date(), NULL, pg_localtime(), POSTGRES_EPOCH_JDATE, rint(), SECS_PER_DAY, session_timezone, 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_year, pg_tm::tm_zone, TMODULO, TSROUND, UNIX_EPOCH_JDATE, USECS_PER_DAY, and USECS_PER_SEC.

Referenced by GetCurrentDateTime(), GetCurrentTimeUsec(), map_sql_value_to_xml_value(), pg_timezone_names(), PGTYPEStimestamp_add_interval(), PGTYPEStimestamp_fmt_asc(), PGTYPEStimestamp_to_asc(), timestamp2timestamptz(), timestamp_abstime(), timestamp_age(), timestamp_date(), timestamp_out(), timestamp_part(), timestamp_pl_interval(), timestamp_recv(), timestamp_time(), timestamp_to_char(), timestamp_trunc(), timestamp_zone(), timestamptz_abstime(), timestamptz_age(), timestamptz_date(), timestamptz_out(), timestamptz_part(), timestamptz_pl_interval(), timestamptz_recv(), timestamptz_time(), timestamptz_timestamp(), timestamptz_timetz(), timestamptz_to_char(), timestamptz_to_str(), timestamptz_trunc(), and timestamptz_zone().

{
    Timestamp   date;
    Timestamp   time;
    pg_time_t   utime;

    /*
     * If HasCTZSet is true then we have a brute force time zone specified. Go
     * ahead and rotate to the local time zone since we will later bypass any
     * calls which adjust the tm fields.
     */
    if (attimezone == NULL && HasCTZSet && tzp != NULL)
    {
#ifdef HAVE_INT64_TIMESTAMP
        dt -= CTimeZone * USECS_PER_SEC;
#else
        dt -= CTimeZone;
#endif
    }

#ifdef HAVE_INT64_TIMESTAMP
    time = dt;
    TMODULO(time, date, USECS_PER_DAY);

    if (time < INT64CONST(0))
    {
        time += USECS_PER_DAY;
        date -= 1;
    }

    /* add offset to go from J2000 back to standard Julian date */
    date += POSTGRES_EPOCH_JDATE;

    /* Julian day routine does not work for negative Julian days */
    if (date < 0 || date > (Timestamp) INT_MAX)
        return -1;

    j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
    dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
#else
    time = dt;
    TMODULO(time, date, (double) SECS_PER_DAY);

    if (time < 0)
    {
        time += SECS_PER_DAY;
        date -= 1;
    }

    /* add offset to go from J2000 back to standard Julian date */
    date += POSTGRES_EPOCH_JDATE;

recalc_d:
    /* Julian day routine does not work for negative Julian days */
    if (date < 0 || date > (Timestamp) INT_MAX)
        return -1;

    j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
recalc_t:
    dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);

    *fsec = TSROUND(*fsec);
    /* roundoff may need to propagate to higher-order fields */
    if (*fsec >= 1.0)
    {
        time = ceil(time);
        if (time >= (double) SECS_PER_DAY)
        {
            time = 0;
            date += 1;
            goto recalc_d;
        }
        goto recalc_t;
    }
#endif

    /* Done if no TZ conversion wanted */
    if (tzp == NULL)
    {
        tm->tm_isdst = -1;
        tm->tm_gmtoff = 0;
        tm->tm_zone = NULL;
        if (tzn != NULL)
            *tzn = NULL;
        return 0;
    }

    /*
     * We have a brute force time zone per SQL99? Then use it without change
     * since we have already rotated to the time zone.
     */
    if (attimezone == NULL && HasCTZSet)
    {
        *tzp = CTimeZone;
        tm->tm_isdst = 0;
        tm->tm_gmtoff = CTimeZone;
        tm->tm_zone = NULL;
        if (tzn != NULL)
            *tzn = NULL;
        return 0;
    }

    /*
     * If the time falls within the range of pg_time_t, use pg_localtime() to
     * rotate to the local time zone.
     *
     * First, convert to an integral timestamp, avoiding possibly
     * platform-specific roundoff-in-wrong-direction errors, and adjust to
     * Unix epoch.  Then see if we can convert to pg_time_t without loss. This
     * coding avoids hardwiring any assumptions about the width of pg_time_t,
     * so it should behave sanely on machines without int64.
     */
#ifdef HAVE_INT64_TIMESTAMP
    dt = (dt - *fsec) / USECS_PER_SEC +
        (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
#else
    dt = rint(dt - *fsec +
              (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
#endif
    utime = (pg_time_t) dt;
    if ((Timestamp) utime == dt)
    {
        struct pg_tm *tx = pg_localtime(&utime,
                                 attimezone ? attimezone : session_timezone);

        tm->tm_year = tx->tm_year + 1900;
        tm->tm_mon = tx->tm_mon + 1;
        tm->tm_mday = tx->tm_mday;
        tm->tm_hour = tx->tm_hour;
        tm->tm_min = tx->tm_min;
        tm->tm_sec = tx->tm_sec;
        tm->tm_isdst = tx->tm_isdst;
        tm->tm_gmtoff = tx->tm_gmtoff;
        tm->tm_zone = tx->tm_zone;
        *tzp = -tm->tm_gmtoff;
        if (tzn != NULL)
            *tzn = tm->tm_zone;
    }
    else
    {
        /*
         * When out of range of pg_time_t, treat as GMT
         */
        *tzp = 0;
        /* Mark this as *no* time zone available */
        tm->tm_isdst = -1;
        tm->tm_gmtoff = 0;
        tm->tm_zone = NULL;
        if (tzn != NULL)
            *tzn = NULL;
    }

    return 0;
}

Datum timestamp_age ( PG_FUNCTION_ARGS   ) 

Definition at line 3149 of file timestamp.c.

References day_tab, ereport, errcode(), errmsg(), ERROR, isleap, NULL, palloc(), PG_GETARG_TIMESTAMP, PG_RETURN_INTERVAL_P, timestamp2tm(), tm, tm2interval(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, and pg_tm::tm_year.

{
    Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
    Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
    Interval   *result;
    fsec_t      fsec,
                fsec1,
                fsec2;
    struct pg_tm tt,
               *tm = &tt;
    struct pg_tm tt1,
               *tm1 = &tt1;
    struct pg_tm tt2,
               *tm2 = &tt2;

    result = (Interval *) palloc(sizeof(Interval));

    if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&
        timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0)
    {
        /* form the symbolic difference */
        fsec = fsec1 - fsec2;
        tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
        tm->tm_min = tm1->tm_min - tm2->tm_min;
        tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
        tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
        tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
        tm->tm_year = tm1->tm_year - tm2->tm_year;

        /* flip sign if necessary... */
        if (dt1 < dt2)
        {
            fsec = -fsec;
            tm->tm_sec = -tm->tm_sec;
            tm->tm_min = -tm->tm_min;
            tm->tm_hour = -tm->tm_hour;
            tm->tm_mday = -tm->tm_mday;
            tm->tm_mon = -tm->tm_mon;
            tm->tm_year = -tm->tm_year;
        }

        /* propagate any negative fields into the next higher field */
        while (fsec < 0)
        {
#ifdef HAVE_INT64_TIMESTAMP
            fsec += USECS_PER_SEC;
#else
            fsec += 1.0;
#endif
            tm->tm_sec--;
        }

        while (tm->tm_sec < 0)
        {
            tm->tm_sec += SECS_PER_MINUTE;
            tm->tm_min--;
        }

        while (tm->tm_min < 0)
        {
            tm->tm_min += MINS_PER_HOUR;
            tm->tm_hour--;
        }

        while (tm->tm_hour < 0)
        {
            tm->tm_hour += HOURS_PER_DAY;
            tm->tm_mday--;
        }

        while (tm->tm_mday < 0)
        {
            if (dt1 < dt2)
            {
                tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
                tm->tm_mon--;
            }
            else
            {
                tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
                tm->tm_mon--;
            }
        }

        while (tm->tm_mon < 0)
        {
            tm->tm_mon += MONTHS_PER_YEAR;
            tm->tm_year--;
        }

        /* recover sign if necessary... */
        if (dt1 < dt2)
        {
            fsec = -fsec;
            tm->tm_sec = -tm->tm_sec;
            tm->tm_min = -tm->tm_min;
            tm->tm_hour = -tm->tm_hour;
            tm->tm_mday = -tm->tm_mday;
            tm->tm_mon = -tm->tm_mon;
            tm->tm_year = -tm->tm_year;
        }

        if (tm2interval(tm, fsec, result) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("interval out of range")));
    }
    else
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("timestamp out of range")));

    PG_RETURN_INTERVAL_P(result);
}

Datum timestamp_cmp ( PG_FUNCTION_ARGS   ) 
int timestamp_cmp_internal ( Timestamp  dt1,
Timestamp  dt2 
)

Definition at line 1861 of file timestamp.c.

Referenced by date_cmp_timestamp(), date_eq_timestamp(), date_ge_timestamp(), date_gt_timestamp(), date_le_timestamp(), date_lt_timestamp(), date_ne_timestamp(), generate_series_timestamp(), generate_series_timestamptz(), timestamp_cmp(), timestamp_cmp_date(), timestamp_cmp_timestamptz(), timestamp_eq(), timestamp_eq_date(), timestamp_eq_timestamptz(), timestamp_fastcmp(), timestamp_ge(), timestamp_ge_date(), timestamp_ge_timestamptz(), timestamp_gt(), timestamp_gt_date(), timestamp_gt_timestamptz(), timestamp_larger(), timestamp_le(), timestamp_le_date(), timestamp_le_timestamptz(), timestamp_lt(), timestamp_lt_date(), timestamp_lt_timestamptz(), timestamp_ne(), timestamp_ne_date(), timestamp_ne_timestamptz(), timestamp_smaller(), timestamptz_cmp_timestamp(), timestamptz_eq_timestamp(), timestamptz_ge_timestamp(), timestamptz_gt_timestamp(), timestamptz_le_timestamp(), timestamptz_lt_timestamp(), and timestamptz_ne_timestamp().

{
#ifdef HAVE_INT64_TIMESTAMP
    return (dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0);
#else

    /*
     * When using float representation, we have to be wary of NaNs.
     *
     * We consider all NANs to be equal and larger than any non-NAN. This is
     * somewhat arbitrary; the important thing is to have a consistent sort
     * order.
     */
    if (isnan(dt1))
    {
        if (isnan(dt2))
            return 0;           /* NAN = NAN */
        else
            return 1;           /* NAN > non-NAN */
    }
    else if (isnan(dt2))
    {
        return -1;              /* non-NAN < NAN */
    }
    else
    {
        if (dt1 > dt2)
            return 1;
        else if (dt1 < dt2)
            return -1;
        else
            return 0;
    }
#endif
}

Datum timestamp_cmp_timestamptz ( PG_FUNCTION_ARGS   ) 
Datum timestamp_eq ( PG_FUNCTION_ARGS   ) 
Datum timestamp_eq_timestamptz ( PG_FUNCTION_ARGS   ) 
static int timestamp_fastcmp ( Datum  x,
Datum  y,
SortSupport  ssup 
) [static]

Definition at line 1962 of file timestamp.c.

References DatumGetTimestamp, and timestamp_cmp_internal().

Datum timestamp_finite ( PG_FUNCTION_ARGS   ) 
Datum timestamp_ge ( PG_FUNCTION_ARGS   ) 
Datum timestamp_ge_timestamptz ( PG_FUNCTION_ARGS   ) 
Datum timestamp_gt ( PG_FUNCTION_ARGS   ) 
Datum timestamp_gt_timestamptz ( PG_FUNCTION_ARGS   ) 
Datum timestamp_hash ( PG_FUNCTION_ARGS   ) 

Definition at line 1980 of file timestamp.c.

References hashfloat8(), and hashint8().

{
    /* We can use either hashint8 or hashfloat8 directly */
#ifdef HAVE_INT64_TIMESTAMP
    return hashint8(fcinfo);
#else
    return hashfloat8(fcinfo);
#endif
}

Datum timestamp_in ( PG_FUNCTION_ARGS   ) 

Definition at line 139 of file timestamp.c.

References AdjustTimestampForTypmod(), DateTimeParseError(), DecodeDateTime(), DTK_DATE, DTK_EARLY, DTK_EPOCH, DTK_INVALID, DTK_LATE, elog, ereport, errcode(), errmsg(), ERROR, MAXDATEFIELDS, MAXDATELEN, NULL, ParseDateTime(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_TIMESTAMP, SetEpochTimestamp(), TIMESTAMP_NOBEGIN, TIMESTAMP_NOEND, tm, and tm2timestamp().

Referenced by moddatetime().

{
    char       *str = PG_GETARG_CSTRING(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       typmod = PG_GETARG_INT32(2);
    Timestamp   result;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;
    int         tz;
    int         dtype;
    int         nf;
    int         dterr;
    char       *field[MAXDATEFIELDS];
    int         ftype[MAXDATEFIELDS];
    char        workbuf[MAXDATELEN + MAXDATEFIELDS];

    dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
                          field, ftype, MAXDATEFIELDS, &nf);
    if (dterr == 0)
        dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);
    if (dterr != 0)
        DateTimeParseError(dterr, str, "timestamp");

    switch (dtype)
    {
        case DTK_DATE:
            if (tm2timestamp(tm, fsec, NULL, &result) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range: \"%s\"", str)));
            break;

        case DTK_EPOCH:
            result = SetEpochTimestamp();
            break;

        case DTK_LATE:
            TIMESTAMP_NOEND(result);
            break;

        case DTK_EARLY:
            TIMESTAMP_NOBEGIN(result);
            break;

        case DTK_INVALID:
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
              errmsg("date/time value \"%s\" is no longer supported", str)));

            TIMESTAMP_NOEND(result);
            break;

        default:
            elog(ERROR, "unexpected dtype %d while parsing timestamp \"%s\"",
                 dtype, str);
            TIMESTAMP_NOEND(result);
    }

    AdjustTimestampForTypmod(&result, typmod);

    PG_RETURN_TIMESTAMP(result);
}

Datum timestamp_izone ( PG_FUNCTION_ARGS   ) 

Definition at line 4598 of file timestamp.c.

References DatumGetCString, Interval::day, DirectFunctionCall1, dt2local(), ereport, errcode(), errmsg(), ERROR, interval_out(), Interval::month, PG_GETARG_INTERVAL_P, PG_GETARG_TIMESTAMP, PG_RETURN_TIMESTAMPTZ, PointerGetDatum, Interval::time, and TIMESTAMP_NOT_FINITE.

{
    Interval   *zone = PG_GETARG_INTERVAL_P(0);
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(1);
    TimestampTz result;
    int         tz;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        PG_RETURN_TIMESTAMPTZ(timestamp);

    if (zone->month != 0 || zone->day != 0)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("interval time zone \"%s\" must not include months or days",
                        DatumGetCString(DirectFunctionCall1(interval_out,
                                                  PointerGetDatum(zone))))));

#ifdef HAVE_INT64_TIMESTAMP
    tz = zone->time / USECS_PER_SEC;
#else
    tz = zone->time;
#endif

    result = dt2local(timestamp, tz);

    PG_RETURN_TIMESTAMPTZ(result);
}   /* timestamp_izone() */

Datum timestamp_larger ( PG_FUNCTION_ARGS   ) 

Definition at line 2426 of file timestamp.c.

References PG_GETARG_TIMESTAMP, PG_RETURN_TIMESTAMP, and timestamp_cmp_internal().

{
    Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
    Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
    Timestamp   result;

    if (timestamp_cmp_internal(dt1, dt2) > 0)
        result = dt1;
    else
        result = dt2;
    PG_RETURN_TIMESTAMP(result);
}

Datum timestamp_le ( PG_FUNCTION_ARGS   ) 
Datum timestamp_le_timestamptz ( PG_FUNCTION_ARGS   ) 
Datum timestamp_lt ( PG_FUNCTION_ARGS   ) 
Datum timestamp_lt_timestamptz ( PG_FUNCTION_ARGS   ) 
Datum timestamp_mi ( PG_FUNCTION_ARGS   ) 

Definition at line 2441 of file timestamp.c.

References DatumGetIntervalP, Interval::day, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, interval_justify_hours(), IntervalPGetDatum, Interval::month, palloc(), PG_GETARG_TIMESTAMP, PG_RETURN_INTERVAL_P, Interval::time, and TIMESTAMP_NOT_FINITE.

Referenced by gbt_ts_dist(), ts_dist(), and tstz_dist().

{
    Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
    Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
    Interval   *result;

    result = (Interval *) palloc(sizeof(Interval));

    if (TIMESTAMP_NOT_FINITE(dt1) || TIMESTAMP_NOT_FINITE(dt2))
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("cannot subtract infinite timestamps")));

    result->time = dt1 - dt2;

    result->month = 0;
    result->day = 0;

    /*----------
     *  This is wrong, but removing it breaks a lot of regression tests.
     *  For example:
     *
     *  test=> SET timezone = 'EST5EDT';
     *  test=> SELECT
     *  test-> ('2005-10-30 13:22:00-05'::timestamptz -
     *  test(>  '2005-10-29 13:22:00-04'::timestamptz);
     *  ?column?
     *  ----------------
     *   1 day 01:00:00
     *   (1 row)
     *
     *  so adding that to the first timestamp gets:
     *
     *   test=> SELECT
     *   test-> ('2005-10-29 13:22:00-04'::timestamptz +
     *   test(> ('2005-10-30 13:22:00-05'::timestamptz -
     *   test(>  '2005-10-29 13:22:00-04'::timestamptz)) at time zone 'EST';
     *      timezone
     *  --------------------
     *  2005-10-30 14:22:00
     *  (1 row)
     *----------
     */
    result = DatumGetIntervalP(DirectFunctionCall1(interval_justify_hours,
                                                 IntervalPGetDatum(result)));

    PG_RETURN_INTERVAL_P(result);
}

Datum timestamp_mi_interval ( PG_FUNCTION_ARGS   ) 
Datum timestamp_ne ( PG_FUNCTION_ARGS   ) 
Datum timestamp_ne_timestamptz ( PG_FUNCTION_ARGS   ) 
Datum timestamp_out ( PG_FUNCTION_ARGS   ) 

Definition at line 210 of file timestamp.c.

References buf, DateStyle, EncodeDateTime(), EncodeSpecialTimestamp(), ereport, errcode(), errmsg(), ERROR, MAXDATELEN, NULL, PG_GETARG_TIMESTAMP, PG_RETURN_CSTRING, pstrdup(), timestamp2tm(), TIMESTAMP_NOT_FINITE, and tm.

{
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(0);
    char       *result;
    struct pg_tm tt,
               *tm = &tt;
    fsec_t      fsec;
    char        buf[MAXDATELEN + 1];

    if (TIMESTAMP_NOT_FINITE(timestamp))
        EncodeSpecialTimestamp(timestamp, buf);
    else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
        EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf);
    else
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("timestamp out of range")));

    result = pstrdup(buf);
    PG_RETURN_CSTRING(result);
}

Datum timestamp_part ( PG_FUNCTION_ARGS   ) 

Definition at line 3967 of file timestamp.c.

References date2isoweek(), date2isoyear(), date2j(), DecodeSpecial(), DecodeUnits(), downcase_truncate_identifier(), DTK_CENTURY, DTK_DAY, DTK_DECADE, DTK_DOW, DTK_DOY, DTK_EPOCH, DTK_HOUR, DTK_ISODOW, DTK_ISOYEAR, DTK_JULIAN, DTK_MICROSEC, DTK_MILLENNIUM, DTK_MILLISEC, DTK_MINUTE, DTK_MONTH, DTK_QUARTER, DTK_SECOND, DTK_TZ, DTK_TZ_HOUR, DTK_TZ_MINUTE, DTK_WEEK, DTK_YEAR, ereport, errcode(), errmsg(), ERROR, j2day(), NULL, PG_GETARG_TEXT_PP, PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, RESERV, SECS_PER_DAY, SetEpochTimestamp(), timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, UNITS, UNKNOWN_FIELD, val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

{
    text       *units = PG_GETARG_TEXT_PP(0);
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(1);
    float8      result;
    int         type,
                val;
    char       *lowunits;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;

    if (TIMESTAMP_NOT_FINITE(timestamp))
    {
        result = 0;
        PG_RETURN_FLOAT8(result);
    }

    lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
                                            VARSIZE_ANY_EXHDR(units),
                                            false);

    type = DecodeUnits(0, lowunits, &val);
    if (type == UNKNOWN_FIELD)
        type = DecodeSpecial(0, lowunits, &val);

    if (type == UNITS)
    {
        if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));

        switch (val)
        {
            case DTK_MICROSEC:
#ifdef HAVE_INT64_TIMESTAMP
                result = tm->tm_sec * 1000000.0 + fsec;
#else
                result = (tm->tm_sec + fsec) * 1000000;
#endif
                break;

            case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
                result = tm->tm_sec * 1000.0 + fsec / 1000.0;
#else
                result = (tm->tm_sec + fsec) * 1000;
#endif
                break;

            case DTK_SECOND:
#ifdef HAVE_INT64_TIMESTAMP
                result = tm->tm_sec + fsec / 1000000.0;
#else
                result = tm->tm_sec + fsec;
#endif
                break;

            case DTK_MINUTE:
                result = tm->tm_min;
                break;

            case DTK_HOUR:
                result = tm->tm_hour;
                break;

            case DTK_DAY:
                result = tm->tm_mday;
                break;

            case DTK_MONTH:
                result = tm->tm_mon;
                break;

            case DTK_QUARTER:
                result = (tm->tm_mon - 1) / 3 + 1;
                break;

            case DTK_WEEK:
                result = (float8) date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
                break;

            case DTK_YEAR:
                if (tm->tm_year > 0)
                    result = tm->tm_year;
                else
                    /* there is no year 0, just 1 BC and 1 AD */
                    result = tm->tm_year - 1;
                break;

            case DTK_DECADE:

                /*
                 * what is a decade wrt dates? let us assume that decade 199
                 * is 1990 thru 1999... decade 0 starts on year 1 BC, and -1
                 * is 11 BC thru 2 BC...
                 */
                if (tm->tm_year >= 0)
                    result = tm->tm_year / 10;
                else
                    result = -((8 - (tm->tm_year - 1)) / 10);
                break;

            case DTK_CENTURY:

                /* ----
                 * centuries AD, c>0: year in [ (c-1)* 100 + 1 : c*100 ]
                 * centuries BC, c<0: year in [ c*100 : (c+1) * 100 - 1]
                 * there is no number 0 century.
                 * ----
                 */
                if (tm->tm_year > 0)
                    result = (tm->tm_year + 99) / 100;
                else
                    /* caution: C division may have negative remainder */
                    result = -((99 - (tm->tm_year - 1)) / 100);
                break;

            case DTK_MILLENNIUM:
                /* see comments above. */
                if (tm->tm_year > 0)
                    result = (tm->tm_year + 999) / 1000;
                else
                    result = -((999 - (tm->tm_year - 1)) / 1000);
                break;

            case DTK_JULIAN:
                result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
#ifdef HAVE_INT64_TIMESTAMP
                result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
                    tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY;
#else
                result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
                           tm->tm_sec + fsec) / (double) SECS_PER_DAY;
#endif
                break;

            case DTK_ISOYEAR:
                result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
                break;

            case DTK_TZ:
            case DTK_TZ_MINUTE:
            case DTK_TZ_HOUR:
            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                         errmsg("timestamp units \"%s\" not supported",
                                lowunits)));
                result = 0;
        }
    }
    else if (type == RESERV)
    {
        switch (val)
        {
            case DTK_EPOCH:
#ifdef HAVE_INT64_TIMESTAMP
                result = (timestamp - SetEpochTimestamp()) / 1000000.0;
#else
                result = timestamp - SetEpochTimestamp();
#endif
                break;

            case DTK_DOW:
            case DTK_ISODOW:
                if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
                    ereport(ERROR,
                            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                             errmsg("timestamp out of range")));
                result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
                if (val == DTK_ISODOW && result == 0)
                    result = 7;
                break;

            case DTK_DOY:
                if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
                    ereport(ERROR,
                            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                             errmsg("timestamp out of range")));
                result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
                          - date2j(tm->tm_year, 1, 1) + 1);
                break;

            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                         errmsg("timestamp units \"%s\" not supported",
                                lowunits)));
                result = 0;
        }

    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("timestamp units \"%s\" not recognized", lowunits)));
        result = 0;
    }

    PG_RETURN_FLOAT8(result);
}

Datum timestamp_pl_interval ( PG_FUNCTION_ARGS   ) 

Definition at line 2657 of file timestamp.c.

References date2j(), Interval::day, day_tab, ereport, errcode(), errmsg(), ERROR, isleap, j2date(), Interval::month, MONTHS_PER_YEAR, NULL, PG_GETARG_INTERVAL_P, PG_GETARG_TIMESTAMP, PG_RETURN_TIMESTAMP, Interval::time, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, tm2timestamp(), pg_tm::tm_mday, pg_tm::tm_mon, and pg_tm::tm_year.

Referenced by date_pl_interval(), generate_series_timestamp(), and timestamp_mi_interval().

{
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(0);
    Interval   *span = PG_GETARG_INTERVAL_P(1);
    Timestamp   result;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        result = timestamp;
    else
    {
        if (span->month != 0)
        {
            struct pg_tm tt,
                       *tm = &tt;
            fsec_t      fsec;

            if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));

            tm->tm_mon += span->month;
            if (tm->tm_mon > MONTHS_PER_YEAR)
            {
                tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
                tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
            }
            else if (tm->tm_mon < 1)
            {
                tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
                tm->tm_mon = tm->tm_mon % MONTHS_PER_YEAR + MONTHS_PER_YEAR;
            }

            /* adjust for end of month boundary problems... */
            if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
                tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);

            if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));
        }

        if (span->day != 0)
        {
            struct pg_tm tt,
                       *tm = &tt;
            fsec_t      fsec;
            int         julian;

            if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));

            /* Add days by converting to and from julian */
            julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + span->day;
            j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);

            if (tm2timestamp(tm, fsec, NULL, &timestamp) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));
        }

        timestamp += span->time;
        result = timestamp;
    }

    PG_RETURN_TIMESTAMP(result);
}

Datum timestamp_recv ( PG_FUNCTION_ARGS   ) 

Definition at line 239 of file timestamp.c.

References AdjustTimestampForTypmod(), buf, ereport, errcode(), errmsg(), ERROR, NULL, PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_TIMESTAMP, pq_getmsgfloat8(), pq_getmsgint64(), timestamp2tm(), TIMESTAMP_NOT_FINITE, and tm.

{
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       typmod = PG_GETARG_INT32(2);
    Timestamp   timestamp;
    struct pg_tm tt,
               *tm = &tt;
    fsec_t      fsec;

#ifdef HAVE_INT64_TIMESTAMP
    timestamp = (Timestamp) pq_getmsgint64(buf);
#else
    timestamp = (Timestamp) pq_getmsgfloat8(buf);

    if (isnan(timestamp))
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("timestamp cannot be NaN")));
#endif

    /* rangecheck: see if timestamp_out would like it */
    if (TIMESTAMP_NOT_FINITE(timestamp))
         /* ok */ ;
    else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("timestamp out of range")));

    AdjustTimestampForTypmod(&timestamp, typmod);

    PG_RETURN_TIMESTAMP(timestamp);
}

Datum timestamp_scale ( PG_FUNCTION_ARGS   ) 

Definition at line 327 of file timestamp.c.

References AdjustTimestampForTypmod(), PG_GETARG_INT32, PG_GETARG_TIMESTAMP, and PG_RETURN_TIMESTAMP.

{
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(0);
    int32       typmod = PG_GETARG_INT32(1);
    Timestamp   result;

    result = timestamp;

    AdjustTimestampForTypmod(&result, typmod);

    PG_RETURN_TIMESTAMP(result);
}

Datum timestamp_send ( PG_FUNCTION_ARGS   ) 

Definition at line 280 of file timestamp.c.

References buf, PG_GETARG_TIMESTAMP, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendfloat8(), and pq_sendint64().

{
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(0);
    StringInfoData buf;

    pq_begintypsend(&buf);
#ifdef HAVE_INT64_TIMESTAMP
    pq_sendint64(&buf, timestamp);
#else
    pq_sendfloat8(&buf, timestamp);
#endif
    PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}

Datum timestamp_smaller ( PG_FUNCTION_ARGS   ) 

Definition at line 2411 of file timestamp.c.

References PG_GETARG_TIMESTAMP, PG_RETURN_TIMESTAMP, and timestamp_cmp_internal().

{
    Timestamp   dt1 = PG_GETARG_TIMESTAMP(0);
    Timestamp   dt2 = PG_GETARG_TIMESTAMP(1);
    Timestamp   result;

    /* use timestamp_cmp_internal to be sure this agrees with comparisons */
    if (timestamp_cmp_internal(dt1, dt2) < 0)
        result = dt1;
    else
        result = dt2;
    PG_RETURN_TIMESTAMP(result);
}

Datum timestamp_sortsupport ( PG_FUNCTION_ARGS   ) 

Definition at line 1971 of file timestamp.c.

References SortSupportData::comparator, PG_GETARG_POINTER, and PG_RETURN_VOID.

{
    SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);

    ssup->comparator = timestamp_fastcmp;
    PG_RETURN_VOID();
}

Datum timestamp_timestamptz ( PG_FUNCTION_ARGS   ) 
Datum timestamp_transform ( PG_FUNCTION_ARGS   ) 
Datum timestamp_trunc ( PG_FUNCTION_ARGS   ) 

Definition at line 3403 of file timestamp.c.

References date2isoweek(), DecodeUnits(), downcase_truncate_identifier(), DTK_CENTURY, DTK_DAY, DTK_DECADE, DTK_HOUR, DTK_MICROSEC, DTK_MILLENNIUM, DTK_MILLISEC, DTK_MINUTE, DTK_MONTH, DTK_QUARTER, DTK_SECOND, DTK_WEEK, DTK_YEAR, ereport, errcode(), errmsg(), ERROR, isoweek2date(), MONTHS_PER_YEAR, NULL, PG_GETARG_TEXT_PP, PG_GETARG_TIMESTAMP, PG_RETURN_TIMESTAMP, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, tm2timestamp(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, UNITS, val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

{
    text       *units = PG_GETARG_TEXT_PP(0);
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(1);
    Timestamp   result;
    int         type,
                val;
    char       *lowunits;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        PG_RETURN_TIMESTAMP(timestamp);

    lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
                                            VARSIZE_ANY_EXHDR(units),
                                            false);

    type = DecodeUnits(0, lowunits, &val);

    if (type == UNITS)
    {
        if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));

        switch (val)
        {
            case DTK_WEEK:
                {
                    int         woy;

                    woy = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);

                    /*
                     * If it is week 52/53 and the month is January, then the
                     * week must belong to the previous year. Also, some
                     * December dates belong to the next year.
                     */
                    if (woy >= 52 && tm->tm_mon == 1)
                        --tm->tm_year;
                    if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
                        ++tm->tm_year;
                    isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
                    tm->tm_hour = 0;
                    tm->tm_min = 0;
                    tm->tm_sec = 0;
                    fsec = 0;
                    break;
                }
            case DTK_MILLENNIUM:
                /* see comments in timestamptz_trunc */
                if (tm->tm_year > 0)
                    tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
                else
                    tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
            case DTK_CENTURY:
                /* see comments in timestamptz_trunc */
                if (tm->tm_year > 0)
                    tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
                else
                    tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
            case DTK_DECADE:
                /* see comments in timestamptz_trunc */
                if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
                {
                    if (tm->tm_year > 0)
                        tm->tm_year = (tm->tm_year / 10) * 10;
                    else
                        tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
                }
            case DTK_YEAR:
                tm->tm_mon = 1;
            case DTK_QUARTER:
                tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
            case DTK_MONTH:
                tm->tm_mday = 1;
            case DTK_DAY:
                tm->tm_hour = 0;
            case DTK_HOUR:
                tm->tm_min = 0;
            case DTK_MINUTE:
                tm->tm_sec = 0;
            case DTK_SECOND:
                fsec = 0;
                break;

            case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
                fsec = (fsec / 1000) * 1000;
#else
                fsec = floor(fsec * 1000) / 1000;
#endif
                break;

            case DTK_MICROSEC:
#ifndef HAVE_INT64_TIMESTAMP
                fsec = floor(fsec * 1000000) / 1000000;
#endif
                break;

            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                         errmsg("timestamp units \"%s\" not supported",
                                lowunits)));
                result = 0;
        }

        if (tm2timestamp(tm, fsec, NULL, &result) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));
    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("timestamp units \"%s\" not recognized",
                        lowunits)));
        result = 0;
    }

    PG_RETURN_TIMESTAMP(result);
}

Datum timestamp_zone ( PG_FUNCTION_ARGS   ) 

Definition at line 4527 of file timestamp.c.

References DecodeSpecial(), DetermineTimeZoneOffset(), downcase_truncate_identifier(), dt2local(), DTZ, ereport, errcode(), errmsg(), ERROR, NULL, PG_GETARG_TEXT_PP, PG_GETARG_TIMESTAMP, PG_RETURN_TIMESTAMPTZ, pg_tzset(), text_to_cstring_buffer(), timestamp2tm(), TIMESTAMP_NOT_FINITE, tm2timestamp(), TZ, TZ_STRLEN_MAX, and val.

{
    text       *zone = PG_GETARG_TEXT_PP(0);
    Timestamp   timestamp = PG_GETARG_TIMESTAMP(1);
    TimestampTz result;
    int         tz;
    char        tzname[TZ_STRLEN_MAX + 1];
    char       *lowzone;
    int         type,
                val;
    pg_tz      *tzp;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        PG_RETURN_TIMESTAMPTZ(timestamp);

    /*
     * Look up the requested timezone.  First we look in the date token table
     * (to handle cases like "EST"), and if that fails, we look in the
     * timezone database (to handle cases like "America/New_York").  (This
     * matches the order in which timestamp input checks the cases; it's
     * important because the timezone database unwisely uses a few zone names
     * that are identical to offset abbreviations.)
     */
    text_to_cstring_buffer(zone, tzname, sizeof(tzname));
    lowzone = downcase_truncate_identifier(tzname,
                                           strlen(tzname),
                                           false);

    type = DecodeSpecial(0, lowzone, &val);

    if (type == TZ || type == DTZ)
    {
        tz = -(val * MINS_PER_HOUR);
        result = dt2local(timestamp, tz);
    }
    else
    {
        tzp = pg_tzset(tzname);
        if (tzp)
        {
            /* Apply the timezone change */
            struct pg_tm tm;
            fsec_t      fsec;

            if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));
            tz = DetermineTimeZoneOffset(&tm, tzp);
            if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("could not convert to time zone \"%s\"",
                                tzname)));
        }
        else
        {
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("time zone \"%s\" not recognized", tzname)));
            result = 0;         /* keep compiler quiet */
        }
    }

    PG_RETURN_TIMESTAMPTZ(result);
}

void TimestampDifference ( TimestampTz  start_time,
TimestampTz  stop_time,
long *  secs,
int *  microsecs 
)

Definition at line 1344 of file timestamp.c.

References USECS_PER_SEC.

Referenced by BackendRun(), check_log_duration(), DetermineSleepTime(), GetReplicationApplyDelay(), GetReplicationTransferLatency(), launcher_determine_sleep(), lazy_vacuum_rel(), log_disconnections(), LogCheckpointEnd(), ProcSleep(), and schedule_alarm().

{
    TimestampTz diff = stop_time - start_time;

    if (diff <= 0)
    {
        *secs = 0;
        *microsecs = 0;
    }
    else
    {
#ifdef HAVE_INT64_TIMESTAMP
        *secs = (long) (diff / USECS_PER_SEC);
        *microsecs = (int) (diff % USECS_PER_SEC);
#else
        *secs = (long) diff;
        *microsecs = (int) ((diff - *secs) * 1000000.0);
#endif
    }
}

bool TimestampDifferenceExceeds ( TimestampTz  start_time,
TimestampTz  stop_time,
int  msec 
)

Definition at line 1374 of file timestamp.c.

References INT64CONST.

Referenced by asyncQueueFillWarning(), autovac_refresh_stats(), AutoVacLauncherMain(), do_analyze_rel(), do_start_worker(), lazy_vacuum_rel(), pgstat_report_stat(), ResolveRecoveryConflictWithVirtualXIDs(), StartOneBackgroundWorker(), XLogWalRcvSendHSFeedback(), and XLogWalRcvSendReply().

{
    TimestampTz diff = stop_time - start_time;

#ifdef HAVE_INT64_TIMESTAMP
    return (diff >= msec * INT64CONST(1000));
#else
    return (diff * 1000.0 >= msec);
#endif
}

Datum timestamptypmodin ( PG_FUNCTION_ARGS   ) 
Datum timestamptypmodout ( PG_FUNCTION_ARGS   ) 

Definition at line 303 of file timestamp.c.

References anytimestamp_typmodout(), PG_GETARG_INT32, and PG_RETURN_CSTRING.

Datum timestamptz_age ( PG_FUNCTION_ARGS   ) 

Definition at line 3272 of file timestamp.c.

References day_tab, ereport, errcode(), errmsg(), ERROR, isleap, NULL, palloc(), PG_GETARG_TIMESTAMPTZ, PG_RETURN_INTERVAL_P, timestamp2tm(), tm, tm2interval(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, and pg_tm::tm_year.

{
    TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0);
    TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1);
    Interval   *result;
    fsec_t      fsec,
                fsec1,
                fsec2;
    struct pg_tm tt,
               *tm = &tt;
    struct pg_tm tt1,
               *tm1 = &tt1;
    struct pg_tm tt2,
               *tm2 = &tt2;
    int         tz1;
    int         tz2;

    result = (Interval *) palloc(sizeof(Interval));

    if (timestamp2tm(dt1, &tz1, tm1, &fsec1, NULL, NULL) == 0 &&
        timestamp2tm(dt2, &tz2, tm2, &fsec2, NULL, NULL) == 0)
    {
        /* form the symbolic difference */
        fsec = fsec1 - fsec2;
        tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
        tm->tm_min = tm1->tm_min - tm2->tm_min;
        tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
        tm->tm_mday = tm1->tm_mday - tm2->tm_mday;
        tm->tm_mon = tm1->tm_mon - tm2->tm_mon;
        tm->tm_year = tm1->tm_year - tm2->tm_year;

        /* flip sign if necessary... */
        if (dt1 < dt2)
        {
            fsec = -fsec;
            tm->tm_sec = -tm->tm_sec;
            tm->tm_min = -tm->tm_min;
            tm->tm_hour = -tm->tm_hour;
            tm->tm_mday = -tm->tm_mday;
            tm->tm_mon = -tm->tm_mon;
            tm->tm_year = -tm->tm_year;
        }

        /* propagate any negative fields into the next higher field */
        while (fsec < 0)
        {
#ifdef HAVE_INT64_TIMESTAMP
            fsec += USECS_PER_SEC;
#else
            fsec += 1.0;
#endif
            tm->tm_sec--;
        }

        while (tm->tm_sec < 0)
        {
            tm->tm_sec += SECS_PER_MINUTE;
            tm->tm_min--;
        }

        while (tm->tm_min < 0)
        {
            tm->tm_min += MINS_PER_HOUR;
            tm->tm_hour--;
        }

        while (tm->tm_hour < 0)
        {
            tm->tm_hour += HOURS_PER_DAY;
            tm->tm_mday--;
        }

        while (tm->tm_mday < 0)
        {
            if (dt1 < dt2)
            {
                tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
                tm->tm_mon--;
            }
            else
            {
                tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
                tm->tm_mon--;
            }
        }

        while (tm->tm_mon < 0)
        {
            tm->tm_mon += MONTHS_PER_YEAR;
            tm->tm_year--;
        }

        /*
         * Note: we deliberately ignore any difference between tz1 and tz2.
         */

        /* recover sign if necessary... */
        if (dt1 < dt2)
        {
            fsec = -fsec;
            tm->tm_sec = -tm->tm_sec;
            tm->tm_min = -tm->tm_min;
            tm->tm_hour = -tm->tm_hour;
            tm->tm_mday = -tm->tm_mday;
            tm->tm_mon = -tm->tm_mon;
            tm->tm_year = -tm->tm_year;
        }

        if (tm2interval(tm, fsec, result) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("interval out of range")));
    }
    else
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("timestamp out of range")));

    PG_RETURN_INTERVAL_P(result);
}

Datum timestamptz_cmp_timestamp ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_eq_timestamp ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_ge_timestamp ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_gt_timestamp ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_in ( PG_FUNCTION_ARGS   ) 

Definition at line 413 of file timestamp.c.

References AdjustTimestampForTypmod(), DateTimeParseError(), DecodeDateTime(), DTK_DATE, DTK_EARLY, DTK_EPOCH, DTK_INVALID, DTK_LATE, elog, ereport, errcode(), errmsg(), ERROR, MAXDATEFIELDS, MAXDATELEN, ParseDateTime(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_TIMESTAMPTZ, SetEpochTimestamp(), TIMESTAMP_NOBEGIN, TIMESTAMP_NOEND, tm, and tm2timestamp().

Referenced by AlterRole(), CreateRole(), moddatetime(), pg_backup_start_time(), and readRecoveryCommandFile().

{
    char       *str = PG_GETARG_CSTRING(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       typmod = PG_GETARG_INT32(2);
    TimestampTz result;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;
    int         tz;
    int         dtype;
    int         nf;
    int         dterr;
    char       *field[MAXDATEFIELDS];
    int         ftype[MAXDATEFIELDS];
    char        workbuf[MAXDATELEN + MAXDATEFIELDS];

    dterr = ParseDateTime(str, workbuf, sizeof(workbuf),
                          field, ftype, MAXDATEFIELDS, &nf);
    if (dterr == 0)
        dterr = DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz);
    if (dterr != 0)
        DateTimeParseError(dterr, str, "timestamp with time zone");

    switch (dtype)
    {
        case DTK_DATE:
            if (tm2timestamp(tm, fsec, &tz, &result) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range: \"%s\"", str)));
            break;

        case DTK_EPOCH:
            result = SetEpochTimestamp();
            break;

        case DTK_LATE:
            TIMESTAMP_NOEND(result);
            break;

        case DTK_EARLY:
            TIMESTAMP_NOBEGIN(result);
            break;

        case DTK_INVALID:
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
              errmsg("date/time value \"%s\" is no longer supported", str)));

            TIMESTAMP_NOEND(result);
            break;

        default:
            elog(ERROR, "unexpected dtype %d while parsing timestamptz \"%s\"",
                 dtype, str);
            TIMESTAMP_NOEND(result);
    }

    AdjustTimestampForTypmod(&result, typmod);

    PG_RETURN_TIMESTAMPTZ(result);
}

Datum timestamptz_izone ( PG_FUNCTION_ARGS   ) 

Definition at line 4771 of file timestamp.c.

References DatumGetCString, Interval::day, DirectFunctionCall1, dt2local(), ereport, errcode(), errmsg(), ERROR, interval_out(), Interval::month, PG_GETARG_INTERVAL_P, PG_GETARG_TIMESTAMPTZ, PG_RETURN_TIMESTAMP, PointerGetDatum, Interval::time, and TIMESTAMP_NOT_FINITE.

{
    Interval   *zone = PG_GETARG_INTERVAL_P(0);
    TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
    Timestamp   result;
    int         tz;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        PG_RETURN_TIMESTAMP(timestamp);

    if (zone->month != 0 || zone->day != 0)
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                 errmsg("interval time zone \"%s\" must not include months or days",
                        DatumGetCString(DirectFunctionCall1(interval_out,
                                                  PointerGetDatum(zone))))));

#ifdef HAVE_INT64_TIMESTAMP
    tz = -(zone->time / USECS_PER_SEC);
#else
    tz = -zone->time;
#endif

    result = dt2local(timestamp, tz);

    PG_RETURN_TIMESTAMP(result);
}

Datum timestamptz_le_timestamp ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_lt_timestamp ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_mi_interval ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_ne_timestamp ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_out ( PG_FUNCTION_ARGS   ) 

Definition at line 484 of file timestamp.c.

References buf, DateStyle, EncodeDateTime(), EncodeSpecialTimestamp(), ereport, errcode(), errmsg(), ERROR, MAXDATELEN, NULL, PG_GETARG_TIMESTAMPTZ, PG_RETURN_CSTRING, pstrdup(), timestamp2tm(), TIMESTAMP_NOT_FINITE, and tm.

{
    TimestampTz dt = PG_GETARG_TIMESTAMPTZ(0);
    char       *result;
    int         tz;
    struct pg_tm tt,
               *tm = &tt;
    fsec_t      fsec;
    const char *tzn;
    char        buf[MAXDATELEN + 1];

    if (TIMESTAMP_NOT_FINITE(dt))
        EncodeSpecialTimestamp(dt, buf);
    else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0)
        EncodeDateTime(tm, fsec, true, tz, tzn, DateStyle, buf);
    else
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("timestamp out of range")));

    result = pstrdup(buf);
    PG_RETURN_CSTRING(result);
}

Datum timestamptz_part ( PG_FUNCTION_ARGS   ) 

Definition at line 4176 of file timestamp.c.

References date2isoweek(), date2isoyear(), date2j(), DecodeSpecial(), DecodeUnits(), downcase_truncate_identifier(), DTK_CENTURY, DTK_DAY, DTK_DECADE, DTK_DOW, DTK_DOY, DTK_EPOCH, DTK_HOUR, DTK_ISODOW, DTK_ISOYEAR, DTK_JULIAN, DTK_MICROSEC, DTK_MILLENNIUM, DTK_MILLISEC, DTK_MINUTE, DTK_MONTH, DTK_QUARTER, DTK_SECOND, DTK_TZ, DTK_TZ_HOUR, DTK_TZ_MINUTE, DTK_WEEK, DTK_YEAR, ereport, errcode(), errmsg(), ERROR, FMODULO, j2day(), MINS_PER_HOUR, NULL, PG_GETARG_TEXT_PP, PG_GETARG_TIMESTAMPTZ, PG_RETURN_FLOAT8, RESERV, SECS_PER_DAY, SECS_PER_HOUR, SetEpochTimestamp(), timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, UNITS, UNKNOWN_FIELD, val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

{
    text       *units = PG_GETARG_TEXT_PP(0);
    TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
    float8      result;
    int         tz;
    int         type,
                val;
    char       *lowunits;
    double      dummy;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;

    if (TIMESTAMP_NOT_FINITE(timestamp))
    {
        result = 0;
        PG_RETURN_FLOAT8(result);
    }

    lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
                                            VARSIZE_ANY_EXHDR(units),
                                            false);

    type = DecodeUnits(0, lowunits, &val);
    if (type == UNKNOWN_FIELD)
        type = DecodeSpecial(0, lowunits, &val);

    if (type == UNITS)
    {
        if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));

        switch (val)
        {
            case DTK_TZ:
                result = -tz;
                break;

            case DTK_TZ_MINUTE:
                result = -tz;
                result /= MINS_PER_HOUR;
                FMODULO(result, dummy, (double) MINS_PER_HOUR);
                break;

            case DTK_TZ_HOUR:
                dummy = -tz;
                FMODULO(dummy, result, (double) SECS_PER_HOUR);
                break;

            case DTK_MICROSEC:
#ifdef HAVE_INT64_TIMESTAMP
                result = tm->tm_sec * 1000000.0 + fsec;
#else
                result = (tm->tm_sec + fsec) * 1000000;
#endif
                break;

            case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
                result = tm->tm_sec * 1000.0 + fsec / 1000.0;
#else
                result = (tm->tm_sec + fsec) * 1000;
#endif
                break;

            case DTK_SECOND:
#ifdef HAVE_INT64_TIMESTAMP
                result = tm->tm_sec + fsec / 1000000.0;
#else
                result = tm->tm_sec + fsec;
#endif
                break;

            case DTK_MINUTE:
                result = tm->tm_min;
                break;

            case DTK_HOUR:
                result = tm->tm_hour;
                break;

            case DTK_DAY:
                result = tm->tm_mday;
                break;

            case DTK_MONTH:
                result = tm->tm_mon;
                break;

            case DTK_QUARTER:
                result = (tm->tm_mon - 1) / 3 + 1;
                break;

            case DTK_WEEK:
                result = (float8) date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);
                break;

            case DTK_YEAR:
                if (tm->tm_year > 0)
                    result = tm->tm_year;
                else
                    /* there is no year 0, just 1 BC and 1 AD */
                    result = tm->tm_year - 1;
                break;

            case DTK_DECADE:
                /* see comments in timestamp_part */
                if (tm->tm_year > 0)
                    result = tm->tm_year / 10;
                else
                    result = -((8 - (tm->tm_year - 1)) / 10);
                break;

            case DTK_CENTURY:
                /* see comments in timestamp_part */
                if (tm->tm_year > 0)
                    result = (tm->tm_year + 99) / 100;
                else
                    result = -((99 - (tm->tm_year - 1)) / 100);
                break;

            case DTK_MILLENNIUM:
                /* see comments in timestamp_part */
                if (tm->tm_year > 0)
                    result = (tm->tm_year + 999) / 1000;
                else
                    result = -((999 - (tm->tm_year - 1)) / 1000);
                break;

            case DTK_JULIAN:
                result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
#ifdef HAVE_INT64_TIMESTAMP
                result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
                    tm->tm_sec + (fsec / 1000000.0)) / (double) SECS_PER_DAY;
#else
                result += ((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) +
                           tm->tm_sec + fsec) / (double) SECS_PER_DAY;
#endif
                break;

            case DTK_ISOYEAR:
                result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday);
                break;

            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                errmsg("timestamp with time zone units \"%s\" not supported",
                       lowunits)));
                result = 0;
        }

    }
    else if (type == RESERV)
    {
        switch (val)
        {
            case DTK_EPOCH:
#ifdef HAVE_INT64_TIMESTAMP
                result = (timestamp - SetEpochTimestamp()) / 1000000.0;
#else
                result = timestamp - SetEpochTimestamp();
#endif
                break;

            case DTK_DOW:
            case DTK_ISODOW:
                if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
                    ereport(ERROR,
                            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                             errmsg("timestamp out of range")));
                result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
                if (val == DTK_ISODOW && result == 0)
                    result = 7;
                break;

            case DTK_DOY:
                if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
                    ereport(ERROR,
                            (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                             errmsg("timestamp out of range")));
                result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
                          - date2j(tm->tm_year, 1, 1) + 1);
                break;

            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                errmsg("timestamp with time zone units \"%s\" not supported",
                       lowunits)));
                result = 0;
        }
    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
               errmsg("timestamp with time zone units \"%s\" not recognized",
                      lowunits)));

        result = 0;
    }

    PG_RETURN_FLOAT8(result);
}

Datum timestamptz_pl_interval ( PG_FUNCTION_ARGS   ) 

Definition at line 2756 of file timestamp.c.

References date2j(), Interval::day, day_tab, DetermineTimeZoneOffset(), ereport, errcode(), errmsg(), ERROR, isleap, j2date(), Interval::month, MONTHS_PER_YEAR, NULL, PG_GETARG_INTERVAL_P, PG_GETARG_TIMESTAMPTZ, PG_RETURN_TIMESTAMP, session_timezone, Interval::time, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, tm2timestamp(), pg_tm::tm_mday, pg_tm::tm_mon, and pg_tm::tm_year.

Referenced by generate_series_timestamptz(), and timestamptz_mi_interval().

{
    TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);
    Interval   *span = PG_GETARG_INTERVAL_P(1);
    TimestampTz result;
    int         tz;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        result = timestamp;
    else
    {
        if (span->month != 0)
        {
            struct pg_tm tt,
                       *tm = &tt;
            fsec_t      fsec;

            if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));

            tm->tm_mon += span->month;
            if (tm->tm_mon > MONTHS_PER_YEAR)
            {
                tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
                tm->tm_mon = ((tm->tm_mon - 1) % MONTHS_PER_YEAR) + 1;
            }
            else if (tm->tm_mon < 1)
            {
                tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
                tm->tm_mon = tm->tm_mon % MONTHS_PER_YEAR + MONTHS_PER_YEAR;
            }

            /* adjust for end of month boundary problems... */
            if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
                tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);

            tz = DetermineTimeZoneOffset(tm, session_timezone);

            if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));
        }

        if (span->day != 0)
        {
            struct pg_tm tt,
                       *tm = &tt;
            fsec_t      fsec;
            int         julian;

            if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));

            /* Add days by converting to and from julian */
            julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + span->day;
            j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);

            tz = DetermineTimeZoneOffset(tm, session_timezone);

            if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));
        }

        timestamp += span->time;
        result = timestamp;
    }

    PG_RETURN_TIMESTAMP(result);
}

Datum timestamptz_recv ( PG_FUNCTION_ARGS   ) 

Definition at line 515 of file timestamp.c.

References AdjustTimestampForTypmod(), buf, ereport, errcode(), errmsg(), ERROR, NULL, PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_TIMESTAMPTZ, pq_getmsgfloat8(), pq_getmsgint64(), timestamp2tm(), TIMESTAMP_NOT_FINITE, and tm.

{
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);

#ifdef NOT_USED
    Oid         typelem = PG_GETARG_OID(1);
#endif
    int32       typmod = PG_GETARG_INT32(2);
    TimestampTz timestamp;
    int         tz;
    struct pg_tm tt,
               *tm = &tt;
    fsec_t      fsec;

#ifdef HAVE_INT64_TIMESTAMP
    timestamp = (TimestampTz) pq_getmsgint64(buf);
#else
    timestamp = (TimestampTz) pq_getmsgfloat8(buf);
#endif

    /* rangecheck: see if timestamptz_out would like it */
    if (TIMESTAMP_NOT_FINITE(timestamp))
         /* ok */ ;
    else if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
        ereport(ERROR,
                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                 errmsg("timestamp out of range")));

    AdjustTimestampForTypmod(&timestamp, typmod);

    PG_RETURN_TIMESTAMPTZ(timestamp);
}

Datum timestamptz_scale ( PG_FUNCTION_ARGS   ) 
Datum timestamptz_send ( PG_FUNCTION_ARGS   ) 

Definition at line 552 of file timestamp.c.

References buf, PG_GETARG_TIMESTAMPTZ, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendfloat8(), and pq_sendint64().

{
    TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);
    StringInfoData buf;

    pq_begintypsend(&buf);
#ifdef HAVE_INT64_TIMESTAMP
    pq_sendint64(&buf, timestamp);
#else
    pq_sendfloat8(&buf, timestamp);
#endif
    PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}

Datum timestamptz_timestamp ( PG_FUNCTION_ARGS   ) 

Definition at line 4670 of file timestamp.c.

References ereport, errcode(), errmsg(), ERROR, NULL, PG_GETARG_TIMESTAMPTZ, PG_RETURN_TIMESTAMP, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, and tm2timestamp().

{
    TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(0);
    Timestamp   result;
    struct pg_tm tt,
               *tm = &tt;
    fsec_t      fsec;
    int         tz;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        result = timestamp;
    else
    {
        if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));
        if (tm2timestamp(tm, fsec, NULL, &result) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));
    }
    PG_RETURN_TIMESTAMP(result);
}

const char* timestamptz_to_str ( TimestampTz  t  ) 

Definition at line 1447 of file timestamp.c.

References buf, EncodeDateTime(), EncodeSpecialTimestamp(), MAXDATELEN, NULL, strlcpy(), timestamp2tm(), TIMESTAMP_NOT_FINITE, timestamptz_to_time_t(), tm, USE_ISO_DATES, and USECS_PER_SEC.

{
    static char buf[MAXDATELEN + 1];
    int         tz;
    struct pg_tm tt,
               *tm = &tt;
    fsec_t      fsec;
    const char *tzn;

    if (TIMESTAMP_NOT_FINITE(t))
        EncodeSpecialTimestamp(t, buf);
    else if (timestamp2tm(t, &tz, tm, &fsec, &tzn, NULL) == 0)
        EncodeDateTime(tm, fsec, true, tz, tzn, USE_ISO_DATES, buf);
    else
        strlcpy(buf, "(timestamp out of range)", sizeof(buf));

    return buf;
}

pg_time_t timestamptz_to_time_t ( TimestampTz  t  ) 

Definition at line 1424 of file timestamp.c.

References POSTGRES_EPOCH_JDATE, SECS_PER_DAY, UNIX_EPOCH_JDATE, and USECS_PER_SEC.

{
    pg_time_t   result;

#ifdef HAVE_INT64_TIMESTAMP
    result = (pg_time_t) (t / USECS_PER_SEC +
                 ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
#else
    result = (pg_time_t) (t +
                 ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY));
#endif

    return result;
}

Datum timestamptz_trunc ( PG_FUNCTION_ARGS   ) 

Definition at line 3535 of file timestamp.c.

References date2isoweek(), DecodeUnits(), DetermineTimeZoneOffset(), downcase_truncate_identifier(), DTK_CENTURY, DTK_DAY, DTK_DECADE, DTK_HOUR, DTK_MICROSEC, DTK_MILLENNIUM, DTK_MILLISEC, DTK_MINUTE, DTK_MONTH, DTK_QUARTER, DTK_SECOND, DTK_WEEK, DTK_YEAR, ereport, errcode(), errmsg(), ERROR, isoweek2date(), MONTHS_PER_YEAR, NULL, PG_GETARG_TEXT_PP, PG_GETARG_TIMESTAMPTZ, PG_RETURN_TIMESTAMPTZ, session_timezone, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, tm2timestamp(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, UNITS, val, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

{
    text       *units = PG_GETARG_TEXT_PP(0);
    TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
    TimestampTz result;
    int         tz;
    int         type,
                val;
    bool        redotz = false;
    char       *lowunits;
    fsec_t      fsec;
    struct pg_tm tt,
               *tm = &tt;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        PG_RETURN_TIMESTAMPTZ(timestamp);

    lowunits = downcase_truncate_identifier(VARDATA_ANY(units),
                                            VARSIZE_ANY_EXHDR(units),
                                            false);

    type = DecodeUnits(0, lowunits, &val);

    if (type == UNITS)
    {
        if (timestamp2tm(timestamp, &tz, tm, &fsec, NULL, NULL) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));

        switch (val)
        {
            case DTK_WEEK:
                {
                    int         woy;

                    woy = date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday);

                    /*
                     * If it is week 52/53 and the month is January, then the
                     * week must belong to the previous year. Also, some
                     * December dates belong to the next year.
                     */
                    if (woy >= 52 && tm->tm_mon == 1)
                        --tm->tm_year;
                    if (woy <= 1 && tm->tm_mon == MONTHS_PER_YEAR)
                        ++tm->tm_year;
                    isoweek2date(woy, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
                    tm->tm_hour = 0;
                    tm->tm_min = 0;
                    tm->tm_sec = 0;
                    fsec = 0;
                    redotz = true;
                    break;
                }
                /* one may consider DTK_THOUSAND and DTK_HUNDRED... */
            case DTK_MILLENNIUM:

                /*
                 * truncating to the millennium? what is this supposed to
                 * mean? let us put the first year of the millennium... i.e.
                 * -1000, 1, 1001, 2001...
                 */
                if (tm->tm_year > 0)
                    tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999;
                else
                    tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1;
                /* FALL THRU */
            case DTK_CENTURY:
                /* truncating to the century? as above: -100, 1, 101... */
                if (tm->tm_year > 0)
                    tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99;
                else
                    tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1;
                /* FALL THRU */
            case DTK_DECADE:

                /*
                 * truncating to the decade? first year of the decade. must
                 * not be applied if year was truncated before!
                 */
                if (val != DTK_MILLENNIUM && val != DTK_CENTURY)
                {
                    if (tm->tm_year > 0)
                        tm->tm_year = (tm->tm_year / 10) * 10;
                    else
                        tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10;
                }
                /* FALL THRU */
            case DTK_YEAR:
                tm->tm_mon = 1;
                /* FALL THRU */
            case DTK_QUARTER:
                tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1;
                /* FALL THRU */
            case DTK_MONTH:
                tm->tm_mday = 1;
                /* FALL THRU */
            case DTK_DAY:
                tm->tm_hour = 0;
                redotz = true;  /* for all cases >= DAY */
                /* FALL THRU */
            case DTK_HOUR:
                tm->tm_min = 0;
                /* FALL THRU */
            case DTK_MINUTE:
                tm->tm_sec = 0;
                /* FALL THRU */
            case DTK_SECOND:
                fsec = 0;
                break;

            case DTK_MILLISEC:
#ifdef HAVE_INT64_TIMESTAMP
                fsec = (fsec / 1000) * 1000;
#else
                fsec = floor(fsec * 1000) / 1000;
#endif
                break;
            case DTK_MICROSEC:
#ifndef HAVE_INT64_TIMESTAMP
                fsec = floor(fsec * 1000000) / 1000000;
#endif
                break;

            default:
                ereport(ERROR,
                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                         errmsg("timestamp with time zone units \"%s\" not "
                                "supported", lowunits)));
                result = 0;
        }

        if (redotz)
            tz = DetermineTimeZoneOffset(tm, session_timezone);

        if (tm2timestamp(tm, fsec, &tz, &result) != 0)
            ereport(ERROR,
                    (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                     errmsg("timestamp out of range")));
    }
    else
    {
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
               errmsg("timestamp with time zone units \"%s\" not recognized",
                      lowunits)));
        result = 0;
    }

    PG_RETURN_TIMESTAMPTZ(result);
}

Datum timestamptz_zone ( PG_FUNCTION_ARGS   ) 

Definition at line 4700 of file timestamp.c.

References DecodeSpecial(), downcase_truncate_identifier(), dt2local(), DTZ, ereport, errcode(), errmsg(), ERROR, NULL, PG_GETARG_TEXT_PP, PG_GETARG_TIMESTAMPTZ, PG_RETURN_TIMESTAMP, pg_tzset(), text_to_cstring_buffer(), timestamp2tm(), TIMESTAMP_NOT_FINITE, tm2timestamp(), TZ, TZ_STRLEN_MAX, and val.

{
    text       *zone = PG_GETARG_TEXT_PP(0);
    TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1);
    Timestamp   result;
    int         tz;
    char        tzname[TZ_STRLEN_MAX + 1];
    char       *lowzone;
    int         type,
                val;
    pg_tz      *tzp;

    if (TIMESTAMP_NOT_FINITE(timestamp))
        PG_RETURN_TIMESTAMP(timestamp);

    /*
     * Look up the requested timezone.  First we look in the date token table
     * (to handle cases like "EST"), and if that fails, we look in the
     * timezone database (to handle cases like "America/New_York").  (This
     * matches the order in which timestamp input checks the cases; it's
     * important because the timezone database unwisely uses a few zone names
     * that are identical to offset abbreviations.)
     */
    text_to_cstring_buffer(zone, tzname, sizeof(tzname));
    lowzone = downcase_truncate_identifier(tzname,
                                           strlen(tzname),
                                           false);

    type = DecodeSpecial(0, lowzone, &val);

    if (type == TZ || type == DTZ)
    {
        tz = val * MINS_PER_HOUR;
        result = dt2local(timestamp, tz);
    }
    else
    {
        tzp = pg_tzset(tzname);
        if (tzp)
        {
            /* Apply the timezone change */
            struct pg_tm tm;
            fsec_t      fsec;

            if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                         errmsg("timestamp out of range")));
            if (tm2timestamp(&tm, fsec, NULL, &result) != 0)
                ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("could not convert to time zone \"%s\"",
                                tzname)));
        }
        else
        {
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                     errmsg("time zone \"%s\" not recognized", tzname)));
            result = 0;         /* keep compiler quiet */
        }
    }

    PG_RETURN_TIMESTAMP(result);
}

Datum timestamptztypmodin ( PG_FUNCTION_ARGS   ) 
Datum timestamptztypmodout ( PG_FUNCTION_ARGS   ) 

Definition at line 575 of file timestamp.c.

References anytimestamp_typmodout(), PG_GETARG_INT32, and PG_RETURN_CSTRING.

int tm2interval ( struct pg_tm tm,
fsec_t  fsec,
Interval span 
)

Definition at line 1756 of file timestamp.c.

References Interval::day, INT64CONST, MINS_PER_HOUR, Interval::month, MONTHS_PER_YEAR, Interval::time, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, and pg_tm::tm_year.

Referenced by interval_in(), interval_trunc(), pg_timezone_abbrevs(), pg_timezone_names(), PGTYPESinterval_from_asc(), timestamp_age(), and timestamptz_age().

{
    span->month = tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon;
    span->day = tm->tm_mday;
#ifdef HAVE_INT64_TIMESTAMP
    span->time = (((((tm->tm_hour * INT64CONST(60)) +
                     tm->tm_min) * INT64CONST(60)) +
                   tm->tm_sec) * USECS_PER_SEC) + fsec;
#else
    span->time = (((tm->tm_hour * (double) MINS_PER_HOUR) +
                   tm->tm_min) * (double) SECS_PER_MINUTE) +
        tm->tm_sec + fsec;
#endif

    return 0;
}

int tm2timestamp ( struct pg_tm tm,
fsec_t  fsec,
int *  tzp,
Timestamp result 
)

Definition at line 1669 of file timestamp.c.

References date2j(), dt2local(), IS_VALID_JULIAN, NULL, SECS_PER_DAY, time2t(), pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_year, and USECS_PER_DAY.

Referenced by abstime_timestamp(), abstime_timestamptz(), PGTYPEStimestamp_add_interval(), PGTYPEStimestamp_current(), PGTYPEStimestamp_defmt_scan(), PGTYPEStimestamp_from_asc(), SetEpochTimestamp(), timestamp2timestamptz(), timestamp_in(), timestamp_pl_interval(), timestamp_trunc(), timestamp_zone(), timestamptz_in(), timestamptz_pl_interval(), timestamptz_timestamp(), timestamptz_trunc(), timestamptz_zone(), and to_timestamp().

{
    TimeOffset  date;
    TimeOffset  time;

    /* Julian day routines are not correct for negative Julian days */
    if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
    {
        *result = 0;            /* keep compiler quiet */
        return -1;
    }

    date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;
    time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);

#ifdef HAVE_INT64_TIMESTAMP
    *result = date * USECS_PER_DAY + time;
    /* check for major overflow */
    if ((*result - time) / USECS_PER_DAY != date)
    {
        *result = 0;            /* keep compiler quiet */
        return -1;
    }
    /* check for just-barely overflow (okay except time-of-day wraps) */
    /* caution: we want to allow 1999-12-31 24:00:00 */
    if ((*result < 0 && date > 0) ||
        (*result > 0 && date < -1))
    {
        *result = 0;            /* keep compiler quiet */
        return -1;
    }
#else
    *result = date * SECS_PER_DAY + time;
#endif
    if (tzp != NULL)
        *result = dt2local(*result, -(*tzp));

    return 0;
}


Variable Documentation

Definition at line 49 of file timestamp.c.

Referenced by pg_conf_load_time().

Definition at line 46 of file timestamp.c.

Referenced by pg_postmaster_start_time(), PostgresMain(), and PostmasterMain().