Header And Logo

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

Defines | Functions | Variables

timestamp.h File Reference

#include "datatype/timestamp.h"
#include "fmgr.h"
#include "pgtime.h"
Include dependency graph for timestamp.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define DatumGetTimestamp(X)   ((Timestamp) DatumGetFloat8(X))
#define DatumGetTimestampTz(X)   ((TimestampTz) DatumGetFloat8(X))
#define DatumGetIntervalP(X)   ((Interval *) DatumGetPointer(X))
#define TimestampGetDatum(X)   Float8GetDatum(X)
#define TimestampTzGetDatum(X)   Float8GetDatum(X)
#define IntervalPGetDatum(X)   PointerGetDatum(X)
#define PG_GETARG_TIMESTAMP(n)   DatumGetTimestamp(PG_GETARG_DATUM(n))
#define PG_GETARG_TIMESTAMPTZ(n)   DatumGetTimestampTz(PG_GETARG_DATUM(n))
#define PG_GETARG_INTERVAL_P(n)   DatumGetIntervalP(PG_GETARG_DATUM(n))
#define PG_RETURN_TIMESTAMP(x)   return TimestampGetDatum(x)
#define PG_RETURN_TIMESTAMPTZ(x)   return TimestampTzGetDatum(x)
#define PG_RETURN_INTERVAL_P(x)   return IntervalPGetDatum(x)
#define TIMESTAMP_MASK(b)   (1 << (b))
#define INTERVAL_MASK(b)   (1 << (b))
#define INTERVAL_FULL_RANGE   (0x7FFF)
#define INTERVAL_RANGE_MASK   (0x7FFF)
#define INTERVAL_FULL_PRECISION   (0xFFFF)
#define INTERVAL_PRECISION_MASK   (0xFFFF)
#define INTERVAL_TYPMOD(p, r)   ((((r) & INTERVAL_RANGE_MASK) << 16) | ((p) & INTERVAL_PRECISION_MASK))
#define INTERVAL_PRECISION(t)   ((t) & INTERVAL_PRECISION_MASK)
#define INTERVAL_RANGE(t)   (((t) >> 16) & INTERVAL_RANGE_MASK)
#define TimestampTzPlusMilliseconds(tz, ms)   ((tz) + ((ms) / 1000.0))
#define timestamptz_cmp_internal(dt1, dt2)   timestamp_cmp_internal(dt1, dt2)

Functions

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 timestamp_eq (PG_FUNCTION_ARGS)
Datum timestamp_ne (PG_FUNCTION_ARGS)
Datum timestamp_lt (PG_FUNCTION_ARGS)
Datum timestamp_le (PG_FUNCTION_ARGS)
Datum timestamp_ge (PG_FUNCTION_ARGS)
Datum timestamp_gt (PG_FUNCTION_ARGS)
Datum timestamp_finite (PG_FUNCTION_ARGS)
Datum timestamp_cmp (PG_FUNCTION_ARGS)
Datum timestamp_sortsupport (PG_FUNCTION_ARGS)
Datum timestamp_hash (PG_FUNCTION_ARGS)
Datum timestamp_smaller (PG_FUNCTION_ARGS)
Datum timestamp_larger (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_le_timestamptz (PG_FUNCTION_ARGS)
Datum timestamp_gt_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_le_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_gt_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_ge_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_cmp_timestamp (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 interval_eq (PG_FUNCTION_ARGS)
Datum interval_ne (PG_FUNCTION_ARGS)
Datum interval_lt (PG_FUNCTION_ARGS)
Datum interval_le (PG_FUNCTION_ARGS)
Datum interval_ge (PG_FUNCTION_ARGS)
Datum interval_gt (PG_FUNCTION_ARGS)
Datum interval_finite (PG_FUNCTION_ARGS)
Datum interval_cmp (PG_FUNCTION_ARGS)
Datum interval_hash (PG_FUNCTION_ARGS)
Datum interval_smaller (PG_FUNCTION_ARGS)
Datum interval_larger (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_trunc (PG_FUNCTION_ARGS)
Datum interval_trunc (PG_FUNCTION_ARGS)
Datum timestamp_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_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 timestamptz_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_zone (PG_FUNCTION_ARGS)
Datum timestamptz_izone (PG_FUNCTION_ARGS)
Datum timestamptz_timestamptz (PG_FUNCTION_ARGS)
Datum interval_um (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_mi (PG_FUNCTION_ARGS)
Datum timestamp_pl_interval (PG_FUNCTION_ARGS)
Datum timestamp_mi_interval (PG_FUNCTION_ARGS)
Datum timestamp_age (PG_FUNCTION_ARGS)
Datum overlaps_timestamp (PG_FUNCTION_ARGS)
Datum timestamptz_pl_interval (PG_FUNCTION_ARGS)
Datum timestamptz_mi_interval (PG_FUNCTION_ARGS)
Datum timestamptz_age (PG_FUNCTION_ARGS)
Datum timestamptz_trunc (PG_FUNCTION_ARGS)
Datum timestamptz_part (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)
Datum generate_series_timestamp (PG_FUNCTION_ARGS)
Datum generate_series_timestamptz (PG_FUNCTION_ARGS)
TimestampTz GetCurrentTimestamp (void)
void TimestampDifference (TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
bool TimestampDifferenceExceeds (TimestampTz start_time, TimestampTz stop_time, int msec)
int64 GetCurrentIntegerTimestamp (void)
TimestampTz IntegerTimestampToTimestampTz (int64 timestamp)
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)
int tm2timestamp (struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *dt)
int timestamp2tm (Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
void dt2time (Timestamp dt, int *hour, int *min, int *sec, fsec_t *fsec)
int interval2tm (Interval span, struct pg_tm *tm, fsec_t *fsec)
int tm2interval (struct pg_tm *tm, fsec_t fsec, Interval *span)
Timestamp SetEpochTimestamp (void)
void GetEpochTime (struct pg_tm *tm)
int timestamp_cmp_internal (Timestamp dt1, Timestamp dt2)
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)

Variables

TimestampTz PgStartTime
TimestampTz PgReloadTime

Define Documentation

#define DatumGetIntervalP (   X  )     ((Interval *) DatumGetPointer(X))
#define DatumGetTimestamp (   X  )     ((Timestamp) DatumGetFloat8(X))
#define DatumGetTimestampTz (   X  )     ((TimestampTz) DatumGetFloat8(X))
#define INTERVAL_FULL_PRECISION   (0xFFFF)

Definition at line 71 of file timestamp.h.

Referenced by AdjustIntervalForTypmod(), intervaltypmodin(), and intervaltypmodout().

#define INTERVAL_FULL_RANGE   (0x7FFF)
#define INTERVAL_MASK (   b  )     (1 << (b))
#define INTERVAL_PRECISION (   t  )     ((t) & INTERVAL_PRECISION_MASK)

Definition at line 74 of file timestamp.h.

Referenced by AdjustIntervalForTypmod(), interval_transform(), and intervaltypmodout().

#define INTERVAL_PRECISION_MASK   (0xFFFF)

Definition at line 72 of file timestamp.h.

#define INTERVAL_RANGE (   t  )     (((t) >> 16) & INTERVAL_RANGE_MASK)
#define INTERVAL_RANGE_MASK   (0x7FFF)

Definition at line 70 of file timestamp.h.

#define INTERVAL_TYPMOD (   p,
  r 
)    ((((r) & INTERVAL_RANGE_MASK) << 16) | ((p) & INTERVAL_PRECISION_MASK))

Definition at line 73 of file timestamp.h.

Referenced by intervaltypmodin().

#define IntervalPGetDatum (   X  )     PointerGetDatum(X)
#define PG_GETARG_INTERVAL_P (   n  )     DatumGetIntervalP(PG_GETARG_DATUM(n))
#define PG_GETARG_TIMESTAMP (   n  )     DatumGetTimestamp(PG_GETARG_DATUM(n))
#define PG_GETARG_TIMESTAMPTZ (   n  )     DatumGetTimestampTz(PG_GETARG_DATUM(n))
#define PG_RETURN_INTERVAL_P (   x  )     return IntervalPGetDatum(x)
#define PG_RETURN_TIMESTAMP (   x  )     return TimestampGetDatum(x)
#define PG_RETURN_TIMESTAMPTZ (   x  )     return TimestampTzGetDatum(x)
#define TIMESTAMP_MASK (   b  )     (1 << (b))

Definition at line 65 of file timestamp.h.

#define TimestampGetDatum (   X  )     Float8GetDatum(X)
#define timestamptz_cmp_internal (   dt1,
  dt2 
)    timestamp_cmp_internal(dt1, dt2)
#define TimestampTzGetDatum (   X  )     Float8GetDatum(X)
#define TimestampTzPlusMilliseconds (   tz,
  ms 
)    ((tz) + ((ms) / 1000.0))

Function Documentation

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

void dt2time ( Timestamp  dt,
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() */

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

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

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

Datum timestamptz_timestamptz ( PG_FUNCTION_ARGS   ) 
const char* timestamptz_to_str ( TimestampTz  t  ) 

Definition at line 55 of file compat.c.

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

Referenced by backend_read_statsfile(), CreateRestartPoint(), pgstat_recv_inquiry(), ProcessWalSndrMessage(), readRecoveryCommandFile(), recoveryStopsHere(), StartupXLOG(), xact_desc_abort(), xact_desc_commit(), xact_desc_commit_compact(), and xlog_desc().

{
    static char buf[MAXDATELEN + 1];
    char        ts[MAXDATELEN + 1];
    char        zone[MAXDATELEN + 1];
    time_t      result = (time_t) timestamptz_to_time_t(dt);
    struct tm  *ltime = localtime(&result);

    strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", ltime);
    strftime(zone, sizeof(zone), "%Z", ltime);

#ifdef HAVE_INT64_TIMESTAMP
    sprintf(buf, "%s.%06d %s", ts, (int) (dt % USECS_PER_SEC), zone);
#else
    sprintf(buf, "%s.%.6f %s", ts, fabs(dt - floor(dt)), zone);
#endif

    return buf;
}

pg_time_t timestamptz_to_time_t ( TimestampTz  t  ) 

Definition at line 28 of file compat.c.

References POSTGRES_EPOCH_JDATE, SECS_PER_DAY, UNIX_EPOCH_JDATE, and USECS_PER_SEC.

Referenced by BackendInitialize(), and timestamptz_to_str().

{
    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 dt 
)

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