#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() */