Header And Logo

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

Functions

timestamp.c File Reference

#include "postgres_fe.h"
#include <time.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include "extern.h"
#include "dt.h"
#include "pgtypes_timestamp.h"
#include "pgtypes_date.h"
Include dependency graph for timestamp.c:

Go to the source code of this file.

Functions

int PGTYPEStimestamp_defmt_scan (char **, const char *, timestamp *, int *, int *, int *, int *, int *, int *, int *)
static double time2t (const int hour, const int min, const int sec, const fsec_t fsec)
static timestamp dt2local (timestamp dt, int tz)
int tm2timestamp (struct tm *tm, fsec_t fsec, int *tzp, timestamp *result)
static timestamp SetEpochTimestamp (void)
static int timestamp2tm (timestamp dt, int *tzp, struct tm *tm, fsec_t *fsec, const char **tzn)
static int EncodeSpecialTimestamp (timestamp dt, char *str)
timestamp PGTYPEStimestamp_from_asc (char *str, char **endptr)
char * PGTYPEStimestamp_to_asc (timestamp tstamp)
void PGTYPEStimestamp_current (timestamp *ts)
static int dttofmtasc_replace (timestamp *ts, date dDate, int dow, struct tm *tm, char *output, int *pstr_len, const char *fmtstr)
int PGTYPEStimestamp_fmt_asc (timestamp *ts, char *output, int str_len, const char *fmtstr)
int PGTYPEStimestamp_sub (timestamp *ts1, timestamp *ts2, interval *iv)
int PGTYPEStimestamp_defmt_asc (char *str, const char *fmt, timestamp *d)
int PGTYPEStimestamp_add_interval (timestamp *tin, interval *span, timestamp *tout)
int PGTYPEStimestamp_sub_interval (timestamp *tin, interval *span, timestamp *tout)

Function Documentation

static timestamp dt2local ( timestamp  dt,
int  tz 
) [static]

Definition at line 39 of file timestamp.c.

Referenced by tm2timestamp().

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

static int dttofmtasc_replace ( timestamp ts,
date  dDate,
int  dow,
struct tm tm,
char *  output,
int *  pstr_len,
const char *  fmtstr 
) [static]

Definition at line 386 of file timestamp.c.

References un_fmt_comb::char_val, days, un_fmt_comb::double_val, i, un_fmt_comb::int64_val, months, pgtypes_date_months, pgtypes_date_weekdays_short, pgtypes_fmt_replace(), SetEpochTimestamp(), un_fmt_comb::str_val, and un_fmt_comb::uint_val.

Referenced by PGTYPEStimestamp_fmt_asc().

{
    union un_fmt_comb replace_val;
    int         replace_type;
    int         i;
    const char *p = fmtstr;
    char       *q = output;

    while (*p)
    {
        if (*p == '%')
        {
            p++;
            /* fix compiler warning */
            replace_type = PGTYPES_TYPE_NOTHING;
            switch (*p)
            {
                    /* the abbreviated name of the day in the week */
                    /* XXX should be locale aware */
                case 'a':
                    replace_val.str_val = pgtypes_date_weekdays_short[dow];
                    replace_type = PGTYPES_TYPE_STRING_CONSTANT;
                    break;
                    /* the full name of the day in the week */
                    /* XXX should be locale aware */
                case 'A':
                    replace_val.str_val = days[dow];
                    replace_type = PGTYPES_TYPE_STRING_CONSTANT;
                    break;
                    /* the abbreviated name of the month */
                    /* XXX should be locale aware */
                case 'b':
                case 'h':
                    replace_val.str_val = months[tm->tm_mon];
                    replace_type = PGTYPES_TYPE_STRING_CONSTANT;
                    break;
                    /* the full name name of the month */
                    /* XXX should be locale aware */
                case 'B':
                    replace_val.str_val = pgtypes_date_months[tm->tm_mon];
                    replace_type = PGTYPES_TYPE_STRING_CONSTANT;
                    break;

                    /*
                     * The  preferred  date  and  time  representation  for
                     * the current locale.
                     */
                case 'c':
                    /* XXX */
                    break;
                    /* the century number with leading zeroes */
                case 'C':
                    replace_val.uint_val = tm->tm_year / 100;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;
                    /* day with leading zeroes (01 - 31) */
                case 'd':
                    replace_val.uint_val = tm->tm_mday;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;
                    /* the date in the format mm/dd/yy */
                case 'D':

                    /*
                     * ts, dDate, dow, tm is information about the timestamp
                     *
                     * q is the start of the current output buffer
                     *
                     * pstr_len is a pointer to the remaining size of output,
                     * i.e. the size of q
                     */
                    i = dttofmtasc_replace(ts, dDate, dow, tm,
                                           q, pstr_len,
                                           "%m/%d/%y");
                    if (i)
                        return i;
                    break;
                    /* day with leading spaces (01 - 31) */
                case 'e':
                    replace_val.uint_val = tm->tm_mday;
                    replace_type = PGTYPES_TYPE_UINT_2_LS;
                    break;

                    /*
                     * alternative format modifier
                     */
                case 'E':
                    {
                        char        tmp[4] = "%Ex";

                        p++;
                        if (*p == '\0')
                            return -1;
                        tmp[2] = *p;

                        /*
                         * strftime's month is 0 based, ours is 1 based
                         */
                        tm->tm_mon -= 1;
                        i = strftime(q, *pstr_len, tmp, tm);
                        if (i == 0)
                            return -1;
                        while (*q)
                        {
                            q++;
                            (*pstr_len)--;
                        }
                        tm->tm_mon += 1;
                        replace_type = PGTYPES_TYPE_NOTHING;
                        break;
                    }

                    /*
                     * The ISO 8601 year with century as a decimal number. The
                     * 4-digit year corresponding to the ISO week number.
                     */
                case 'G':
                    {
                        /* Keep compiler quiet - Don't use a literal format */
                        const char *fmt = "%G";

                        tm->tm_mon -= 1;
                        i = strftime(q, *pstr_len, fmt, tm);
                        if (i == 0)
                            return -1;
                        while (*q)
                        {
                            q++;
                            (*pstr_len)--;
                        }
                        tm->tm_mon += 1;
                        replace_type = PGTYPES_TYPE_NOTHING;
                    }
                    break;

                    /*
                     * Like %G, but without century, i.e., with a 2-digit year
                     * (00-99).
                     */
                case 'g':
                    {
                        const char *fmt = "%g"; /* Keep compiler quiet about
                                                 * 2-digit year */

                        tm->tm_mon -= 1;
                        i = strftime(q, *pstr_len, fmt, tm);
                        if (i == 0)
                            return -1;
                        while (*q)
                        {
                            q++;
                            (*pstr_len)--;
                        }
                        tm->tm_mon += 1;
                        replace_type = PGTYPES_TYPE_NOTHING;
                    }
                    break;
                    /* hour (24 hour clock) with leading zeroes */
                case 'H':
                    replace_val.uint_val = tm->tm_hour;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;
                    /* hour (12 hour clock) with leading zeroes */
                case 'I':
                    replace_val.uint_val = tm->tm_hour % 12;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;

                    /*
                     * The day of the year as a decimal number with leading
                     * zeroes. It ranges from 001 to 366.
                     */
                case 'j':
                    replace_val.uint_val = tm->tm_yday;
                    replace_type = PGTYPES_TYPE_UINT_3_LZ;
                    break;

                    /*
                     * The hour (24 hour clock). Leading zeroes will be turned
                     * into spaces.
                     */
                case 'k':
                    replace_val.uint_val = tm->tm_hour;
                    replace_type = PGTYPES_TYPE_UINT_2_LS;
                    break;

                    /*
                     * The hour (12 hour clock). Leading zeroes will be turned
                     * into spaces.
                     */
                case 'l':
                    replace_val.uint_val = tm->tm_hour % 12;
                    replace_type = PGTYPES_TYPE_UINT_2_LS;
                    break;
                    /* The month as a decimal number with a leading zero */
                case 'm':
                    replace_val.uint_val = tm->tm_mon;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;
                    /* The minute as a decimal number with a leading zero */
                case 'M':
                    replace_val.uint_val = tm->tm_min;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;
                    /* A newline character */
                case 'n':
                    replace_val.char_val = '\n';
                    replace_type = PGTYPES_TYPE_CHAR;
                    break;
                    /* the AM/PM specifier (uppercase) */
                    /* XXX should be locale aware */
                case 'p':
                    if (tm->tm_hour < 12)
                        replace_val.str_val = "AM";
                    else
                        replace_val.str_val = "PM";
                    replace_type = PGTYPES_TYPE_STRING_CONSTANT;
                    break;
                    /* the AM/PM specifier (lowercase) */
                    /* XXX should be locale aware */
                case 'P':
                    if (tm->tm_hour < 12)
                        replace_val.str_val = "am";
                    else
                        replace_val.str_val = "pm";
                    replace_type = PGTYPES_TYPE_STRING_CONSTANT;
                    break;
                    /* the time in the format %I:%M:%S %p */
                    /* XXX should be locale aware */
                case 'r':
                    i = dttofmtasc_replace(ts, dDate, dow, tm,
                                           q, pstr_len,
                                           "%I:%M:%S %p");
                    if (i)
                        return i;
                    break;
                    /* The time in 24 hour notation (%H:%M) */
                case 'R':
                    i = dttofmtasc_replace(ts, dDate, dow, tm,
                                           q, pstr_len,
                                           "%H:%M");
                    if (i)
                        return i;
                    break;
                    /* The number of seconds since the Epoch (1970-01-01) */
                case 's':
#ifdef HAVE_INT64_TIMESTAMP
                    replace_val.int64_val = (*ts - SetEpochTimestamp()) / 1000000.0;
                    replace_type = PGTYPES_TYPE_INT64;
#else
                    replace_val.double_val = *ts - SetEpochTimestamp();
                    replace_type = PGTYPES_TYPE_DOUBLE_NF;
#endif
                    break;
                    /* seconds as a decimal number with leading zeroes */
                case 'S':
                    replace_val.uint_val = tm->tm_sec;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;
                    /* A tabulator */
                case 't':
                    replace_val.char_val = '\t';
                    replace_type = PGTYPES_TYPE_CHAR;
                    break;
                    /* The time in 24 hour notation (%H:%M:%S) */
                case 'T':
                    i = dttofmtasc_replace(ts, dDate, dow, tm,
                                           q, pstr_len,
                                           "%H:%M:%S");
                    if (i)
                        return i;
                    break;

                    /*
                     * The day of the week as a decimal, Monday = 1, Sunday =
                     * 7
                     */
                case 'u':
                    replace_val.uint_val = dow;
                    if (replace_val.uint_val == 0)
                        replace_val.uint_val = 7;
                    replace_type = PGTYPES_TYPE_UINT;
                    break;
                    /* The week number of the year as a decimal number */
                case 'U':
                    tm->tm_mon -= 1;
                    i = strftime(q, *pstr_len, "%U", tm);
                    if (i == 0)
                        return -1;
                    while (*q)
                    {
                        q++;
                        (*pstr_len)--;
                    }
                    tm->tm_mon += 1;
                    replace_type = PGTYPES_TYPE_NOTHING;
                    break;

                    /*
                     * The ISO 8601:1988 week number of the current year as a
                     * decimal number.
                     */
                case 'V':
                    {
                        /* Keep compiler quiet - Don't use a literal format */
                        const char *fmt = "%V";

                        i = strftime(q, *pstr_len, fmt, tm);
                        if (i == 0)
                            return -1;
                        while (*q)
                        {
                            q++;
                            (*pstr_len)--;
                        }
                        replace_type = PGTYPES_TYPE_NOTHING;
                    }
                    break;

                    /*
                     * The day of the week as a decimal, Sunday being 0 and
                     * Monday 1.
                     */
                case 'w':
                    replace_val.uint_val = dow;
                    replace_type = PGTYPES_TYPE_UINT;
                    break;
                    /* The week number of the year (another definition) */
                case 'W':
                    tm->tm_mon -= 1;
                    i = strftime(q, *pstr_len, "%U", tm);
                    if (i == 0)
                        return -1;
                    while (*q)
                    {
                        q++;
                        (*pstr_len)--;
                    }
                    tm->tm_mon += 1;
                    replace_type = PGTYPES_TYPE_NOTHING;
                    break;

                    /*
                     * The preferred date representation for the current
                     * locale without the time.
                     */
                case 'x':
                    {
                        const char *fmt = "%x"; /* Keep compiler quiet about
                                                 * 2-digit year */

                        tm->tm_mon -= 1;
                        i = strftime(q, *pstr_len, fmt, tm);
                        if (i == 0)
                            return -1;
                        while (*q)
                        {
                            q++;
                            (*pstr_len)--;
                        }
                        tm->tm_mon += 1;
                        replace_type = PGTYPES_TYPE_NOTHING;
                    }
                    break;

                    /*
                     * The preferred time representation for the current
                     * locale without the date.
                     */
                case 'X':
                    tm->tm_mon -= 1;
                    i = strftime(q, *pstr_len, "%X", tm);
                    if (i == 0)
                        return -1;
                    while (*q)
                    {
                        q++;
                        (*pstr_len)--;
                    }
                    tm->tm_mon += 1;
                    replace_type = PGTYPES_TYPE_NOTHING;
                    break;
                    /* The year without the century (2 digits, leading zeroes) */
                case 'y':
                    replace_val.uint_val = tm->tm_year % 100;
                    replace_type = PGTYPES_TYPE_UINT_2_LZ;
                    break;
                    /* The year with the century (4 digits) */
                case 'Y':
                    replace_val.uint_val = tm->tm_year;
                    replace_type = PGTYPES_TYPE_UINT;
                    break;
                    /* The time zone offset from GMT */
                case 'z':
                    tm->tm_mon -= 1;
                    i = strftime(q, *pstr_len, "%z", tm);
                    if (i == 0)
                        return -1;
                    while (*q)
                    {
                        q++;
                        (*pstr_len)--;
                    }
                    tm->tm_mon += 1;
                    replace_type = PGTYPES_TYPE_NOTHING;
                    break;
                    /* The name or abbreviation of the time zone */
                case 'Z':
                    tm->tm_mon -= 1;
                    i = strftime(q, *pstr_len, "%Z", tm);
                    if (i == 0)
                        return -1;
                    while (*q)
                    {
                        q++;
                        (*pstr_len)--;
                    }
                    tm->tm_mon += 1;
                    replace_type = PGTYPES_TYPE_NOTHING;
                    break;
                    /* A % sign */
                case '%':
                    replace_val.char_val = '%';
                    replace_type = PGTYPES_TYPE_CHAR;
                    break;
                case '\0':
                    /* fmtstr: foo%' - The string ends with a % sign */

                    /*
                     * this is not compliant to the specification
                     */
                    return -1;
                default:

                    /*
                     * if we don't know the pattern, we just copy it
                     */
                    if (*pstr_len > 1)
                    {
                        *q = '%';
                        q++;
                        (*pstr_len)--;
                        if (*pstr_len > 1)
                        {
                            *q = *p;
                            q++;
                            (*pstr_len)--;
                        }
                        else
                        {
                            *q = '\0';
                            return -1;
                        }
                        *q = '\0';
                    }
                    else
                        return -1;
                    break;
            }
            i = pgtypes_fmt_replace(replace_val, replace_type, &q, pstr_len);
            if (i)
                return i;
        }
        else
        {
            if (*pstr_len > 1)
            {
                *q = *p;
                (*pstr_len)--;
                q++;
                *q = '\0';
            }
            else
                return -1;
        }
        p++;
    }
    return 0;
}

static int EncodeSpecialTimestamp ( timestamp  dt,
char *  str 
) [static]

Definition at line 265 of file timestamp.c.

References EARLY, LATE, TIMESTAMP_IS_NOBEGIN, and TIMESTAMP_IS_NOEND.

Referenced by PGTYPEStimestamp_to_asc().

{
    if (TIMESTAMP_IS_NOBEGIN(dt))
        strcpy(str, EARLY);
    else if (TIMESTAMP_IS_NOEND(dt))
        strcpy(str, LATE);
    else
        return FALSE;

    return TRUE;
}   /* EncodeSpecialTimestamp() */

int PGTYPEStimestamp_add_interval ( timestamp tin,
interval span,
timestamp tout 
)

Definition at line 949 of file timestamp.c.

References day_tab, isleap, interval::month, MONTHS_PER_YEAR, NULL, interval::time, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, tm2timestamp(), and pg_tm::tm_mon.

Referenced by main(), and PGTYPEStimestamp_sub_interval().

{


    if (TIMESTAMP_NOT_FINITE(*tin))
        *tout = *tin;


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


            if (timestamp2tm(*tin, NULL, tm, &fsec, NULL) != 0)
                return -1;
            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, tin) != 0)
                return -1;
        }


        *tin += span->time;
        *tout = *tin;
    }
    return 0;

}

void PGTYPEStimestamp_current ( timestamp ts  ) 

Definition at line 375 of file timestamp.c.

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

Referenced by dtcurrent(), and main().

{
    struct tm   tm;

    GetCurrentDateTime(&tm);
    if (errno == 0)
        tm2timestamp(&tm, 0, NULL, ts);
    return;
}

int PGTYPEStimestamp_defmt_asc ( char *  str,
const char *  fmt,
timestamp d 
)

Definition at line 897 of file timestamp.c.

References free, i, pgtypes_strdup(), and PGTYPEStimestamp_defmt_scan().

Referenced by dtcvfmtasc(), and main().

{
    int         year,
                month,
                day;
    int         hour,
                minute,
                second;
    int         tz;

    int         i;
    char       *mstr;
    char       *mfmt;

    if (!fmt)
        fmt = "%Y-%m-%d %H:%M:%S";
    if (!fmt[0])
        return 1;

    mstr = pgtypes_strdup(str);
    mfmt = pgtypes_strdup(fmt);

    /*
     * initialize with impossible values so that we can see if the fields
     * where specified at all
     */
    /* XXX ambiguity with 1 BC for year? */
    year = -1;
    month = -1;
    day = -1;
    hour = 0;
    minute = -1;
    second = -1;
    tz = 0;

    i = PGTYPEStimestamp_defmt_scan(&mstr, mfmt, d, &year, &month, &day, &hour, &minute, &second, &tz);
    free(mstr);
    free(mfmt);
    return i;
}

int PGTYPEStimestamp_defmt_scan ( char **  ,
const char *  ,
timestamp ,
int *  ,
int *  ,
int *  ,
int *  ,
int *  ,
int *  ,
int *   
)
int PGTYPEStimestamp_fmt_asc ( timestamp ts,
char *  output,
int  str_len,
const char *  fmtstr 
)

Definition at line 869 of file timestamp.c.

References dttofmtasc_replace(), NULL, PGTYPESdate_dayofweek(), PGTYPESdate_from_timestamp(), timestamp2tm(), and tm.

Referenced by dttofmtasc(), and main().

{
    struct tm   tm;
    fsec_t      fsec;
    date        dDate;
    int         dow;

    dDate = PGTYPESdate_from_timestamp(*ts);
    dow = PGTYPESdate_dayofweek(dDate);
    timestamp2tm(*ts, NULL, &tm, &fsec, NULL);

    return dttofmtasc_replace(ts, dDate, dow, &tm, output, &str_len, fmtstr);
}

timestamp PGTYPEStimestamp_from_asc ( char *  str,
char **  endptr 
)

Definition at line 278 of file timestamp.c.

References DecodeDateTime(), DTK_DATE, DTK_EARLY, DTK_EPOCH, DTK_INVALID, DTK_LATE, MAXDATELEN, NULL, ParseDateTime(), SetEpochTimestamp(), TIMESTAMP_NOBEGIN, TIMESTAMP_NOEND, tm, and tm2timestamp().

Referenced by dtcvasc(), ecpg_get_data(), and main().

{
    timestamp   result;

#ifdef HAVE_INT64_TIMESTAMP
    int64       noresult = 0;
#else
    double      noresult = 0.0;
#endif
    fsec_t      fsec;
    struct tm   tt,
               *tm = &tt;
    int         dtype;
    int         nf;
    char       *field[MAXDATEFIELDS];
    int         ftype[MAXDATEFIELDS];
    char        lowstr[MAXDATELEN + MAXDATEFIELDS];
    char       *realptr;
    char      **ptr = (endptr != NULL) ? endptr : &realptr;

    if (strlen(str) >= sizeof(lowstr))
    {
        errno = PGTYPES_TS_BAD_TIMESTAMP;
        return (noresult);
    }

    if (ParseDateTime(str, lowstr, field, ftype, &nf, ptr) != 0 ||
        DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, 0) != 0)
    {
        errno = PGTYPES_TS_BAD_TIMESTAMP;
        return (noresult);
    }

    switch (dtype)
    {
        case DTK_DATE:
            if (tm2timestamp(tm, fsec, NULL, &result) != 0)
            {
                errno = PGTYPES_TS_BAD_TIMESTAMP;
                return (noresult);
            }
            break;

        case DTK_EPOCH:
            result = SetEpochTimestamp();
            break;

        case DTK_LATE:
            TIMESTAMP_NOEND(result);
            break;

        case DTK_EARLY:
            TIMESTAMP_NOBEGIN(result);
            break;

        case DTK_INVALID:
            errno = PGTYPES_TS_BAD_TIMESTAMP;
            return (noresult);

        default:
            errno = PGTYPES_TS_BAD_TIMESTAMP;
            return (noresult);
    }

    /* AdjustTimestampForTypmod(&result, typmod); */

    /*
     * Since it's difficult to test for noresult, make sure errno is 0 if no
     * error occurred.
     */
    errno = 0;
    return result;
}

int PGTYPEStimestamp_sub ( timestamp ts1,
timestamp ts2,
interval iv 
)

Definition at line 884 of file timestamp.c.

References interval::month, interval::time, and TIMESTAMP_NOT_FINITE.

Referenced by dtsub().

{
    if (TIMESTAMP_NOT_FINITE(*ts1) || TIMESTAMP_NOT_FINITE(*ts2))
        return PGTYPES_TS_ERR_EINFTIME;
    else
        iv->time = (*ts1 - *ts2);

    iv->month = 0;

    return 0;
}

int PGTYPEStimestamp_sub_interval ( timestamp tin,
interval span,
timestamp tout 
)

Definition at line 1010 of file timestamp.c.

References interval::month, PGTYPEStimestamp_add_interval(), and interval::time.

{
    interval    tspan;

    tspan.month = -span->month;
    tspan.time = -span->time;


    return PGTYPEStimestamp_add_interval(tin, &tspan, tout);
}

char* PGTYPEStimestamp_to_asc ( timestamp  tstamp  ) 

Definition at line 353 of file timestamp.c.

References buf, DateStyle, EncodeDateTime(), EncodeSpecialTimestamp(), MAXDATELEN, NULL, pgtypes_strdup(), timestamp2tm(), TIMESTAMP_NOT_FINITE, and tm.

Referenced by dttoasc(), ecpg_store_input(), and main().

{
    struct tm   tt,
               *tm = &tt;
    char        buf[MAXDATELEN + 1];
    fsec_t      fsec;
    int         DateStyle = 1;  /* this defaults to ISO_DATES, shall we make
                                 * it an option? */

    if (TIMESTAMP_NOT_FINITE(tstamp))
        EncodeSpecialTimestamp(tstamp, buf);
    else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0)
        EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf, 0);
    else
    {
        errno = PGTYPES_TS_BAD_TIMESTAMP;
        return NULL;
    }
    return pgtypes_strdup(buf);
}

static timestamp SetEpochTimestamp ( void   )  [static]

Definition at line 93 of file timestamp.c.

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

{
#ifdef HAVE_INT64_TIMESTAMP
    int64       noresult = 0;
#else
    double      noresult = 0.0;
#endif
    timestamp   dt;
    struct tm   tt,
               *tm = &tt;

    if (GetEpochTime(tm) < 0)
        return noresult;

    tm2timestamp(tm, 0, NULL, &dt);
    return dt;
}   /* SetEpochTimestamp() */

static double time2t ( const int  hour,
const int  min,
const int  sec,
const fsec_t  fsec 
) [static]

Definition at line 32 of file timestamp.c.

References MINS_PER_HOUR, and SECS_PER_MINUTE.

Referenced by tm2timestamp().

{
    return (((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec + fsec;
}   /* time2t() */

static int timestamp2tm ( timestamp  dt,
int *  tzp,
struct tm tm,
fsec_t fsec,
const char **  tzn 
) [static]

Definition at line 123 of file timestamp.c.

References date2j(), dt2time(), INT64CONST, IS_VALID_UTIME, j2date(), NULL, SECS_PER_DAY, SECS_PER_HOUR, TIMEZONE_GLOBAL, TMODULO, TSROUND, TZNAME_GLOBAL, USECS_PER_DAY, and USECS_PER_SEC.

{
#ifdef HAVE_INT64_TIMESTAMP
    int64       dDate,
                date0;
    int64       time;
#else
    double      dDate,
                date0;
    double      time;
#endif
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
    time_t      utime;
    struct tm  *tx;
#endif

    date0 = date2j(2000, 1, 1);

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

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

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

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

    j2date((int) dDate, &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, dDate, (double) SECS_PER_DAY);

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

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

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

    j2date((int) dDate, &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;
            dDate += 1;
            goto recalc_d;
        }
        goto recalc_t;
    }
#endif

    if (tzp != NULL)
    {
        /*
         * Does this fall within the capabilities of the localtime()
         * interface? Then use this to rotate to the local time zone.
         */
        if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
        {
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)

#ifdef HAVE_INT64_TIMESTAMP
            utime = dt / USECS_PER_SEC +
                ((date0 - date2j(1970, 1, 1)) * INT64CONST(86400));
#else
            utime = dt + (date0 - date2j(1970, 1, 1)) * SECS_PER_DAY;
#endif

            tx = localtime(&utime);
            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_isdst = tx->tm_isdst;

#if defined(HAVE_TM_ZONE)
            tm->tm_gmtoff = tx->tm_gmtoff;
            tm->tm_zone = tx->tm_zone;

            *tzp = -tm->tm_gmtoff;      /* tm_gmtoff is Sun/DEC-ism */
            if (tzn != NULL)
                *tzn = tm->tm_zone;
#elif defined(HAVE_INT_TIMEZONE)
            *tzp = (tm->tm_isdst > 0) ? TIMEZONE_GLOBAL - SECS_PER_HOUR : TIMEZONE_GLOBAL;
            if (tzn != NULL)
                *tzn = TZNAME_GLOBAL[(tm->tm_isdst > 0)];
#endif
#else                           /* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
            *tzp = 0;
            /* Mark this as *no* time zone available */
            tm->tm_isdst = -1;
            if (tzn != NULL)
                *tzn = NULL;
#endif
        }
        else
        {
            *tzp = 0;
            /* Mark this as *no* time zone available */
            tm->tm_isdst = -1;
            if (tzn != NULL)
                *tzn = NULL;
        }
    }
    else
    {
        tm->tm_isdst = -1;
        if (tzn != NULL)
            *tzn = NULL;
    }

    return 0;
}   /* timestamp2tm() */

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

Definition at line 57 of file timestamp.c.

References date2j(), dt2local(), IS_VALID_JULIAN, NULL, SECS_PER_DAY, time2t(), and USECS_PER_DAY.

{
#ifdef HAVE_INT64_TIMESTAMP
    int         dDate;
    int64       time;
#else
    double      dDate,
                time;
#endif

    /* Julian day routines are not correct for negative Julian days */
    if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
        return -1;

    dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
    time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
#ifdef HAVE_INT64_TIMESTAMP
    *result = (dDate * USECS_PER_DAY) + time;
    /* check for major overflow */
    if ((*result - time) / USECS_PER_DAY != dDate)
        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 && dDate > 0) ||
        (*result > 0 && dDate < -1))
        return -1;
#else
    *result = dDate * SECS_PER_DAY + time;
#endif
    if (tzp != NULL)
        *result = dt2local(*result, -(*tzp));

    return 0;
}   /* tm2timestamp() */