#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"
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) |
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() */
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;
}
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;
}
Definition at line 1010 of file timestamp.c.
References interval::month, PGTYPEStimestamp_add_interval(), and interval::time.
| 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() */
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() */
1.7.1