PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
timestamp.c File Reference
#include "postgres_fe.h"
#include <time.h>
#include <limits.h>
#include <math.h>
#include "common/int.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 27 of file timestamp.c.

28{
29 dt -= (tz * USECS_PER_SEC);
30 return dt;
31} /* 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 300 of file timestamp.c.

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

◆ EncodeSpecialTimestamp()

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

Definition at line 191 of file timestamp.c.

192{
193 if (TIMESTAMP_IS_NOBEGIN(dt))
194 strcpy(str, EARLY);
195 else if (TIMESTAMP_IS_NOEND(dt))
196 strcpy(str, LATE);
197 else
198 abort(); /* shouldn't happen */
199}
#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 858 of file timestamp.c.

859{
860 if (TIMESTAMP_NOT_FINITE(*tin))
861 *tout = *tin;
862 else
863 {
864 if (span->month != 0)
865 {
866 struct tm tt,
867 *tm = &tt;
868 fsec_t fsec;
869
870 if (timestamp2tm(*tin, NULL, tm, &fsec, NULL) != 0)
871 return -1;
872 tm->tm_mon += span->month;
874 {
875 tm->tm_year += (tm->tm_mon - 1) / MONTHS_PER_YEAR;
876 tm->tm_mon = (tm->tm_mon - 1) % MONTHS_PER_YEAR + 1;
877 }
878 else if (tm->tm_mon < 1)
879 {
882 }
883
884
885 /* adjust for end of month boundary problems... */
886 if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
887 tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
888
889
890 if (tm2timestamp(tm, fsec, NULL, tin) != 0)
891 return -1;
892 }
893
894 *tin += span->time;
895 *tout = *tin;
896 }
897
898 return 0;
899}
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:1987
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1891
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 290 of file timestamp.c.

291{
292 struct tm tm;
293
295 if (errno == 0)
296 tm2timestamp(&tm, 0, NULL, ts);
297}
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:376

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

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

779{
780 struct tm tm;
781 fsec_t fsec;
782 date dDate;
783 int dow;
784
785 dDate = PGTYPESdate_from_timestamp(*ts);
786 dow = PGTYPESdate_dayofweek(dDate);
787 timestamp2tm(*ts, NULL, &tm, &fsec, NULL);
788
789 return dttofmtasc_replace(ts, dDate, dow, &tm, output, &str_len, fmtstr);
790}
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 202 of file timestamp.c.

203{
204 timestamp result;
205 int64 noresult = 0;
206 fsec_t fsec;
207 struct tm tt,
208 *tm = &tt;
209 int dtype;
210 int nf;
211 char *field[MAXDATEFIELDS];
212 int ftype[MAXDATEFIELDS];
213 char lowstr[MAXDATELEN + MAXDATEFIELDS];
214 char *realptr;
215 char **ptr = (endptr != NULL) ? endptr : &realptr;
216
217 if (strlen(str) > MAXDATELEN)
218 {
220 return noresult;
221 }
222
223 if (ParseDateTime(str, lowstr, field, ftype, &nf, ptr) != 0 ||
224 DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, 0) != 0)
225 {
227 return noresult;
228 }
229
230 switch (dtype)
231 {
232 case DTK_DATE:
233 if (tm2timestamp(tm, fsec, NULL, &result) != 0)
234 {
236 return noresult;
237 }
238 break;
239
240 case DTK_EPOCH:
241 result = SetEpochTimestamp();
242 break;
243
244 case DTK_LATE:
245 TIMESTAMP_NOEND(result);
246 break;
247
248 case DTK_EARLY:
249 TIMESTAMP_NOBEGIN(result);
250 break;
251
252 default:
254 return noresult;
255 }
256
257 /* AdjustTimestampForTypmod(&result, typmod); */
258
259 /*
260 * Since it's difficult to test for noresult, make sure errno is 0 if no
261 * error occurred.
262 */
263 errno = 0;
264 return result;
265}
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:764
int DecodeDateTime(char **field, int *ftype, int nf, int *dtype, struct pg_tm *tm, fsec_t *fsec, int *tzp, DateTimeErrorExtra *extra)
Definition: datetime.c:988
int64_t int64
Definition: c.h:485
#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 793 of file timestamp.c.

794{
797 else
798 iv->time = (*ts1 - *ts2);
799
800 iv->month = 0;
801
802 return 0;
803}
#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 913 of file timestamp.c.

914{
915 interval tspan;
916
917 tspan.month = -span->month;
918 tspan.time = -span->time;
919
920 return PGTYPEStimestamp_add_interval(tin, &tspan, tout);
921}
int PGTYPEStimestamp_add_interval(timestamp *tin, interval *span, timestamp *tout)
Definition: timestamp.c:858

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

◆ PGTYPEStimestamp_to_asc()

char * PGTYPEStimestamp_to_asc ( timestamp  tstamp)

Definition at line 268 of file timestamp.c.

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

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

67{
68 int64 noresult = 0;
69 timestamp dt;
70 struct tm tt,
71 *tm = &tt;
72
73 if (GetEpochTime(tm) < 0)
74 return noresult;
75
76 tm2timestamp(tm, 0, NULL, &dt);
77 return dt;
78} /* SetEpochTimestamp() */
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2149

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

22{
23 return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;
24} /* 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 92 of file timestamp.c.

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

42{
43 int dDate;
44 int64 time;
45
46 /* Prevent overflow in Julian-day routines */
48 return -1;
49
50 dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
51 time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
52 if (unlikely(pg_mul_s64_overflow(dDate, USECS_PER_DAY, result) ||
53 pg_add_s64_overflow(*result, time, result)))
54 return -1;
55 if (tzp != NULL)
56 *result = dt2local(*result, -(*tzp));
57
58 /* final range check catches just-out-of-range timestamps */
59 if (!IS_VALID_TIMESTAMP(*result))
60 return -1;
61
62 return 0;
63} /* tm2timestamp() */
#define unlikely(x)
Definition: c.h:333
#define IS_VALID_JULIAN(y, m, d)
Definition: timestamp.h:227
#define IS_VALID_TIMESTAMP(t)
Definition: timestamp.h:267
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:293
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
Definition: int.h:235
static timestamp dt2local(timestamp dt, int tz)
Definition: timestamp.c:27
static int64 time2t(const int hour, const int min, const int sec, const fsec_t fsec)
Definition: timestamp.c:21

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