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

Go to the source code of this file.

Macros

#define PGTYPES_DATE_NUM_MAX_DIGITS
 
#define PGTYPES_FMTDATE_DAY_DIGITS_LZ   1 /* LZ means "leading zeroes" */
 
#define PGTYPES_FMTDATE_DOW_LITERAL_SHORT   2
 
#define PGTYPES_FMTDATE_MONTH_DIGITS_LZ   3
 
#define PGTYPES_FMTDATE_MONTH_LITERAL_SHORT   4
 
#define PGTYPES_FMTDATE_YEAR_DIGITS_SHORT   5
 
#define PGTYPES_FMTDATE_YEAR_DIGITS_LONG   6
 
#define PGTYPES_DATE_MONTH_MAXLENGTH   20 /* probably even less :-) */
 

Functions

datePGTYPESdate_new (void)
 
void PGTYPESdate_free (date *d)
 
date PGTYPESdate_from_timestamp (timestamp dt)
 
date PGTYPESdate_from_asc (char *str, char **endptr)
 
char * PGTYPESdate_to_asc (date dDate)
 
void PGTYPESdate_julmdy (date jd, int *mdy)
 
void PGTYPESdate_mdyjul (int *mdy, date *jdate)
 
int PGTYPESdate_dayofweek (date dDate)
 
void PGTYPESdate_today (date *d)
 
int PGTYPESdate_fmt_asc (date dDate, const char *fmtstring, char *outbuf)
 
int PGTYPESdate_defmt_asc (date *d, const char *fmt, const char *str)
 

Macro Definition Documentation

◆ PGTYPES_DATE_MONTH_MAXLENGTH

#define PGTYPES_DATE_MONTH_MAXLENGTH   20 /* probably even less :-) */

Definition at line 328 of file datetime.c.

Referenced by PGTYPESdate_defmt_asc().

◆ PGTYPES_DATE_NUM_MAX_DIGITS

#define PGTYPES_DATE_NUM_MAX_DIGITS
Value:
20 /* should suffice for most
* years... */

Definition at line 157 of file datetime.c.

Referenced by PGTYPESdate_fmt_asc().

◆ PGTYPES_FMTDATE_DAY_DIGITS_LZ

#define PGTYPES_FMTDATE_DAY_DIGITS_LZ   1 /* LZ means "leading zeroes" */

Definition at line 160 of file datetime.c.

Referenced by PGTYPESdate_fmt_asc().

◆ PGTYPES_FMTDATE_DOW_LITERAL_SHORT

#define PGTYPES_FMTDATE_DOW_LITERAL_SHORT   2

Definition at line 161 of file datetime.c.

Referenced by PGTYPESdate_fmt_asc().

◆ PGTYPES_FMTDATE_MONTH_DIGITS_LZ

#define PGTYPES_FMTDATE_MONTH_DIGITS_LZ   3

Definition at line 162 of file datetime.c.

Referenced by PGTYPESdate_fmt_asc().

◆ PGTYPES_FMTDATE_MONTH_LITERAL_SHORT

#define PGTYPES_FMTDATE_MONTH_LITERAL_SHORT   4

Definition at line 163 of file datetime.c.

Referenced by PGTYPESdate_fmt_asc().

◆ PGTYPES_FMTDATE_YEAR_DIGITS_LONG

#define PGTYPES_FMTDATE_YEAR_DIGITS_LONG   6

Definition at line 165 of file datetime.c.

Referenced by PGTYPESdate_fmt_asc().

◆ PGTYPES_FMTDATE_YEAR_DIGITS_SHORT

#define PGTYPES_FMTDATE_YEAR_DIGITS_SHORT   5

Definition at line 164 of file datetime.c.

Referenced by PGTYPESdate_fmt_asc().

Function Documentation

◆ PGTYPESdate_dayofweek()

int PGTYPESdate_dayofweek ( date  dDate)

Definition at line 138 of file datetime.c.

References date2j().

Referenced by main(), PGTYPESdate_fmt_asc(), PGTYPEStimestamp_fmt_asc(), and rdayofweek().

139 {
140  /*
141  * Sunday: 0 Monday: 1 Tuesday: 2 Wednesday: 3 Thursday: 4
142  * Friday: 5 Saturday: 6
143  */
144  return (int) (dDate + date2j(2000, 1, 1) + 1) % 7;
145 }
int date2j(int y, int m, int d)
Definition: datetime.c:269

◆ PGTYPESdate_defmt_asc()

int PGTYPESdate_defmt_asc ( date d,
const char *  fmt,
const char *  str 
)

Definition at line 330 of file datetime.c.

References date2j(), free, i, sort-test::list, months, MONTHS_PER_YEAR, pg_tolower(), pgtypes_alloc(), PGTYPES_DATE_BAD_DAY, PGTYPES_DATE_BAD_MONTH, PGTYPES_DATE_ERR_EARGS, PGTYPES_DATE_ERR_ENOSHORTDATE, PGTYPES_DATE_ERR_ENOTDMY, PGTYPES_DATE_MONTH_MAXLENGTH, pgtypes_date_months, pgtypes_strdup(), tm, and pg_tm::tm_year.

Referenced by main(), and rdefmtdate().

331 {
332  /*
333  * token[2] = { 4,6 } means that token 2 starts at position 4 and ends at
334  * (including) position 6
335  */
336  int token[3][2];
337  int token_values[3] = {-1, -1, -1};
338  char *fmt_token_order;
339  char *fmt_ystart,
340  *fmt_mstart,
341  *fmt_dstart;
342  unsigned int i;
343  int reading_digit;
344  int token_count;
345  char *str_copy;
346  struct tm tm;
347 
348  tm.tm_year = tm.tm_mon = tm.tm_mday = 0; /* keep compiler quiet */
349 
350  if (!d || !str || !fmt)
351  {
352  errno = PGTYPES_DATE_ERR_EARGS;
353  return -1;
354  }
355 
356  /* analyze the fmt string */
357  fmt_ystart = strstr(fmt, "yy");
358  fmt_mstart = strstr(fmt, "mm");
359  fmt_dstart = strstr(fmt, "dd");
360 
361  if (!fmt_ystart || !fmt_mstart || !fmt_dstart)
362  {
363  errno = PGTYPES_DATE_ERR_EARGS;
364  return -1;
365  }
366 
367  if (fmt_ystart < fmt_mstart)
368  {
369  /* y m */
370  if (fmt_dstart < fmt_ystart)
371  {
372  /* d y m */
373  fmt_token_order = "dym";
374  }
375  else if (fmt_dstart > fmt_mstart)
376  {
377  /* y m d */
378  fmt_token_order = "ymd";
379  }
380  else
381  {
382  /* y d m */
383  fmt_token_order = "ydm";
384  }
385  }
386  else
387  {
388  /* fmt_ystart > fmt_mstart */
389  /* m y */
390  if (fmt_dstart < fmt_mstart)
391  {
392  /* d m y */
393  fmt_token_order = "dmy";
394  }
395  else if (fmt_dstart > fmt_ystart)
396  {
397  /* m y d */
398  fmt_token_order = "myd";
399  }
400  else
401  {
402  /* m d y */
403  fmt_token_order = "mdy";
404  }
405  }
406 
407  /*
408  * handle the special cases where there is no delimiter between the
409  * digits. If we see this:
410  *
411  * only digits, 6 or 8 bytes then it might be ddmmyy and ddmmyyyy (or
412  * similar)
413  *
414  * we reduce it to a string with delimiters and continue processing
415  */
416 
417  /* check if we have only digits */
418  reading_digit = 1;
419  for (i = 0; str[i]; i++)
420  {
421  if (!isdigit((unsigned char) str[i]))
422  {
423  reading_digit = 0;
424  break;
425  }
426  }
427  if (reading_digit)
428  {
429  int frag_length[3];
430  int target_pos;
431 
432  i = strlen(str);
433  if (i != 8 && i != 6)
434  {
436  return -1;
437  }
438  /* okay, this really is the special case */
439 
440  /*
441  * as long as the string, one additional byte for the terminator and 2
442  * for the delimiters between the 3 fields
443  */
444  str_copy = pgtypes_alloc(strlen(str) + 1 + 2);
445  if (!str_copy)
446  return -1;
447 
448  /* determine length of the fragments */
449  if (i == 6)
450  {
451  frag_length[0] = 2;
452  frag_length[1] = 2;
453  frag_length[2] = 2;
454  }
455  else
456  {
457  if (fmt_token_order[0] == 'y')
458  {
459  frag_length[0] = 4;
460  frag_length[1] = 2;
461  frag_length[2] = 2;
462  }
463  else if (fmt_token_order[1] == 'y')
464  {
465  frag_length[0] = 2;
466  frag_length[1] = 4;
467  frag_length[2] = 2;
468  }
469  else
470  {
471  frag_length[0] = 2;
472  frag_length[1] = 2;
473  frag_length[2] = 4;
474  }
475  }
476  target_pos = 0;
477 
478  /*
479  * XXX: Here we could calculate the positions of the tokens and save
480  * the for loop down there where we again check with isdigit() for
481  * digits.
482  */
483  for (i = 0; i < 3; i++)
484  {
485  int start_pos = 0;
486 
487  if (i >= 1)
488  start_pos += frag_length[0];
489  if (i == 2)
490  start_pos += frag_length[1];
491 
492  strncpy(str_copy + target_pos, str + start_pos,
493  frag_length[i]);
494  target_pos += frag_length[i];
495  if (i != 2)
496  {
497  str_copy[target_pos] = ' ';
498  target_pos++;
499  }
500  }
501  str_copy[target_pos] = '\0';
502  }
503  else
504  {
505  str_copy = pgtypes_strdup(str);
506  if (!str_copy)
507  return -1;
508 
509  /* convert the whole string to lower case */
510  for (i = 0; str_copy[i]; i++)
511  str_copy[i] = (char) pg_tolower((unsigned char) str_copy[i]);
512  }
513 
514  /* look for numerical tokens */
515  reading_digit = 0;
516  token_count = 0;
517  for (i = 0; i < strlen(str_copy); i++)
518  {
519  if (!isdigit((unsigned char) str_copy[i]) && reading_digit)
520  {
521  /* the token is finished */
522  token[token_count][1] = i - 1;
523  reading_digit = 0;
524  token_count++;
525  }
526  else if (isdigit((unsigned char) str_copy[i]) && !reading_digit)
527  {
528  /* we have found a token */
529  token[token_count][0] = i;
530  reading_digit = 1;
531  }
532  }
533 
534  /*
535  * we're at the end of the input string, but maybe we are still reading a
536  * number...
537  */
538  if (reading_digit)
539  {
540  token[token_count][1] = i - 1;
541  token_count++;
542  }
543 
544 
545  if (token_count < 2)
546  {
547  /*
548  * not all tokens found, no way to find 2 missing tokens with string
549  * matches
550  */
551  free(str_copy);
553  return -1;
554  }
555 
556  if (token_count != 3)
557  {
558  /*
559  * not all tokens found but we may find another one with string
560  * matches by testing for the months names and months abbreviations
561  */
562  char *month_lower_tmp = pgtypes_alloc(PGTYPES_DATE_MONTH_MAXLENGTH);
563  char *start_pos;
564  int j;
565  int offset;
566  int found = 0;
567  char **list;
568 
569  if (!month_lower_tmp)
570  {
571  /* free variables we alloc'ed before */
572  free(str_copy);
573  return -1;
574  }
575  list = pgtypes_date_months;
576  for (i = 0; list[i]; i++)
577  {
578  for (j = 0; j < PGTYPES_DATE_MONTH_MAXLENGTH; j++)
579  {
580  month_lower_tmp[j] = (char) pg_tolower((unsigned char) list[i][j]);
581  if (!month_lower_tmp[j])
582  {
583  /* properly terminated */
584  break;
585  }
586  }
587  if ((start_pos = strstr(str_copy, month_lower_tmp)))
588  {
589  offset = start_pos - str_copy;
590 
591  /*
592  * sort the new token into the numeric tokens, shift them if
593  * necessary
594  */
595  if (offset < token[0][0])
596  {
597  token[2][0] = token[1][0];
598  token[2][1] = token[1][1];
599  token[1][0] = token[0][0];
600  token[1][1] = token[0][1];
601  token_count = 0;
602  }
603  else if (offset < token[1][0])
604  {
605  token[2][0] = token[1][0];
606  token[2][1] = token[1][1];
607  token_count = 1;
608  }
609  else
610  token_count = 2;
611  token[token_count][0] = offset;
612  token[token_count][1] = offset + strlen(month_lower_tmp) - 1;
613 
614  /*
615  * the value is the index of the month in the array of months
616  * + 1 (January is month 0)
617  */
618  token_values[token_count] = i + 1;
619  found = 1;
620  break;
621  }
622 
623  /*
624  * evil[tm] hack: if we read the pgtypes_date_months and haven't
625  * found a match, reset list to point to months (abbreviations)
626  * and reset the counter variable i
627  */
628  if (list == pgtypes_date_months)
629  {
630  if (list[i + 1] == NULL)
631  {
632  list = months;
633  i = -1;
634  }
635  }
636  }
637  if (!found)
638  {
639  free(month_lower_tmp);
640  free(str_copy);
641  errno = PGTYPES_DATE_ERR_ENOTDMY;
642  return -1;
643  }
644 
645  /*
646  * here we found a month. token[token_count] and
647  * token_values[token_count] reflect the month's details.
648  *
649  * only the month can be specified with a literal. Here we can do a
650  * quick check if the month is at the right position according to the
651  * format string because we can check if the token that we expect to
652  * be the month is at the position of the only token that already has
653  * a value. If we wouldn't check here we could say "December 4 1990"
654  * with a fmt string of "dd mm yy" for 12 April 1990.
655  */
656  if (fmt_token_order[token_count] != 'm')
657  {
658  /* deal with the error later on */
659  token_values[token_count] = -1;
660  }
661  free(month_lower_tmp);
662  }
663 
664  /* terminate the tokens with ASCII-0 and get their values */
665  for (i = 0; i < 3; i++)
666  {
667  *(str_copy + token[i][1] + 1) = '\0';
668  /* A month already has a value set, check for token_value == -1 */
669  if (token_values[i] == -1)
670  {
671  errno = 0;
672  token_values[i] = strtol(str_copy + token[i][0], (char **) NULL, 10);
673  /* strtol sets errno in case of an error */
674  if (errno)
675  token_values[i] = -1;
676  }
677  if (fmt_token_order[i] == 'd')
678  tm.tm_mday = token_values[i];
679  else if (fmt_token_order[i] == 'm')
680  tm.tm_mon = token_values[i];
681  else if (fmt_token_order[i] == 'y')
682  tm.tm_year = token_values[i];
683  }
684  free(str_copy);
685 
686  if (tm.tm_mday < 1 || tm.tm_mday > 31)
687  {
688  errno = PGTYPES_DATE_BAD_DAY;
689  return -1;
690  }
691 
692  if (tm.tm_mon < 1 || tm.tm_mon > MONTHS_PER_YEAR)
693  {
694  errno = PGTYPES_DATE_BAD_MONTH;
695  return -1;
696  }
697 
698  if (tm.tm_mday == 31 && (tm.tm_mon == 4 || tm.tm_mon == 6 || tm.tm_mon == 9 || tm.tm_mon == 11))
699  {
700  errno = PGTYPES_DATE_BAD_DAY;
701  return -1;
702  }
703 
704  if (tm.tm_mon == 2 && tm.tm_mday > 29)
705  {
706  errno = PGTYPES_DATE_BAD_DAY;
707  return -1;
708  }
709 
710  *d = date2j(tm.tm_year, tm.tm_mon, tm.tm_mday) - date2j(2000, 1, 1);
711 
712  return 0;
713 }
#define PGTYPES_DATE_BAD_DAY
Definition: pgtypes_error.h:12
#define PGTYPES_DATE_ERR_EARGS
Definition: pgtypes_error.h:9
#define PGTYPES_DATE_ERR_ENOTDMY
Definition: pgtypes_error.h:11
unsigned char pg_tolower(unsigned char ch)
Definition: pgstrcasecmp.c:122
#define PGTYPES_DATE_BAD_MONTH
Definition: pgtypes_error.h:13
static struct pg_tm tm
Definition: localtime.c:108
#define MONTHS_PER_YEAR
Definition: timestamp.h:69
char * pgtypes_strdup(const char *str)
Definition: common.c:20
const char *const months[]
Definition: datetime.c:65
#define PGTYPES_DATE_ERR_ENOSHORTDATE
Definition: pgtypes_error.h:10
char * pgtypes_alloc(long size)
Definition: common.c:10
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define PGTYPES_DATE_MONTH_MAXLENGTH
Definition: datetime.c:328
int date2j(int y, int m, int d)
Definition: datetime.c:269
char * pgtypes_date_months[]
Definition: dt_common.c:499
#define free(a)
Definition: header.h:65
int tm_year
Definition: pgtime.h:32
int i

◆ PGTYPESdate_fmt_asc()

int PGTYPESdate_fmt_asc ( date  dDate,
const char *  fmtstring,
char *  outbuf 
)

Definition at line 168 of file datetime.c.

References date2j(), format, free, i, j2date(), months, pgtypes_alloc(), PGTYPES_DATE_NUM_MAX_DIGITS, pgtypes_date_weekdays_short, PGTYPES_FMTDATE_DAY_DIGITS_LZ, PGTYPES_FMTDATE_DOW_LITERAL_SHORT, PGTYPES_FMTDATE_MONTH_DIGITS_LZ, PGTYPES_FMTDATE_MONTH_LITERAL_SHORT, PGTYPES_FMTDATE_YEAR_DIGITS_LONG, PGTYPES_FMTDATE_YEAR_DIGITS_SHORT, PGTYPES_TYPE_STRING_CONSTANT, PGTYPES_TYPE_STRING_MALLOCED, PGTYPES_TYPE_UINT, PGTYPES_TYPE_UINT_2_LZ, PGTYPES_TYPE_UINT_4_LZ, PGTYPESdate_dayofweek(), snprintf, un_fmt_comb::str_val, tm, and un_fmt_comb::uint_val.

Referenced by main(), and rfmtdate().

169 {
170  static struct
171  {
172  char *format;
173  int component;
174  } mapping[] =
175  {
176  /*
177  * format items have to be sorted according to their length, since the
178  * first pattern that matches gets replaced by its value
179  */
180  {
182  },
183  {
185  },
186  {
188  },
189  {
191  },
192  {
194  },
195  {
197  },
198  {
199  NULL, 0
200  }
201  };
202 
203  union un_fmt_comb replace_val;
204  int replace_type;
205 
206  int i;
207  int dow;
208  char *start_pattern;
209  struct tm tm;
210 
211  /* copy the string over */
212  strcpy(outbuf, fmtstring);
213 
214  /* get the date */
215  j2date(dDate + date2j(2000, 1, 1), &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
216  dow = PGTYPESdate_dayofweek(dDate);
217 
218  for (i = 0; mapping[i].format != NULL; i++)
219  {
220  while ((start_pattern = strstr(outbuf, mapping[i].format)) != NULL)
221  {
222  switch (mapping[i].component)
223  {
225  replace_val.str_val = pgtypes_date_weekdays_short[dow];
226  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
227  break;
229  replace_val.uint_val = tm.tm_mday;
230  replace_type = PGTYPES_TYPE_UINT_2_LZ;
231  break;
233  replace_val.str_val = months[tm.tm_mon - 1];
234  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
235  break;
237  replace_val.uint_val = tm.tm_mon;
238  replace_type = PGTYPES_TYPE_UINT_2_LZ;
239  break;
241  replace_val.uint_val = tm.tm_year;
242  replace_type = PGTYPES_TYPE_UINT_4_LZ;
243  break;
245  replace_val.uint_val = tm.tm_year % 100;
246  replace_type = PGTYPES_TYPE_UINT_2_LZ;
247  break;
248  default:
249 
250  /*
251  * should not happen, set something anyway
252  */
253  replace_val.str_val = " ";
254  replace_type = PGTYPES_TYPE_STRING_CONSTANT;
255  }
256  switch (replace_type)
257  {
260  memcpy(start_pattern, replace_val.str_val,
261  strlen(replace_val.str_val));
262  if (replace_type == PGTYPES_TYPE_STRING_MALLOCED)
263  free(replace_val.str_val);
264  break;
265  case PGTYPES_TYPE_UINT:
266  {
268 
269  if (!t)
270  return -1;
272  "%u", replace_val.uint_val);
273  memcpy(start_pattern, t, strlen(t));
274  free(t);
275  }
276  break;
278  {
280 
281  if (!t)
282  return -1;
284  "%02u", replace_val.uint_val);
285  memcpy(start_pattern, t, strlen(t));
286  free(t);
287  }
288  break;
290  {
292 
293  if (!t)
294  return -1;
296  "%04u", replace_val.uint_val);
297  memcpy(start_pattern, t, strlen(t));
298  free(t);
299  }
300  break;
301  default:
302 
303  /*
304  * doesn't happen (we set replace_type to
305  * PGTYPES_TYPE_STRING_CONSTANT in case of an error above)
306  */
307  break;
308  }
309  }
310  }
311  return 0;
312 }
#define PGTYPES_TYPE_UINT_4_LZ
#define PGTYPES_FMTDATE_DAY_DIGITS_LZ
Definition: datetime.c:160
char * pgtypes_date_weekdays_short[]
Definition: dt_common.c:497
#define PGTYPES_TYPE_UINT_2_LZ
#define PGTYPES_TYPE_STRING_CONSTANT
#define PGTYPES_DATE_NUM_MAX_DIGITS
Definition: datetime.c:157
static struct pg_tm tm
Definition: localtime.c:108
const char *const months[]
Definition: datetime.c:65
#define PGTYPES_TYPE_UINT
char * pgtypes_alloc(long size)
Definition: common.c:10
int tm_mday
Definition: pgtime.h:30
int tm_mon
Definition: pgtime.h:31
#define PGTYPES_FMTDATE_YEAR_DIGITS_LONG
Definition: datetime.c:165
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:294
#define PGTYPES_TYPE_STRING_MALLOCED
#define PGTYPES_FMTDATE_YEAR_DIGITS_SHORT
Definition: datetime.c:164
int date2j(int y, int m, int d)
Definition: datetime.c:269
#define free(a)
Definition: header.h:65
#define PGTYPES_FMTDATE_MONTH_LITERAL_SHORT
Definition: datetime.c:163
int tm_year
Definition: pgtime.h:32
int i
int PGTYPESdate_dayofweek(date dDate)
Definition: datetime.c:138
#define PGTYPES_FMTDATE_DOW_LITERAL_SHORT
Definition: datetime.c:161
static char format
#define snprintf
Definition: port.h:192
#define PGTYPES_FMTDATE_MONTH_DIGITS_LZ
Definition: datetime.c:162

◆ PGTYPESdate_free()

void PGTYPESdate_free ( date d)

Definition at line 25 of file datetime.c.

References free.

Referenced by main().

26 {
27  free(d);
28 }
#define free(a)
Definition: header.h:65

◆ PGTYPESdate_from_asc()

date PGTYPESdate_from_asc ( char *  str,
char **  endptr 
)

Definition at line 47 of file datetime.c.

References date2j(), DecodeDateTime(), DTK_DATE, DTK_EPOCH, GetEpochTime(), MAXDATEFIELDS, MAXDATELEN, ParseDateTime(), PGTYPES_DATE_BAD_DATE, and tm.

Referenced by ecpg_get_data(), and main().

48 {
49  date dDate;
50  fsec_t fsec;
51  struct tm tt,
52  *tm = &tt;
53  int dtype;
54  int nf;
55  char *field[MAXDATEFIELDS];
56  int ftype[MAXDATEFIELDS];
57  char lowstr[MAXDATELEN + MAXDATEFIELDS];
58  char *realptr;
59  char **ptr = (endptr != NULL) ? endptr : &realptr;
60 
61  bool EuroDates = false;
62 
63  errno = 0;
64  if (strlen(str) > MAXDATELEN)
65  {
66  errno = PGTYPES_DATE_BAD_DATE;
67  return INT_MIN;
68  }
69 
70  if (ParseDateTime(str, lowstr, field, ftype, &nf, ptr) != 0 ||
71  DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, EuroDates) != 0)
72  {
73  errno = PGTYPES_DATE_BAD_DATE;
74  return INT_MIN;
75  }
76 
77  switch (dtype)
78  {
79  case DTK_DATE:
80  break;
81 
82  case DTK_EPOCH:
83  if (GetEpochTime(tm) < 0)
84  {
85  errno = PGTYPES_DATE_BAD_DATE;
86  return INT_MIN;
87  }
88  break;
89 
90  default:
91  errno = PGTYPES_DATE_BAD_DATE;
92  return INT_MIN;
93  }
94 
95  dDate = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1));
96 
97  return dDate;
98 }
#define MAXDATELEN
Definition: datetime.h:201
#define PGTYPES_DATE_BAD_DATE
Definition: pgtypes_error.h:8
long date
Definition: pgtypes_date.h:9
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
int32 fsec_t
Definition: timestamp.h:41
int date2j(int y, int m, int d)
Definition: datetime.c:269
#define MAXDATEFIELDS
Definition: datetime.h:203
#define DTK_EPOCH
Definition: datetime.h:153
void GetEpochTime(struct pg_tm *tm)
Definition: timestamp.c:2017
int ParseDateTime(const char *timestr, char *workbuf, size_t buflen, char **field, int *ftype, int maxfields, int *numfields)
Definition: datetime.c:537
#define DTK_DATE
Definition: datetime.h:145

◆ PGTYPESdate_from_timestamp()

date PGTYPESdate_from_timestamp ( timestamp  dt)

Definition at line 31 of file datetime.c.

References TIMESTAMP_NOT_FINITE, and USECS_PER_DAY.

Referenced by main(), and PGTYPEStimestamp_fmt_asc().

32 {
33  date dDate;
34 
35  dDate = 0; /* suppress compiler warning */
36 
37  if (!TIMESTAMP_NOT_FINITE(dt))
38  {
39  /* Microseconds to days */
40  dDate = (dt / USECS_PER_DAY);
41  }
42 
43  return dDate;
44 }
long date
Definition: pgtypes_date.h:9
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:122
#define USECS_PER_DAY
Definition: timestamp.h:91

◆ PGTYPESdate_julmdy()

void PGTYPESdate_julmdy ( date  jd,
int *  mdy 
)

Definition at line 115 of file datetime.c.

References date2j(), and j2date().

Referenced by main(), and rjulmdy().

116 {
117  int y,
118  m,
119  d;
120 
121  j2date((int) (jd + date2j(2000, 1, 1)), &y, &m, &d);
122  mdy[0] = m;
123  mdy[1] = d;
124  mdy[2] = y;
125 }
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:294
int date2j(int y, int m, int d)
Definition: datetime.c:269

◆ PGTYPESdate_mdyjul()

void PGTYPESdate_mdyjul ( int *  mdy,
date jdate 
)

Definition at line 128 of file datetime.c.

References date2j().

Referenced by main(), and rmdyjul().

129 {
130  /* month is mdy[0] */
131  /* day is mdy[1] */
132  /* year is mdy[2] */
133 
134  *jdate = (date) (date2j(mdy[2], mdy[0], mdy[1]) - date2j(2000, 1, 1));
135 }
long date
Definition: pgtypes_date.h:9
int date2j(int y, int m, int d)
Definition: datetime.c:269

◆ PGTYPESdate_new()

date* PGTYPESdate_new ( void  )

Definition at line 15 of file datetime.c.

References pgtypes_alloc().

Referenced by main().

16 {
17  date *result;
18 
19  result = (date *) pgtypes_alloc(sizeof(date));
20  /* result can be NULL if we run out of memory */
21  return result;
22 }
long date
Definition: pgtypes_date.h:9
char * pgtypes_alloc(long size)
Definition: common.c:10

◆ PGTYPESdate_to_asc()

char* PGTYPESdate_to_asc ( date  dDate)

Definition at line 101 of file datetime.c.

References buf, date2j(), DateStyle, EncodeDateOnly(), j2date(), MAXDATELEN, pgtypes_strdup(), and tm.

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

102 {
103  struct tm tt,
104  *tm = &tt;
105  char buf[MAXDATELEN + 1];
106  int DateStyle = 1;
107  bool EuroDates = false;
108 
109  j2date(dDate + date2j(2000, 1, 1), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
110  EncodeDateOnly(tm, DateStyle, buf, EuroDates);
111  return pgtypes_strdup(buf);
112 }
#define MAXDATELEN
Definition: datetime.h:201
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:3855
static struct pg_tm tm
Definition: localtime.c:108
char * pgtypes_strdup(const char *str)
Definition: common.c:20
static char * buf
Definition: pg_test_fsync.c:67
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:294
int date2j(int y, int m, int d)
Definition: datetime.c:269
int DateStyle
Definition: globals.c:115

◆ PGTYPESdate_today()

void PGTYPESdate_today ( date d)

Definition at line 148 of file datetime.c.

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

Referenced by rtoday().

149 {
150  struct tm ts;
151 
152  GetCurrentDateTime(&ts);
153  if (errno == 0)
154  *d = date2j(ts.tm_year, ts.tm_mon, ts.tm_mday) - date2j(2000, 1, 1);
155 }
void GetCurrentDateTime(struct pg_tm *tm)
Definition: datetime.c:345
static struct pg_tm tm
Definition: localtime.c:108
int date2j(int y, int m, int d)
Definition: datetime.c:269