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

Go to the source code of this file.

Functions

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

References USECS_PER_SEC.

Referenced by tm2timestamp().

29 {
30  dt -= (tz * USECS_PER_SEC);
31  return dt;
32 } /* 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 310 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().

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

◆ EncodeSpecialTimestamp()

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

Definition at line 196 of file timestamp.c.

References EARLY, LATE, TIMESTAMP_IS_NOBEGIN, and TIMESTAMP_IS_NOEND.

197 {
198  if (TIMESTAMP_IS_NOBEGIN(dt))
199  strcpy(str, EARLY);
200  else if (TIMESTAMP_IS_NOEND(dt))
201  strcpy(str, LATE);
202  else
203  abort(); /* shouldn't happen */
204 }
#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 868 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().

869 {
870  if (TIMESTAMP_NOT_FINITE(*tin))
871  *tout = *tin;
872 
873 
874  else
875  {
876  if (span->month != 0)
877  {
878  struct tm tt,
879  *tm = &tt;
880  fsec_t fsec;
881 
882 
883  if (timestamp2tm(*tin, NULL, tm, &fsec, NULL) != 0)
884  return -1;
885  tm->tm_mon += span->month;
886  if (tm->tm_mon > MONTHS_PER_YEAR)
887  {
888  tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
889  tm->tm_mon = (tm->tm_mon - 1) % MONTHS_PER_YEAR + 1;
890  }
891  else if (tm->tm_mon < 1)
892  {
893  tm->tm_year += tm->tm_mon / MONTHS_PER_YEAR - 1;
894  tm->tm_mon = tm->tm_mon % MONTHS_PER_YEAR + MONTHS_PER_YEAR;
895  }
896 
897 
898  /* adjust for end of month boundary problems... */
899  if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
900  tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
901 
902 
903  if (tm2timestamp(tm, fsec, NULL, tin) != 0)
904  return -1;
905  }
906 
907 
908  *tin += span->time;
909  *tout = *tin;
910  }
911  return 0;
912 
913 }
#define isleap(y)
Definition: datetime.h:273
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1758
static struct pg_tm tm
Definition: localtime.c:106
#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:61
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1854

◆ PGTYPEStimestamp_current()

void PGTYPEStimestamp_current ( timestamp ts)

Definition at line 299 of file timestamp.c.

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

Referenced by dtcurrent(), and main().

300 {
301  struct tm tm;
302 
304  if (errno == 0)
305  tm2timestamp(&tm, 0, NULL, ts);
306  return;
307 }
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:354
static struct pg_tm tm
Definition: localtime.c:106
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1854

◆ PGTYPEStimestamp_defmt_asc()

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

Definition at line 816 of file timestamp.c.

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

Referenced by dtcvfmtasc(), and main().

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

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

Referenced by dttofmtasc(), and main().

789 {
790  struct tm tm;
791  fsec_t fsec;
792  date dDate;
793  int dow;
794 
795  dDate = PGTYPESdate_from_timestamp(*ts);
796  dow = PGTYPESdate_dayofweek(dDate);
797  timestamp2tm(*ts, NULL, &tm, &fsec, NULL);
798 
799  return dttofmtasc_replace(ts, dDate, dow, &tm, output, &str_len, fmtstr);
800 }
static int dttofmtasc_replace(timestamp *ts, date dDate, int dow, struct tm *tm, char *output, int *pstr_len, const char *fmtstr)
Definition: timestamp.c:310
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:1758
long date
Definition: pgtypes_date.h:8
static struct pg_tm tm
Definition: localtime.c:106
int PGTYPESdate_dayofweek(date)
Definition: datetime.c:139
int32 fsec_t
Definition: timestamp.h:41
static void fmtstr(char *value, int leftjust, int minlen, int maxwidth, int pointflag, PrintfTarget *target)
Definition: snprintf.c:796
date PGTYPESdate_from_timestamp(timestamp)
Definition: datetime.c:32

◆ PGTYPEStimestamp_from_asc()

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

Definition at line 207 of file timestamp.c.

References DecodeDateTime(), DTK_DATE, DTK_EARLY, DTK_EPOCH, DTK_INVALID, 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().

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

◆ PGTYPEStimestamp_sub()

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

Definition at line 803 of file timestamp.c.

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

Referenced by dtsub().

804 {
805  if (TIMESTAMP_NOT_FINITE(*ts1) || TIMESTAMP_NOT_FINITE(*ts2))
807  else
808  iv->time = (*ts1 - *ts2);
809 
810  iv->month = 0;
811 
812  return 0;
813 }
#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 927 of file timestamp.c.

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

928 {
929  interval tspan;
930 
931  tspan.month = -span->month;
932  tspan.time = -span->time;
933 
934 
935  return PGTYPEStimestamp_add_interval(tin, &tspan, tout);
936 }
int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout)
Definition: timestamp.c:868

◆ PGTYPEStimestamp_to_asc()

char* PGTYPEStimestamp_to_asc ( timestamp  tstamp)

Definition at line 277 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().

278 {
279  struct tm tt,
280  *tm = &tt;
281  char buf[MAXDATELEN + 1];
282  fsec_t fsec;
283  int DateStyle = 1; /* this defaults to ISO_DATES, shall we make
284  * it an option? */
285 
286  if (TIMESTAMP_NOT_FINITE(tstamp))
287  EncodeSpecialTimestamp(tstamp, buf);
288  else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0)
289  EncodeDateTime(tm, fsec, false, 0, NULL, DateStyle, buf, 0);
290  else
291  {
292  errno = PGTYPES_TS_BAD_TIMESTAMP;
293  return NULL;
294  }
295  return pgtypes_strdup(buf);
296 }
#define MAXDATELEN
Definition: datetime.h:203
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1758
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1523
static struct pg_tm tm
Definition: localtime.c:106
char * pgtypes_strdup(const char *str)
Definition: common.c:19
#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:3988
int32 fsec_t
Definition: timestamp.h:41
int DateStyle
Definition: globals.c:114
#define PGTYPES_TS_BAD_TIMESTAMP
Definition: pgtypes_error.h:15

◆ SetEpochTimestamp()

static timestamp SetEpochTimestamp ( void  )
static

Definition at line 73 of file timestamp.c.

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

74 {
75  int64 noresult = 0;
76  timestamp dt;
77  struct tm tt,
78  *tm = &tt;
79 
80  if (GetEpochTime(tm) < 0)
81  return noresult;
82 
83  tm2timestamp(tm, 0, NULL, &dt);
84  return dt;
85 } /* SetEpochTimestamp() */
int64 timestamp
static struct pg_tm tm
Definition: localtime.c:106
int tm2timestamp(struct pg_tm *tm, fsec_t fsec, int *tzp, Timestamp *result)
Definition: timestamp.c:1854
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:1984

◆ time2t()

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

Definition at line 22 of file timestamp.c.

References MINS_PER_HOUR, SECS_PER_MINUTE, and USECS_PER_SEC.

Referenced by tm2timestamp().

23 {
24  return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
25 } /* 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 99 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.

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

◆ tm2timestamp()

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

Definition at line 42 of file timestamp.c.

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

43 {
44  int dDate;
45  int64 time;
46 
47  /* Prevent overflow in Julian-day routines */
49  return -1;
50 
51  dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
52  time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
53  *result = (dDate * USECS_PER_DAY) + time;
54  /* check for major overflow */
55  if ((*result - time) / USECS_PER_DAY != dDate)
56  return -1;
57  /* check for just-barely overflow (okay except time-of-day wraps) */
58  /* caution: we want to allow 1999-12-31 24:00:00 */
59  if ((*result < 0 && dDate > 0) ||
60  (*result > 0 && dDate < -1))
61  return -1;
62  if (tzp != NULL)
63  *result = dt2local(*result, -(*tzp));
64 
65  /* final range check catches just-out-of-range timestamps */
66  if (!IS_VALID_TIMESTAMP(*result))
67  return -1;
68 
69  return 0;
70 } /* tm2timestamp() */
static int64 time2t(const int hour, const int min, const int sec, const fsec_t fsec)
Definition: timestamp.c:22
int tm_hour
Definition: pgtime.h:29
static timestamp dt2local(timestamp dt, int tz)
Definition: timestamp.c:28
static struct pg_tm tm
Definition: localtime.c:106
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:276
#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