PostgreSQL Source Code  git master
timestamp.c File Reference
#include "postgres_fe.h"
#include <time.h>
#include <limits.h>
#include <math.h>
#include "dt.h"
#include "pgtypes_date.h"
#include "pgtypes_timestamp.h"
#include "pgtypeslib_extern.h"
Include dependency graph for timestamp.c:

Go to the source code of this file.

Functions

static int64 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 void 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 (const 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

◆ dt2local()

static timestamp dt2local ( timestamp  dt,
int  tz 
)
static

Definition at line 26 of file timestamp.c.

27 {
28  dt -= (tz * USECS_PER_SEC);
29  return dt;
30 } /* dt2local() */
#define USECS_PER_SEC
Definition: timestamp.h:134

References USECS_PER_SEC.

Referenced by tm2timestamp().

◆ dttofmtasc_replace()

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 304 of file timestamp.c.

306 {
307  union un_fmt_comb replace_val;
308  int replace_type;
309  int i;
310  const char *p = fmtstr;
311  char *q = output;
312 
313  while (*p)
314  {
315  if (*p == '%')
316  {
317  p++;
318  /* fix compiler warning */
319  replace_type = PGTYPES_TYPE_NOTHING;
320  switch (*p)
321  {
322  /* the abbreviated name of the day in the week */
323  /* XXX should be locale aware */
324  case 'a':
325  replace_val.str_val = pgtypes_date_weekdays_short[dow];
326  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
327  break;
328  /* the full name of the day in the week */
329  /* XXX should be locale aware */
330  case 'A':
331  replace_val.str_val = days[dow];
332  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
333  break;
334  /* the abbreviated name of the month */
335  /* XXX should be locale aware */
336  case 'b':
337  case 'h':
338  replace_val.str_val = months[tm->tm_mon - 1];
339  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
340  break;
341  /* the full name of the month */
342  /* XXX should be locale aware */
343  case 'B':
344  replace_val.str_val = pgtypes_date_months[tm->tm_mon - 1];
345  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
346  break;
347 
348  /*
349  * The preferred date and time representation for the
350  * current locale.
351  */
352  case 'c':
353  /* XXX */
354  break;
355  /* the century number with leading zeroes */
356  case 'C':
357  replace_val.uint_val = tm->tm_year / 100;
358  replace_type = PGTYPES_TYPE_UINT_2_LZ;
359  break;
360  /* day with leading zeroes (01 - 31) */
361  case 'd':
362  replace_val.uint_val = tm->tm_mday;
363  replace_type = PGTYPES_TYPE_UINT_2_LZ;
364  break;
365  /* the date in the format mm/dd/yy */
366  case 'D':
367 
368  /*
369  * ts, dDate, dow, tm is information about the timestamp
370  *
371  * q is the start of the current output buffer
372  *
373  * pstr_len is a pointer to the remaining size of output,
374  * i.e. the size of q
375  */
376  i = dttofmtasc_replace(ts, dDate, dow, tm,
377  q, pstr_len,
378  "%m/%d/%y");
379  if (i)
380  return i;
381  break;
382  /* day with leading spaces (01 - 31) */
383  case 'e':
384  replace_val.uint_val = tm->tm_mday;
385  replace_type = PGTYPES_TYPE_UINT_2_LS;
386  break;
387 
388  /*
389  * alternative format modifier
390  */
391  case 'E':
392  {
393  char tmp[4] = "%Ex";
394 
395  p++;
396  if (*p == '\0')
397  return -1;
398  tmp[2] = *p;
399 
400  /*
401  * strftime's month is 0 based, ours is 1 based
402  */
403  tm->tm_mon -= 1;
404  i = strftime(q, *pstr_len, tmp, tm);
405  if (i == 0)
406  return -1;
407  while (*q)
408  {
409  q++;
410  (*pstr_len)--;
411  }
412  tm->tm_mon += 1;
413  replace_type = PGTYPES_TYPE_NOTHING;
414  break;
415  }
416 
417  /*
418  * The ISO 8601 year with century as a decimal number. The
419  * 4-digit year corresponding to the ISO week number.
420  */
421  case 'G':
422  {
423  /* Keep compiler quiet - Don't use a literal format */
424  const char *fmt = "%G";
425 
426  tm->tm_mon -= 1;
427  i = strftime(q, *pstr_len, fmt, tm);
428  if (i == 0)
429  return -1;
430  while (*q)
431  {
432  q++;
433  (*pstr_len)--;
434  }
435  tm->tm_mon += 1;
436  replace_type = PGTYPES_TYPE_NOTHING;
437  }
438  break;
439 
440  /*
441  * Like %G, but without century, i.e., with a 2-digit year
442  * (00-99).
443  */
444  case 'g':
445  {
446  const char *fmt = "%g"; /* Keep compiler quiet about
447  * 2-digit year */
448 
449  tm->tm_mon -= 1;
450  i = strftime(q, *pstr_len, fmt, tm);
451  if (i == 0)
452  return -1;
453  while (*q)
454  {
455  q++;
456  (*pstr_len)--;
457  }
458  tm->tm_mon += 1;
459  replace_type = PGTYPES_TYPE_NOTHING;
460  }
461  break;
462  /* hour (24 hour clock) with leading zeroes */
463  case 'H':
464  replace_val.uint_val = tm->tm_hour;
465  replace_type = PGTYPES_TYPE_UINT_2_LZ;
466  break;
467  /* hour (12 hour clock) with leading zeroes */
468  case 'I':
469  replace_val.uint_val = tm->tm_hour % 12;
470  replace_type = PGTYPES_TYPE_UINT_2_LZ;
471  break;
472 
473  /*
474  * The day of the year as a decimal number with leading
475  * zeroes. It ranges from 001 to 366.
476  */
477  case 'j':
478  replace_val.uint_val = tm->tm_yday;
479  replace_type = PGTYPES_TYPE_UINT_3_LZ;
480  break;
481 
482  /*
483  * The hour (24 hour clock). Leading zeroes will be turned
484  * into spaces.
485  */
486  case 'k':
487  replace_val.uint_val = tm->tm_hour;
488  replace_type = PGTYPES_TYPE_UINT_2_LS;
489  break;
490 
491  /*
492  * The hour (12 hour clock). Leading zeroes will be turned
493  * into spaces.
494  */
495  case 'l':
496  replace_val.uint_val = tm->tm_hour % 12;
497  replace_type = PGTYPES_TYPE_UINT_2_LS;
498  break;
499  /* The month as a decimal number with a leading zero */
500  case 'm':
501  replace_val.uint_val = tm->tm_mon;
502  replace_type = PGTYPES_TYPE_UINT_2_LZ;
503  break;
504  /* The minute as a decimal number with a leading zero */
505  case 'M':
506  replace_val.uint_val = tm->tm_min;
507  replace_type = PGTYPES_TYPE_UINT_2_LZ;
508  break;
509  /* A newline character */
510  case 'n':
511  replace_val.char_val = '\n';
512  replace_type = PGTYPES_TYPE_CHAR;
513  break;
514  /* the AM/PM specifier (uppercase) */
515  /* XXX should be locale aware */
516  case 'p':
517  if (tm->tm_hour < 12)
518  replace_val.str_val = "AM";
519  else
520  replace_val.str_val = "PM";
521  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
522  break;
523  /* the AM/PM specifier (lowercase) */
524  /* XXX should be locale aware */
525  case 'P':
526  if (tm->tm_hour < 12)
527  replace_val.str_val = "am";
528  else
529  replace_val.str_val = "pm";
530  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
531  break;
532  /* the time in the format %I:%M:%S %p */
533  /* XXX should be locale aware */
534  case 'r':
535  i = dttofmtasc_replace(ts, dDate, dow, tm,
536  q, pstr_len,
537  "%I:%M:%S %p");
538  if (i)
539  return i;
540  break;
541  /* The time in 24 hour notation (%H:%M) */
542  case 'R':
543  i = dttofmtasc_replace(ts, dDate, dow, tm,
544  q, pstr_len,
545  "%H:%M");
546  if (i)
547  return i;
548  break;
549  /* The number of seconds since the Epoch (1970-01-01) */
550  case 's':
551  replace_val.int64_val = (*ts - SetEpochTimestamp()) / 1000000.0;
552  replace_type = PGTYPES_TYPE_INT64;
553  break;
554  /* seconds as a decimal number with leading zeroes */
555  case 'S':
556  replace_val.uint_val = tm->tm_sec;
557  replace_type = PGTYPES_TYPE_UINT_2_LZ;
558  break;
559  /* A tabulator */
560  case 't':
561  replace_val.char_val = '\t';
562  replace_type = PGTYPES_TYPE_CHAR;
563  break;
564  /* The time in 24 hour notation (%H:%M:%S) */
565  case 'T':
566  i = dttofmtasc_replace(ts, dDate, dow, tm,
567  q, pstr_len,
568  "%H:%M:%S");
569  if (i)
570  return i;
571  break;
572 
573  /*
574  * The day of the week as a decimal, Monday = 1, Sunday =
575  * 7
576  */
577  case 'u':
578  replace_val.uint_val = dow;
579  if (replace_val.uint_val == 0)
580  replace_val.uint_val = 7;
581  replace_type = PGTYPES_TYPE_UINT;
582  break;
583  /* The week number of the year as a decimal number */
584  case 'U':
585  tm->tm_mon -= 1;
586  i = strftime(q, *pstr_len, "%U", tm);
587  if (i == 0)
588  return -1;
589  while (*q)
590  {
591  q++;
592  (*pstr_len)--;
593  }
594  tm->tm_mon += 1;
595  replace_type = PGTYPES_TYPE_NOTHING;
596  break;
597 
598  /*
599  * The ISO 8601:1988 week number of the current year as a
600  * decimal number.
601  */
602  case 'V':
603  {
604  /* Keep compiler quiet - Don't use a literal format */
605  const char *fmt = "%V";
606 
607  i = strftime(q, *pstr_len, fmt, tm);
608  if (i == 0)
609  return -1;
610  while (*q)
611  {
612  q++;
613  (*pstr_len)--;
614  }
615  replace_type = PGTYPES_TYPE_NOTHING;
616  }
617  break;
618 
619  /*
620  * The day of the week as a decimal, Sunday being 0 and
621  * Monday 1.
622  */
623  case 'w':
624  replace_val.uint_val = dow;
625  replace_type = PGTYPES_TYPE_UINT;
626  break;
627  /* The week number of the year (another definition) */
628  case 'W':
629  tm->tm_mon -= 1;
630  i = strftime(q, *pstr_len, "%U", tm);
631  if (i == 0)
632  return -1;
633  while (*q)
634  {
635  q++;
636  (*pstr_len)--;
637  }
638  tm->tm_mon += 1;
639  replace_type = PGTYPES_TYPE_NOTHING;
640  break;
641 
642  /*
643  * The preferred date representation for the current
644  * locale without the time.
645  */
646  case 'x':
647  {
648  const char *fmt = "%x"; /* Keep compiler quiet about
649  * 2-digit year */
650 
651  tm->tm_mon -= 1;
652  i = strftime(q, *pstr_len, fmt, tm);
653  if (i == 0)
654  return -1;
655  while (*q)
656  {
657  q++;
658  (*pstr_len)--;
659  }
660  tm->tm_mon += 1;
661  replace_type = PGTYPES_TYPE_NOTHING;
662  }
663  break;
664 
665  /*
666  * The preferred time representation for the current
667  * locale without the date.
668  */
669  case 'X':
670  tm->tm_mon -= 1;
671  i = strftime(q, *pstr_len, "%X", tm);
672  if (i == 0)
673  return -1;
674  while (*q)
675  {
676  q++;
677  (*pstr_len)--;
678  }
679  tm->tm_mon += 1;
680  replace_type = PGTYPES_TYPE_NOTHING;
681  break;
682  /* The year without the century (2 digits, leading zeroes) */
683  case 'y':
684  replace_val.uint_val = tm->tm_year % 100;
685  replace_type = PGTYPES_TYPE_UINT_2_LZ;
686  break;
687  /* The year with the century (4 digits) */
688  case 'Y':
689  replace_val.uint_val = tm->tm_year;
690  replace_type = PGTYPES_TYPE_UINT;
691  break;
692  /* The time zone offset from GMT */
693  case 'z':
694  tm->tm_mon -= 1;
695  i = strftime(q, *pstr_len, "%z", tm);
696  if (i == 0)
697  return -1;
698  while (*q)
699  {
700  q++;
701  (*pstr_len)--;
702  }
703  tm->tm_mon += 1;
704  replace_type = PGTYPES_TYPE_NOTHING;
705  break;
706  /* The name or abbreviation of the time zone */
707  case 'Z':
708  tm->tm_mon -= 1;
709  i = strftime(q, *pstr_len, "%Z", tm);
710  if (i == 0)
711  return -1;
712  while (*q)
713  {
714  q++;
715  (*pstr_len)--;
716  }
717  tm->tm_mon += 1;
718  replace_type = PGTYPES_TYPE_NOTHING;
719  break;
720  /* A % sign */
721  case '%':
722  replace_val.char_val = '%';
723  replace_type = PGTYPES_TYPE_CHAR;
724  break;
725  case '\0':
726  /* fmtstr: foo%' - The string ends with a % sign */
727 
728  /*
729  * this is not compliant to the specification
730  */
731  return -1;
732  default:
733 
734  /*
735  * if we don't know the pattern, we just copy it
736  */
737  if (*pstr_len > 1)
738  {
739  *q = '%';
740  q++;
741  (*pstr_len)--;
742  if (*pstr_len > 1)
743  {
744  *q = *p;
745  q++;
746  (*pstr_len)--;
747  }
748  else
749  {
750  *q = '\0';
751  return -1;
752  }
753  *q = '\0';
754  }
755  else
756  return -1;
757  break;
758  }
759  i = pgtypes_fmt_replace(replace_val, replace_type, &q, pstr_len);
760  if (i)
761  return i;
762  }
763  else
764  {
765  if (*pstr_len > 1)
766  {
767  *q = *p;
768  (*pstr_len)--;
769  q++;
770  *q = '\0';
771  }
772  else
773  return -1;
774  }
775  p++;
776  }
777  return 0;
778 }
const char *const months[]
Definition: datetime.c:81
const char *const days[]
Definition: datetime.c:84
Timestamp SetEpochTimestamp(void)
Definition: timestamp.c:2190
char * pgtypes_date_months[]
Definition: dt_common.c:499
char * pgtypes_date_weekdays_short[]
Definition: dt_common.c:497
FILE * output
int pgtypes_fmt_replace(union un_fmt_comb replace_val, int replace_type, char **output, int *pstr_len)
Definition: common.c:30
static int dttofmtasc_replace(timestamp *ts, date dDate, int dow, struct tm *tm, char *output, int *pstr_len, const char *fmtstr)
Definition: timestamp.c:304
int i
Definition: isn.c:73
static void const char * fmt
static struct pg_tm tm
Definition: localtime.c:104
#define PGTYPES_TYPE_STRING_CONSTANT
#define PGTYPES_TYPE_NOTHING
#define PGTYPES_TYPE_UINT
#define PGTYPES_TYPE_CHAR
#define PGTYPES_TYPE_UINT_2_LS
#define PGTYPES_TYPE_UINT_2_LZ
#define PGTYPES_TYPE_INT64
#define PGTYPES_TYPE_UINT_3_LZ
static void fmtstr(const char *value, int leftjust, int minlen, int maxwidth, int pointflag, PrintfTarget *target)
Definition: snprintf.c:967
int tm_hour
Definition: pgtime.h:38
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_min
Definition: pgtime.h:37
int tm_yday
Definition: pgtime.h:43
int tm_sec
Definition: pgtime.h:36
int tm_year
Definition: pgtime.h:41

References un_fmt_comb::char_val, days, fmt, fmtstr(), i, un_fmt_comb::int64_val, months, output, pgtypes_date_months, pgtypes_date_weekdays_short, pgtypes_fmt_replace(), PGTYPES_TYPE_CHAR, PGTYPES_TYPE_INT64, PGTYPES_TYPE_NOTHING, PGTYPES_TYPE_STRING_CONSTANT, PGTYPES_TYPE_UINT, PGTYPES_TYPE_UINT_2_LS, PGTYPES_TYPE_UINT_2_LZ, PGTYPES_TYPE_UINT_3_LZ, SetEpochTimestamp(), un_fmt_comb::str_val, tm, pg_tm::tm_hour, pg_tm::tm_mday, pg_tm::tm_min, pg_tm::tm_mon, pg_tm::tm_sec, pg_tm::tm_yday, pg_tm::tm_year, and un_fmt_comb::uint_val.

Referenced by PGTYPEStimestamp_fmt_asc().

◆ EncodeSpecialTimestamp()

static void EncodeSpecialTimestamp ( timestamp  dt,
char *  str 
)
static

Definition at line 195 of file timestamp.c.

196 {
197  if (TIMESTAMP_IS_NOBEGIN(dt))
198  strcpy(str, EARLY);
199  else if (TIMESTAMP_IS_NOEND(dt))
200  strcpy(str, LATE);
201  else
202  abort(); /* shouldn't happen */
203 }
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:167
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:162
const char * str
#define EARLY
Definition: datetime.h:39
#define LATE
Definition: datetime.h:40

References EARLY, LATE, str, TIMESTAMP_IS_NOBEGIN, and TIMESTAMP_IS_NOEND.

◆ PGTYPEStimestamp_add_interval()

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

Definition at line 862 of file timestamp.c.

863 {
864  if (TIMESTAMP_NOT_FINITE(*tin))
865  *tout = *tin;
866  else
867  {
868  if (span->month != 0)
869  {
870  struct tm tt,
871  *tm = &tt;
872  fsec_t fsec;
873 
874  if (timestamp2tm(*tin, NULL, tm, &fsec, NULL) != 0)
875  return -1;
876  tm->tm_mon += span->month;
877  if (tm->tm_mon > MONTHS_PER_YEAR)
878  {
879  tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
880  tm->tm_mon = (tm->tm_mon - 1) % MONTHS_PER_YEAR + 1;
881  }
882  else if (tm->tm_mon < 1)
883  {
884  tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
886  }
887 
888 
889  /* adjust for end of month boundary problems... */
890  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
891  tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
892 
893 
894  if (tm2timestamp(tm, fsec, NULL, tin) != 0)
895  return -1;
896  }
897 
898  *tin += span->time;
899  *tout = *tin;
900  }
901 
902  return 0;
903 }
const int day_tab[2][13]
Definition: datetime.c:75
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1997
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1901
int32 fsec_t
Definition: timestamp.h:41
#define MONTHS_PER_YEAR
Definition: timestamp.h:108
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:169
#define isleap(y)
Definition: datetime.h:271

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

Referenced by main(), and PGTYPEStimestamp_sub_interval().

◆ PGTYPEStimestamp_current()

void PGTYPEStimestamp_current ( timestamp ts)

Definition at line 294 of file timestamp.c.

295 {
296  struct tm tm;
297 
299  if (errno == 0)
300  tm2timestamp(&tm, 0, NULL, ts);
301 }
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:366

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

Referenced by dtcurrent(), and main().

◆ PGTYPEStimestamp_defmt_asc()

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

Definition at line 810 of file timestamp.c.

811 {
812  int year,
813  month,
814  day;
815  int hour,
816  minute,
817  second;
818  int tz;
819 
820  int i;
821  char *mstr;
822  char *mfmt;
823 
824  if (!fmt)
825  fmt = "%Y-%m-%d %H:%M:%S";
826  if (!fmt[0])
827  return 1;
828 
829  mstr = pgtypes_strdup(str);
830  mfmt = pgtypes_strdup(fmt);
831 
832  /*
833  * initialize with impossible values so that we can see if the fields
834  * where specified at all
835  */
836  /* XXX ambiguity with 1 BC for year? */
837  year = -1;
838  month = -1;
839  day = -1;
840  hour = 0;
841  minute = -1;
842  second = -1;
843  tz = 0;
844 
845  i = PGTYPEStimestamp_defmt_scan(&mstr, mfmt, d, &year, &month, &day, &hour, &minute, &second, &tz);
846  free(mstr);
847  free(mfmt);
848  return i;
849 }
int PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp *d, int *year, int *month, int *day, int *hour, int *minute, int *second, int *tz)
Definition: dt_common.c:2519
#define free(a)
Definition: header.h:65
char * pgtypes_strdup(const char *str)
Definition: common.c:20

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

Referenced by dtcvfmtasc(), and main().

◆ PGTYPEStimestamp_fmt_asc()

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

Definition at line 782 of file timestamp.c.

783 {
784  struct tm tm;
785  fsec_t fsec;
786  date dDate;
787  int dow;
788 
789  dDate = PGTYPESdate_from_timestamp(*ts);
790  dow = PGTYPESdate_dayofweek(dDate);
791  timestamp2tm(*ts, NULL, &tm, &fsec, NULL);
792 
793  return dttofmtasc_replace(ts, dDate, dow, &tm, output, &str_len, fmtstr);
794 }
date PGTYPESdate_from_timestamp(timestamp dt)
Definition: datetime.c:31
int PGTYPESdate_dayofweek(date dDate)
Definition: datetime.c:138
long date
Definition: pgtypes_date.h:9

References dttofmtasc_replace(), fmtstr(), output, PGTYPESdate_dayofweek(), PGTYPESdate_from_timestamp(), timestamp2tm(), and tm.

Referenced by dttofmtasc(), and main().

◆ PGTYPEStimestamp_from_asc()

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

Definition at line 206 of file timestamp.c.

207 {
208  timestamp result;
209  int64 noresult = 0;
210  fsec_t fsec;
211  struct tm tt,
212  *tm = &tt;
213  int dtype;
214  int nf;
215  char *field[MAXDATEFIELDS];
216  int ftype[MAXDATEFIELDS];
217  char lowstr[MAXDATELEN + MAXDATEFIELDS];
218  char *realptr;
219  char **ptr = (endptr != NULL) ? endptr : &realptr;
220 
221  if (strlen(str) > MAXDATELEN)
222  {
223  errno = PGTYPES_TS_BAD_TIMESTAMP;
224  return noresult;
225  }
226 
227  if (ParseDateTime(str, lowstr, field, ftype, &nf, ptr) != 0 ||
228  DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, 0) != 0)
229  {
230  errno = PGTYPES_TS_BAD_TIMESTAMP;
231  return noresult;
232  }
233 
234  switch (dtype)
235  {
236  case DTK_DATE:
237  if (tm2timestamp(tm, fsec, NULL, &result) != 0)
238  {
239  errno = PGTYPES_TS_BAD_TIMESTAMP;
240  return noresult;
241  }
242  break;
243 
244  case DTK_EPOCH:
245  result = SetEpochTimestamp();
246  break;
247 
248  case DTK_LATE:
249  TIMESTAMP_NOEND(result);
250  break;
251 
252  case DTK_EARLY:
253  TIMESTAMP_NOBEGIN(result);
254  break;
255 
256  default:
257  errno = PGTYPES_TS_BAD_TIMESTAMP;
258  return noresult;
259  }
260 
261  /* AdjustTimestampForTypmod(&result, typmod); */
262 
263  /*
264  * Since it's difficult to test for noresult, make sure errno is 0 if no
265  * error occurred.
266  */
267  errno = 0;
268  return result;
269 }
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:754
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:978
#define TIMESTAMP_NOBEGIN(j)
Definition: timestamp.h:159
#define TIMESTAMP_NOEND(j)
Definition: timestamp.h:164
#define MAXDATEFIELDS
Definition: datetime.h:202
#define DTK_EPOCH
Definition: datetime.h:152
#define DTK_LATE
Definition: datetime.h:151
#define DTK_DATE
Definition: datetime.h:144
#define DTK_EARLY
Definition: datetime.h:150
#define MAXDATELEN
Definition: datetime.h:200
#define PGTYPES_TS_BAD_TIMESTAMP
Definition: pgtypes_error.h:15
int64 timestamp

References DecodeDateTime(), DTK_DATE, DTK_EARLY, DTK_EPOCH, DTK_LATE, MAXDATEFIELDS, MAXDATELEN, ParseDateTime(), PGTYPES_TS_BAD_TIMESTAMP, SetEpochTimestamp(), str, TIMESTAMP_NOBEGIN, TIMESTAMP_NOEND, tm, and tm2timestamp().

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

◆ PGTYPEStimestamp_sub()

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

Definition at line 797 of file timestamp.c.

798 {
799  if (TIMESTAMP_NOT_FINITE(*ts1) || TIMESTAMP_NOT_FINITE(*ts2))
801  else
802  iv->time = (*ts1 - *ts2);
803 
804  iv->month = 0;
805 
806  return 0;
807 }
#define PGTYPES_TS_ERR_EINFTIME
Definition: pgtypes_error.h:16

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

Referenced by dtsub().

◆ PGTYPEStimestamp_sub_interval()

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

Definition at line 917 of file timestamp.c.

918 {
919  interval tspan;
920 
921  tspan.month = -span->month;
922  tspan.time = -span->time;
923 
924  return PGTYPEStimestamp_add_interval(tin, &tspan, tout);
925 }
int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout)
Definition: timestamp.c:862

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

◆ PGTYPEStimestamp_to_asc()

char* PGTYPEStimestamp_to_asc ( timestamp  tstamp)

Definition at line 272 of file timestamp.c.

273 {
274  struct tm tt,
275  *tm = &tt;
276  char buf[MAXDATELEN + 1];
277  fsec_t fsec;
278  int DateStyle = 1; /* this defaults to USE_ISO_DATES, shall we
279  * make it an option? */
280 
281  if (TIMESTAMP_NOT_FINITE(tstamp))
282  EncodeSpecialTimestamp(tstamp, buf);
283  else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0)
284  EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf, 0);
285  else
286  {
287  errno = PGTYPES_TS_BAD_TIMESTAMP;
288  return NULL;
289  }
290  return pgtypes_strdup(buf);
291 }
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4331
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1596
int DateStyle
Definition: globals.c:122
static char * buf
Definition: pg_test_fsync.c:73

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

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

◆ SetEpochTimestamp()

static timestamp SetEpochTimestamp ( void  )
static

Definition at line 71 of file timestamp.c.

72 {
73  int64 noresult = 0;
74  timestamp dt;
75  struct tm tt,
76  *tm = &tt;
77 
78  if (GetEpochTime(tm) < 0)
79  return noresult;
80 
81  tm2timestamp(tm, 0, NULL, &dt);
82  return dt;
83 } /* SetEpochTimestamp() */
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2168

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

◆ time2t()

static int64 time2t ( const int  hour,
const int  min,
const int  sec,
const fsec_t  fsec 
)
static

Definition at line 20 of file timestamp.c.

21 {
22  return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
23 } /* time2t() */
#define MINS_PER_HOUR
Definition: timestamp.h:129
#define SECS_PER_MINUTE
Definition: timestamp.h:128

References MINS_PER_HOUR, SECS_PER_MINUTE, and USECS_PER_SEC.

Referenced by tm2timestamp().

◆ timestamp2tm()

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

Definition at line 97 of file timestamp.c.

98 {
99  int64 dDate,
100  date0;
101  int64 time;
102 #if defined(HAVE_STRUCT_TM_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
103  time_t utime;
104  struct tm *tx;
105 #endif
106 
107  date0 = date2j(2000, 1, 1);
108 
109  time = dt;
110  TMODULO(time, dDate, USECS_PER_DAY);
111 
112  if (time < INT64CONST(0))
113  {
114  time += USECS_PER_DAY;
115  dDate -= 1;
116  }
117 
118  /* add offset to go from J2000 back to standard Julian date */
119  dDate += date0;
120 
121  /* Julian day routine does not work for negative Julian days */
122  if (dDate < 0 || dDate > (timestamp) INT_MAX)
123  return -1;
124 
125  j2date((int) dDate, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
126  dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
127 
128  if (tzp != NULL)
129  {
130  /*
131  * Does this fall within the capabilities of the localtime()
132  * interface? Then use this to rotate to the local time zone.
133  */
135  {
136 #if defined(HAVE_STRUCT_TM_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
137 
138  utime = dt / USECS_PER_SEC +
139  ((date0 - date2j(1970, 1, 1)) * INT64CONST(86400));
140 
141  tx = localtime(&utime);
142  tm->tm_year = tx->tm_year + 1900;
143  tm->tm_mon = tx->tm_mon + 1;
144  tm->tm_mday = tx->tm_mday;
145  tm->tm_hour = tx->tm_hour;
146  tm->tm_min = tx->tm_min;
147  tm->tm_isdst = tx->tm_isdst;
148 
149 #if defined(HAVE_STRUCT_TM_TM_ZONE)
150  tm->tm_gmtoff = tx->tm_gmtoff;
151  tm->tm_zone = tx->tm_zone;
152 
153  *tzp = -tm->tm_gmtoff; /* tm_gmtoff is Sun/DEC-ism */
154  if (tzn != NULL)
155  *tzn = tm->tm_zone;
156 #elif defined(HAVE_INT_TIMEZONE)
158  if (tzn != NULL)
159  *tzn = TZNAME_GLOBAL[(tm->tm_isdst > 0)];
160 #endif
161 #else /* not (HAVE_STRUCT_TM_TM_ZONE ||
162  * HAVE_INT_TIMEZONE) */
163  *tzp = 0;
164  /* Mark this as *no* time zone available */
165  tm->tm_isdst = -1;
166  if (tzn != NULL)
167  *tzn = NULL;
168 #endif
169  }
170  else
171  {
172  *tzp = 0;
173  /* Mark this as *no* time zone available */
174  tm->tm_isdst = -1;
175  if (tzn != NULL)
176  *tzn = NULL;
177  }
178  }
179  else
180  {
181  tm->tm_isdst = -1;
182  if (tzn != NULL)
183  *tzn = NULL;
184  }
185 
186  tm->tm_yday = dDate - date2j(tm->tm_year, 1, 1) + 1;
187 
188  return 0;
189 } /* timestamp2tm() */
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:311
int date2j(int year, int month, int day)
Definition: datetime.c:286
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1874
#define SECS_PER_HOUR
Definition: timestamp.h:127
#define USECS_PER_DAY
Definition: timestamp.h:131
#define IS_VALID_UTIME(y, m, d)
Definition: dt.h:298
#define TMODULO(t, q, u)
Definition: datetime.h:248
#define TIMEZONE_GLOBAL
Definition: port.h:268
#define TZNAME_GLOBAL
Definition: port.h:269
const char * tm_zone
Definition: pgtime.h:46
int tm_isdst
Definition: pgtime.h:44
long int tm_gmtoff
Definition: pgtime.h:45

References date2j(), dt2time(), IS_VALID_UTIME, j2date(), SECS_PER_HOUR, TIMEZONE_GLOBAL, tm, 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_yday, pg_tm::tm_year, pg_tm::tm_zone, TMODULO, TZNAME_GLOBAL, USECS_PER_DAY, and USECS_PER_SEC.

◆ tm2timestamp()

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

Definition at line 40 of file timestamp.c.

41 {
42  int dDate;
43  int64 time;
44 
45  /* Prevent overflow in Julian-day routines */
47  return -1;
48 
49  dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
50  time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
51  *result = (dDate * USECS_PER_DAY) + time;
52  /* check for major overflow */
53  if ((*result - time) / USECS_PER_DAY != dDate)
54  return -1;
55  /* check for just-barely overflow (okay except time-of-day wraps) */
56  /* caution: we want to allow 1999-12-31 24:00:00 */
57  if ((*result < 0 && dDate > 0) ||
58  (*result > 0 && dDate < -1))
59  return -1;
60  if (tzp != NULL)
61  *result = dt2local(*result, -(*tzp));
62 
63  /* final range check catches just-out-of-range timestamps */
64  if (!IS_VALID_TIMESTAMP(*result))
65  return -1;
66 
67  return 0;
68 } /* tm2timestamp() */
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:227
#define IS_VALID_TIMESTAMP(t)
Definition: timestamp.h:267
static timestamp dt2local(timestamp dt, int tz)
Definition: timestamp.c:26
static int64 time2t(const int hour, const int min, const int sec, const fsec_t fsec)
Definition: timestamp.c:20

References date2j(), dt2local(), IS_VALID_JULIAN, IS_VALID_TIMESTAMP, time2t(), 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, and USECS_PER_DAY.