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.

References USECS_PER_SEC.

Referenced by tm2timestamp().

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

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

References un_fmt_comb::char_val, days, 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, and un_fmt_comb::uint_val.

Referenced by PGTYPEStimestamp_fmt_asc().

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

◆ EncodeSpecialTimestamp()

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

Definition at line 194 of file timestamp.c.

References EARLY, LATE, TIMESTAMP_IS_NOBEGIN, and TIMESTAMP_IS_NOEND.

195 {
196  if (TIMESTAMP_IS_NOBEGIN(dt))
197  strcpy(str, EARLY);
198  else if (TIMESTAMP_IS_NOEND(dt))
199  strcpy(str, LATE);
200  else
201  abort(); /* shouldn't happen */
202 }
#define LATE
Definition: datetime.h:41
#define TIMESTAMP_IS_NOEND(j)
Definition: timestamp.h:120
#define TIMESTAMP_IS_NOBEGIN(j)
Definition: timestamp.h:115
#define EARLY
Definition: datetime.h:40

◆ PGTYPEStimestamp_add_interval()

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

Definition at line 861 of file timestamp.c.

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

Referenced by main(), and PGTYPEStimestamp_sub_interval().

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

◆ PGTYPEStimestamp_current()

void PGTYPEStimestamp_current ( timestamp ts)

Definition at line 293 of file timestamp.c.

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

Referenced by dtcurrent(), and main().

294 {
295  struct tm tm;
296 
298  if (errno == 0)
299  tm2timestamp(&tm, 0, NULL, ts);
300 }
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:345
static struct pg_tm tm
Definition: localtime.c:108
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1887

◆ PGTYPEStimestamp_defmt_asc()

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

Definition at line 809 of file timestamp.c.

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

Referenced by dtcvfmtasc(), and main().

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

◆ PGTYPEStimestamp_fmt_asc()

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

Definition at line 781 of file timestamp.c.

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

Referenced by dttofmtasc(), and main().

782 {
783  struct tm tm;
784  fsec_t fsec;
785  date dDate;
786  int dow;
787 
788  dDate = PGTYPESdate_from_timestamp(*ts);
789  dow = PGTYPESdate_dayofweek(dDate);
790  timestamp2tm(*ts, NULL, &tm, &fsec, NULL);
791 
792  return dttofmtasc_replace(ts, dDate, dow, &tm, output, &str_len, fmtstr);
793 }
static int dttofmtasc_replace(timestamp *ts, date dDate, int dow, struct tm *tm, char *output, int *pstr_len, const char *fmtstr)
Definition: timestamp.c:303
static void output(uint64 loop_count)
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1791
long date
Definition: pgtypes_date.h:9
static struct pg_tm tm
Definition: localtime.c:108
int PGTYPESdate_dayofweek(date)
Definition: datetime.c:138
int32 fsec_t
Definition: timestamp.h:41
static void fmtstr(const char *value, int leftjust, int minlen, int maxwidth, int pointflag, PrintfTarget *target)
Definition: snprintf.c:969
date PGTYPESdate_from_timestamp(timestamp)
Definition: datetime.c:31

◆ PGTYPEStimestamp_from_asc()

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

Definition at line 205 of file timestamp.c.

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

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

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

◆ PGTYPEStimestamp_sub()

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

Definition at line 796 of file timestamp.c.

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

Referenced by dtsub().

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

◆ PGTYPEStimestamp_sub_interval()

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

Definition at line 920 of file timestamp.c.

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

921 {
922  interval tspan;
923 
924  tspan.month = -span->month;
925  tspan.time = -span->time;
926 
927 
928  return PGTYPEStimestamp_add_interval(tin, &tspan, tout);
929 }
int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout)
Definition: timestamp.c:861

◆ PGTYPEStimestamp_to_asc()

char* PGTYPEStimestamp_to_asc ( timestamp  tstamp)

Definition at line 271 of file timestamp.c.

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

272 {
273  struct tm tt,
274  *tm = &tt;
275  char buf[MAXDATELEN + 1];
276  fsec_t fsec;
277  int DateStyle = 1; /* this defaults to USE_ISO_DATES, shall we
278  * make it an option? */
279 
280  if (TIMESTAMP_NOT_FINITE(tstamp))
281  EncodeSpecialTimestamp(tstamp, buf);
282  else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0)
283  EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf, 0);
284  else
285  {
286  errno = PGTYPES_TS_BAD_TIMESTAMP;
287  return NULL;
288  }
289  return pgtypes_strdup(buf);
290 }
#define MAXDATELEN
Definition: datetime.h:201
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1791
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1536
static struct pg_tm tm
Definition: localtime.c:108
char * pgtypes_strdup(const char *str)
Definition: common.c:20
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:122
static char * buf
Definition: pg_test_fsync.c:67
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:3970
int32 fsec_t
Definition: timestamp.h:41
int DateStyle
Definition: globals.c:115
#define PGTYPES_TS_BAD_TIMESTAMP
Definition: pgtypes_error.h:15

◆ SetEpochTimestamp()

static timestamp SetEpochTimestamp ( void  )
static

Definition at line 71 of file timestamp.c.

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

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() */
int64 timestamp
static struct pg_tm tm
Definition: localtime.c:108
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1887
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2017

◆ 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.

References MINS_PER_HOUR, SECS_PER_MINUTE, and USECS_PER_SEC.

Referenced by tm2timestamp().

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

◆ 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.

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

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 || HAVE_INT_TIMEZONE) */
162  *tzp = 0;
163  /* Mark this as *no* time zone available */
164  tm->tm_isdst = -1;
165  if (tzn != NULL)
166  *tzn = NULL;
167 #endif
168  }
169  else
170  {
171  *tzp = 0;
172  /* Mark this as *no* time zone available */
173  tm->tm_isdst = -1;
174  if (tzn != NULL)
175  *tzn = NULL;
176  }
177  }
178  else
179  {
180  tm->tm_isdst = -1;
181  if (tzn != NULL)
182  *tzn = NULL;
183  }
184 
185  tm->tm_yday = dDate - date2j(tm->tm_year, 1, 1) + 1;
186 
187  return 0;
188 } /* timestamp2tm() */
int tm_isdst
Definition: pgtime.h:35
#define USECS_PER_SEC
Definition: timestamp.h:94
int64 timestamp
int tm_hour
Definition: pgtime.h:29
#define TZNAME_GLOBAL
Definition: port.h:227
#define TIMEZONE_GLOBAL
Definition: port.h:226
long int tm_gmtoff
Definition: pgtime.h:36
static struct pg_tm tm
Definition: localtime.c:108
int tm_mday
Definition: pgtime.h:30
#define IS_VALID_UTIME(y, m, d)
Definition: dt.h:298
int tm_mon
Definition: pgtime.h:31
#define USECS_PER_DAY
Definition: timestamp.h:91
const char * tm_zone
Definition: pgtime.h:37
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:294
#define SECS_PER_HOUR
Definition: timestamp.h:87
int date2j(int y, int m, int d)
Definition: datetime.c:269
void dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
Definition: timestamp.c:1764
int tm_year
Definition: pgtime.h:32
int tm_yday
Definition: pgtime.h:34
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28
#define TMODULO(t, q, u)
Definition: datetime.h:249

◆ tm2timestamp()

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

Definition at line 40 of file timestamp.c.

References date2j(), dt2local(), IS_VALID_JULIAN, IS_VALID_TIMESTAMP, time2t(), and USECS_PER_DAY.

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() */
static int64 time2t(const int hour, const int min, const int sec, const fsec_t fsec)
Definition: timestamp.c:20
int tm_hour
Definition: pgtime.h:29
static timestamp dt2local(timestamp dt, int tz)
Definition: timestamp.c:26
static struct pg_tm tm
Definition: localtime.c:108
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:155
#define USECS_PER_DAY
Definition: timestamp.h:91
int date2j(int y, int m, int d)
Definition: datetime.c:269
#define IS_VALID_TIMESTAMP(t)
Definition: timestamp.h:195
int tm_year
Definition: pgtime.h:32
int tm_sec
Definition: pgtime.h:27
int tm_min
Definition: pgtime.h:28