LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/pgtypeslib - dt_common.c (source / functions) Coverage Total Hit UBC CBC
Current: b45a8d7d8b306b43f31a002f1b3f1dddc8defeaf vs 8767b449a3a1e75626dfb08f24da54933171d4c5 Lines: 57.1 % 1252 715 537 715
Current Date: 2025-10-28 08:26:42 +0900 Functions: 91.3 % 23 21 2 21
Baseline: lcov-20251028-005825-baseline Branches: 52.7 % 810 427 383 427
Baseline Date: 2025-10-27 06:37:35 +0000 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 0.0 % 3 0 3
(360..) days: 57.2 % 1249 715 534 715
Function coverage date bins:
(360..) days: 91.3 % 23 21 2 21
Branch coverage date bins:
(360..) days: 52.7 % 810 427 383 427

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /* src/interfaces/ecpg/pgtypeslib/dt_common.c */
                                  2                 :                : 
                                  3                 :                : #include "postgres_fe.h"
                                  4                 :                : 
                                  5                 :                : #include <time.h>
                                  6                 :                : #include <ctype.h>
                                  7                 :                : #include <math.h>
                                  8                 :                : 
                                  9                 :                : #include "common/string.h"
                                 10                 :                : #include "dt.h"
                                 11                 :                : #include "pgtypes_timestamp.h"
                                 12                 :                : #include "pgtypeslib_extern.h"
                                 13                 :                : 
                                 14                 :                : const int   day_tab[2][13] = {
                                 15                 :                :     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
                                 16                 :                : {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}};
                                 17                 :                : 
                                 18                 :                : typedef long AbsoluteTime;
                                 19                 :                : 
                                 20                 :                : static const datetkn datetktbl[] = {
                                 21                 :                : /*  text, token, lexval */
                                 22                 :                :     {EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
                                 23                 :                :     {"acsst", DTZ, 37800},        /* Cent. Australia */
                                 24                 :                :     {"acst", DTZ, -14400},        /* Atlantic/Porto Acre */
                                 25                 :                :     {"act", TZ, -18000},      /* Atlantic/Porto Acre */
                                 26                 :                :     {DA_D, ADBC, AD},           /* "ad" for years >= 0 */
                                 27                 :                :     {"adt", DTZ, -10800},     /* Atlantic Daylight Time */
                                 28                 :                :     {"aesst", DTZ, 39600},        /* E. Australia */
                                 29                 :                :     {"aest", TZ, 36000},      /* Australia Eastern Std Time */
                                 30                 :                :     {"aft", TZ, 16200},           /* Kabul */
                                 31                 :                :     {"ahst", TZ, -36000},     /* Alaska-Hawaii Std Time */
                                 32                 :                :     {"akdt", DTZ, -28800},        /* Alaska Daylight Time */
                                 33                 :                :     {"akst", DTZ, -32400},        /* Alaska Standard Time */
                                 34                 :                :     {"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */
                                 35                 :                :     {"almst", TZ, 25200},     /* Almaty Savings Time */
                                 36                 :                :     {"almt", TZ, 21600},      /* Almaty Time */
                                 37                 :                :     {"am", AMPM, AM},
                                 38                 :                :     {"amst", DTZ, 18000},     /* Armenia Summer Time (Yerevan) */
                                 39                 :                : #if 0
                                 40                 :                :     {"amst", DTZ, -10800},        /* Porto Velho */
                                 41                 :                : #endif
                                 42                 :                :     {"amt", TZ, 14400},           /* Armenia Time (Yerevan) */
                                 43                 :                :     {"anast", DTZ, 46800},        /* Anadyr Summer Time (Russia) */
                                 44                 :                :     {"anat", TZ, 43200},      /* Anadyr Time (Russia) */
                                 45                 :                :     {"apr", MONTH, 4},
                                 46                 :                :     {"april", MONTH, 4},
                                 47                 :                : #if 0
                                 48                 :                :     aqtst
                                 49                 :                :     aqtt
                                 50                 :                :     arst
                                 51                 :                : #endif
                                 52                 :                :     {"art", TZ, -10800},      /* Argentina Time */
                                 53                 :                : #if 0
                                 54                 :                :     ashst
                                 55                 :                :     ast                         /* Atlantic Standard Time, Arabia Standard
                                 56                 :                :                                  * Time, Acre Standard Time */
                                 57                 :                : #endif
                                 58                 :                :     {"ast", TZ, -14400},      /* Atlantic Std Time (Canada) */
                                 59                 :                :     {"at", IGNORE_DTF, 0},        /* "at" (throwaway) */
                                 60                 :                :     {"aug", MONTH, 8},
                                 61                 :                :     {"august", MONTH, 8},
                                 62                 :                :     {"awsst", DTZ, 32400},        /* W. Australia */
                                 63                 :                :     {"awst", TZ, 28800},      /* W. Australia */
                                 64                 :                :     {"awt", DTZ, -10800},
                                 65                 :                :     {"azost", DTZ, 0},            /* Azores Summer Time */
                                 66                 :                :     {"azot", TZ, -3600},      /* Azores Time */
                                 67                 :                :     {"azst", DTZ, 18000},     /* Azerbaijan Summer Time */
                                 68                 :                :     {"azt", TZ, 14400},           /* Azerbaijan Time */
                                 69                 :                :     {DB_C, ADBC, BC},           /* "bc" for years < 0 */
                                 70                 :                :     {"bdst", TZ, 7200},           /* British Double Summer Time */
                                 71                 :                :     {"bdt", TZ, 21600},           /* Dacca */
                                 72                 :                :     {"bnt", TZ, 28800},           /* Brunei Darussalam Time */
                                 73                 :                :     {"bort", TZ, 28800},      /* Borneo Time (Indonesia) */
                                 74                 :                : #if 0
                                 75                 :                :     bortst
                                 76                 :                :     bost
                                 77                 :                : #endif
                                 78                 :                :     {"bot", TZ, -14400},      /* Bolivia Time */
                                 79                 :                :     {"bra", TZ, -10800},      /* Brazil Time */
                                 80                 :                : #if 0
                                 81                 :                :     brst
                                 82                 :                :     brt
                                 83                 :                : #endif
                                 84                 :                :     {"bst", DTZ, 3600},           /* British Summer Time */
                                 85                 :                : #if 0
                                 86                 :                :     {"bst", TZ, -10800},      /* Brazil Standard Time */
                                 87                 :                :     {"bst", DTZ, -39600},     /* Bering Summer Time */
                                 88                 :                : #endif
                                 89                 :                :     {"bt", TZ, 10800},            /* Baghdad Time */
                                 90                 :                :     {"btt", TZ, 21600},           /* Bhutan Time */
                                 91                 :                :     {"cadt", DTZ, 37800},     /* Central Australian DST */
                                 92                 :                :     {"cast", TZ, 34200},      /* Central Australian ST */
                                 93                 :                :     {"cat", TZ, -36000},      /* Central Alaska Time */
                                 94                 :                :     {"cct", TZ, 28800},           /* China Coast Time */
                                 95                 :                : #if 0
                                 96                 :                :     {"cct", TZ, 23400},           /* Indian Cocos (Island) Time */
                                 97                 :                : #endif
                                 98                 :                :     {"cdt", DTZ, -18000},     /* Central Daylight Time */
                                 99                 :                :     {"cest", DTZ, 7200},      /* Central European Dayl.Time */
                                100                 :                :     {"cet", TZ, 3600},            /* Central European Time */
                                101                 :                :     {"cetdst", DTZ, 7200},        /* Central European Dayl.Time */
                                102                 :                :     {"chadt", DTZ, 49500},        /* Chatham Island Daylight Time (13:45) */
                                103                 :                :     {"chast", TZ, 45900},     /* Chatham Island Time (12:45) */
                                104                 :                : #if 0
                                105                 :                :     ckhst
                                106                 :                : #endif
                                107                 :                :     {"ckt", TZ, 43200},           /* Cook Islands Time */
                                108                 :                :     {"clst", DTZ, -10800},        /* Chile Summer Time */
                                109                 :                :     {"clt", TZ, -14400},      /* Chile Time */
                                110                 :                : #if 0
                                111                 :                :     cost
                                112                 :                : #endif
                                113                 :                :     {"cot", TZ, -18000},      /* Columbia Time */
                                114                 :                :     {"cst", TZ, -21600},      /* Central Standard Time */
                                115                 :                : #if 0
                                116                 :                :     cvst
                                117                 :                : #endif
                                118                 :                :     {"cvt", TZ, 25200},           /* Christmas Island Time (Indian Ocean) */
                                119                 :                :     {"cxt", TZ, 25200},           /* Christmas Island Time (Indian Ocean) */
                                120                 :                :     {"d", UNITS, DTK_DAY},        /* "day of month" for ISO input */
                                121                 :                :     {"davt", TZ, 25200},      /* Davis Time (Antarctica) */
                                122                 :                :     {"ddut", TZ, 36000},      /* Dumont-d'Urville Time (Antarctica) */
                                123                 :                :     {"dec", MONTH, 12},
                                124                 :                :     {"december", MONTH, 12},
                                125                 :                :     {"dnt", TZ, 3600},            /* Dansk Normal Tid */
                                126                 :                :     {"dow", UNITS, DTK_DOW},  /* day of week */
                                127                 :                :     {"doy", UNITS, DTK_DOY},  /* day of year */
                                128                 :                :     {"dst", DTZMOD, SECS_PER_HOUR},
                                129                 :                : #if 0
                                130                 :                :     {"dusst", DTZ, 21600},        /* Dushanbe Summer Time */
                                131                 :                : #endif
                                132                 :                :     {"easst", DTZ, -18000},       /* Easter Island Summer Time */
                                133                 :                :     {"east", TZ, -21600},     /* Easter Island Time */
                                134                 :                :     {"eat", TZ, 10800},           /* East Africa Time */
                                135                 :                : #if 0
                                136                 :                :     {"east", DTZ, 14400},     /* Indian Antananarivo Savings Time */
                                137                 :                :     {"eat", TZ, 10800},           /* Indian Antananarivo Time */
                                138                 :                :     {"ect", TZ, -14400},      /* Eastern Caribbean Time */
                                139                 :                :     {"ect", TZ, -18000},      /* Ecuador Time */
                                140                 :                : #endif
                                141                 :                :     {"edt", DTZ, -14400},     /* Eastern Daylight Time */
                                142                 :                :     {"eest", DTZ, 10800},     /* Eastern Europe Summer Time */
                                143                 :                :     {"eet", TZ, 7200},            /* East. Europe, USSR Zone 1 */
                                144                 :                :     {"eetdst", DTZ, 10800},       /* Eastern Europe Daylight Time */
                                145                 :                :     {"egst", DTZ, 0},         /* East Greenland Summer Time */
                                146                 :                :     {"egt", TZ, -3600},           /* East Greenland Time */
                                147                 :                : #if 0
                                148                 :                :     ehdt
                                149                 :                : #endif
                                150                 :                :     {EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
                                151                 :                :     {"est", TZ, -18000},      /* Eastern Standard Time */
                                152                 :                :     {"feb", MONTH, 2},
                                153                 :                :     {"february", MONTH, 2},
                                154                 :                :     {"fjst", DTZ, -46800},        /* Fiji Summer Time (13 hour offset!) */
                                155                 :                :     {"fjt", TZ, -43200},      /* Fiji Time */
                                156                 :                :     {"fkst", DTZ, -10800},        /* Falkland Islands Summer Time */
                                157                 :                :     {"fkt", TZ, -7200},           /* Falkland Islands Time */
                                158                 :                : #if 0
                                159                 :                :     fnst
                                160                 :                :     fnt
                                161                 :                : #endif
                                162                 :                :     {"fri", DOW, 5},
                                163                 :                :     {"friday", DOW, 5},
                                164                 :                :     {"fst", TZ, 3600},            /* French Summer Time */
                                165                 :                :     {"fwt", DTZ, 7200},           /* French Winter Time  */
                                166                 :                :     {"galt", TZ, -21600},     /* Galapagos Time */
                                167                 :                :     {"gamt", TZ, -32400},     /* Gambier Time */
                                168                 :                :     {"gest", DTZ, 18000},     /* Georgia Summer Time */
                                169                 :                :     {"get", TZ, 14400},           /* Georgia Time */
                                170                 :                :     {"gft", TZ, -10800},      /* French Guiana Time */
                                171                 :                : #if 0
                                172                 :                :     ghst
                                173                 :                : #endif
                                174                 :                :     {"gilt", TZ, 43200},      /* Gilbert Islands Time */
                                175                 :                :     {"gmt", TZ, 0},               /* Greenwich Mean Time */
                                176                 :                :     {"gst", TZ, 36000},           /* Guam Std Time, USSR Zone 9 */
                                177                 :                :     {"gyt", TZ, -14400},      /* Guyana Time */
                                178                 :                :     {"h", UNITS, DTK_HOUR},       /* "hour" */
                                179                 :                : #if 0
                                180                 :                :     hadt
                                181                 :                :     hast
                                182                 :                : #endif
                                183                 :                :     {"hdt", DTZ, -32400},     /* Hawaii/Alaska Daylight Time */
                                184                 :                : #if 0
                                185                 :                :     hkst
                                186                 :                : #endif
                                187                 :                :     {"hkt", TZ, 28800},           /* Hong Kong Time */
                                188                 :                : #if 0
                                189                 :                :     {"hmt", TZ, 10800},           /* Hellas ? ? */
                                190                 :                :     hovst
                                191                 :                :     hovt
                                192                 :                : #endif
                                193                 :                :     {"hst", TZ, -36000},      /* Hawaii Std Time */
                                194                 :                : #if 0
                                195                 :                :     hwt
                                196                 :                : #endif
                                197                 :                :     {"ict", TZ, 25200},           /* Indochina Time */
                                198                 :                :     {"idle", TZ, 43200},      /* Intl. Date Line, East */
                                199                 :                :     {"idlw", TZ, -43200},     /* Intl. Date Line, West */
                                200                 :                : #if 0
                                201                 :                :     idt                         /* Israeli, Iran, Indian Daylight Time */
                                202                 :                : #endif
                                203                 :                :     {LATE, RESERV, DTK_LATE},   /* "infinity" reserved for "late time" */
                                204                 :                :     {"iot", TZ, 18000},           /* Indian Chagos Time */
                                205                 :                :     {"irkst", DTZ, 32400},        /* Irkutsk Summer Time */
                                206                 :                :     {"irkt", TZ, 28800},      /* Irkutsk Time */
                                207                 :                :     {"irt", TZ, 12600},           /* Iran Time */
                                208                 :                :     {"isodow", UNITS, DTK_ISODOW},    /* ISO day of week, Sunday == 7 */
                                209                 :                : #if 0
                                210                 :                :     isst
                                211                 :                : #endif
                                212                 :                :     {"ist", TZ, 7200},            /* Israel */
                                213                 :                :     {"it", TZ, 12600},            /* Iran Time */
                                214                 :                :     {"j", UNITS, DTK_JULIAN},
                                215                 :                :     {"jan", MONTH, 1},
                                216                 :                :     {"january", MONTH, 1},
                                217                 :                :     {"javt", TZ, 25200},      /* Java Time (07:00? see JT) */
                                218                 :                :     {"jayt", TZ, 32400},      /* Jayapura Time (Indonesia) */
                                219                 :                :     {"jd", UNITS, DTK_JULIAN},
                                220                 :                :     {"jst", TZ, 32400},           /* Japan Std Time,USSR Zone 8 */
                                221                 :                :     {"jt", TZ, 27000},            /* Java Time (07:30? see JAVT) */
                                222                 :                :     {"jul", MONTH, 7},
                                223                 :                :     {"julian", UNITS, DTK_JULIAN},
                                224                 :                :     {"july", MONTH, 7},
                                225                 :                :     {"jun", MONTH, 6},
                                226                 :                :     {"june", MONTH, 6},
                                227                 :                :     {"kdt", DTZ, 36000},      /* Korea Daylight Time */
                                228                 :                :     {"kgst", DTZ, 21600},     /* Kyrgyzstan Summer Time */
                                229                 :                :     {"kgt", TZ, 18000},           /* Kyrgyzstan Time */
                                230                 :                :     {"kost", TZ, 43200},      /* Kosrae Time */
                                231                 :                :     {"krast", DTZ, 25200},        /* Krasnoyarsk Summer Time */
                                232                 :                :     {"krat", TZ, 28800},      /* Krasnoyarsk Standard Time */
                                233                 :                :     {"kst", TZ, 32400},           /* Korea Standard Time */
                                234                 :                :     {"lhdt", DTZ, 39600},     /* Lord Howe Daylight Time, Australia */
                                235                 :                :     {"lhst", TZ, 37800},      /* Lord Howe Standard Time, Australia */
                                236                 :                :     {"ligt", TZ, 36000},      /* From Melbourne, Australia */
                                237                 :                :     {"lint", TZ, 50400},      /* Line Islands Time (Kiribati; +14 hours!) */
                                238                 :                :     {"lkt", TZ, 21600},           /* Lanka Time */
                                239                 :                :     {"m", UNITS, DTK_MONTH},  /* "month" for ISO input */
                                240                 :                :     {"magst", DTZ, 43200},        /* Magadan Summer Time */
                                241                 :                :     {"magt", TZ, 39600},      /* Magadan Time */
                                242                 :                :     {"mar", MONTH, 3},
                                243                 :                :     {"march", MONTH, 3},
                                244                 :                :     {"mart", TZ, -34200},     /* Marquesas Time */
                                245                 :                :     {"mawt", TZ, 21600},      /* Mawson, Antarctica */
                                246                 :                :     {"may", MONTH, 5},
                                247                 :                :     {"mdt", DTZ, -21600},     /* Mountain Daylight Time */
                                248                 :                :     {"mest", DTZ, 7200},      /* Middle Europe Summer Time */
                                249                 :                :     {"met", TZ, 3600},            /* Middle Europe Time */
                                250                 :                :     {"metdst", DTZ, 7200},        /* Middle Europe Daylight Time */
                                251                 :                :     {"mewt", TZ, 3600},           /* Middle Europe Winter Time */
                                252                 :                :     {"mez", TZ, 3600},            /* Middle Europe Zone */
                                253                 :                :     {"mht", TZ, 43200},           /* Kwajalein */
                                254                 :                :     {"mm", UNITS, DTK_MINUTE},    /* "minute" for ISO input */
                                255                 :                :     {"mmt", TZ, 23400},           /* Myannar Time */
                                256                 :                :     {"mon", DOW, 1},
                                257                 :                :     {"monday", DOW, 1},
                                258                 :                : #if 0
                                259                 :                :     most
                                260                 :                : #endif
                                261                 :                :     {"mpt", TZ, 36000},           /* North Mariana Islands Time */
                                262                 :                :     {"msd", DTZ, 14400},      /* Moscow Summer Time */
                                263                 :                :     {"msk", TZ, 10800},           /* Moscow Time */
                                264                 :                :     {"mst", TZ, -25200},      /* Mountain Standard Time */
                                265                 :                :     {"mt", TZ, 30600},            /* Moluccas Time */
                                266                 :                :     {"mut", TZ, 14400},           /* Mauritius Island Time */
                                267                 :                :     {"mvt", TZ, 18000},           /* Maldives Island Time */
                                268                 :                :     {"myt", TZ, 28800},           /* Malaysia Time */
                                269                 :                : #if 0
                                270                 :                :     ncst
                                271                 :                : #endif
                                272                 :                :     {"nct", TZ, 39600},           /* New Caledonia Time */
                                273                 :                :     {"ndt", DTZ, -9000},      /* Nfld. Daylight Time */
                                274                 :                :     {"nft", TZ, -12600},      /* Newfoundland Standard Time */
                                275                 :                :     {"nor", TZ, 3600},            /* Norway Standard Time */
                                276                 :                :     {"nov", MONTH, 11},
                                277                 :                :     {"november", MONTH, 11},
                                278                 :                :     {"novst", DTZ, 25200},        /* Novosibirsk Summer Time */
                                279                 :                :     {"novt", TZ, 21600},      /* Novosibirsk Standard Time */
                                280                 :                :     {NOW, RESERV, DTK_NOW},     /* current transaction time */
                                281                 :                :     {"npt", TZ, 20700},           /* Nepal Standard Time (GMT-5:45) */
                                282                 :                :     {"nst", TZ, -12600},      /* Nfld. Standard Time */
                                283                 :                :     {"nt", TZ, -39600},           /* Nome Time */
                                284                 :                :     {"nut", TZ, -39600},      /* Niue Time */
                                285                 :                :     {"nzdt", DTZ, 46800},     /* New Zealand Daylight Time */
                                286                 :                :     {"nzst", TZ, 43200},      /* New Zealand Standard Time */
                                287                 :                :     {"nzt", TZ, 43200},           /* New Zealand Time */
                                288                 :                :     {"oct", MONTH, 10},
                                289                 :                :     {"october", MONTH, 10},
                                290                 :                :     {"omsst", DTZ, 25200},        /* Omsk Summer Time */
                                291                 :                :     {"omst", TZ, 21600},      /* Omsk Time */
                                292                 :                :     {"on", IGNORE_DTF, 0},        /* "on" (throwaway) */
                                293                 :                :     {"pdt", DTZ, -25200},     /* Pacific Daylight Time */
                                294                 :                : #if 0
                                295                 :                :     pest
                                296                 :                : #endif
                                297                 :                :     {"pet", TZ, -18000},      /* Peru Time */
                                298                 :                :     {"petst", DTZ, 46800},        /* Petropavlovsk-Kamchatski Summer Time */
                                299                 :                :     {"pett", TZ, 43200},      /* Petropavlovsk-Kamchatski Time */
                                300                 :                :     {"pgt", TZ, 36000},           /* Papua New Guinea Time */
                                301                 :                :     {"phot", TZ, 46800},      /* Phoenix Islands (Kiribati) Time */
                                302                 :                : #if 0
                                303                 :                :     phst
                                304                 :                : #endif
                                305                 :                :     {"pht", TZ, 28800},           /* Philippine Time */
                                306                 :                :     {"pkt", TZ, 18000},           /* Pakistan Time */
                                307                 :                :     {"pm", AMPM, PM},
                                308                 :                :     {"pmdt", DTZ, -7200},     /* Pierre & Miquelon Daylight Time */
                                309                 :                : #if 0
                                310                 :                :     pmst
                                311                 :                : #endif
                                312                 :                :     {"pont", TZ, 39600},      /* Ponape Time (Micronesia) */
                                313                 :                :     {"pst", TZ, -28800},      /* Pacific Standard Time */
                                314                 :                :     {"pwt", TZ, 32400},           /* Palau Time */
                                315                 :                :     {"pyst", DTZ, -10800},        /* Paraguay Summer Time */
                                316                 :                :     {"pyt", TZ, -14400},      /* Paraguay Time */
                                317                 :                :     {"ret", DTZ, 14400},      /* Reunion Island Time */
                                318                 :                :     {"s", UNITS, DTK_SECOND}, /* "seconds" for ISO input */
                                319                 :                :     {"sadt", DTZ, 37800},     /* S. Australian Dayl. Time */
                                320                 :                : #if 0
                                321                 :                :     samst
                                322                 :                :     samt
                                323                 :                : #endif
                                324                 :                :     {"sast", TZ, 34200},      /* South Australian Std Time */
                                325                 :                :     {"sat", DOW, 6},
                                326                 :                :     {"saturday", DOW, 6},
                                327                 :                : #if 0
                                328                 :                :     sbt
                                329                 :                : #endif
                                330                 :                :     {"sct", DTZ, 14400},      /* Mahe Island Time */
                                331                 :                :     {"sep", MONTH, 9},
                                332                 :                :     {"sept", MONTH, 9},
                                333                 :                :     {"september", MONTH, 9},
                                334                 :                :     {"set", TZ, -3600},           /* Seychelles Time ?? */
                                335                 :                : #if 0
                                336                 :                :     sgt
                                337                 :                : #endif
                                338                 :                :     {"sst", DTZ, 7200},           /* Swedish Summer Time */
                                339                 :                :     {"sun", DOW, 0},
                                340                 :                :     {"sunday", DOW, 0},
                                341                 :                :     {"swt", TZ, 3600},            /* Swedish Winter Time */
                                342                 :                : #if 0
                                343                 :                :     syot
                                344                 :                : #endif
                                345                 :                :     {"t", ISOTIME, DTK_TIME}, /* Filler for ISO time fields */
                                346                 :                :     {"tft", TZ, 18000},           /* Kerguelen Time */
                                347                 :                :     {"that", TZ, -36000},     /* Tahiti Time */
                                348                 :                :     {"thu", DOW, 4},
                                349                 :                :     {"thur", DOW, 4},
                                350                 :                :     {"thurs", DOW, 4},
                                351                 :                :     {"thursday", DOW, 4},
                                352                 :                :     {"tjt", TZ, 18000},           /* Tajikistan Time */
                                353                 :                :     {"tkt", TZ, -36000},      /* Tokelau Time */
                                354                 :                :     {"tmt", TZ, 18000},           /* Turkmenistan Time */
                                355                 :                :     {TODAY, RESERV, DTK_TODAY}, /* midnight */
                                356                 :                :     {TOMORROW, RESERV, DTK_TOMORROW},   /* tomorrow midnight */
                                357                 :                : #if 0
                                358                 :                :     tost
                                359                 :                : #endif
                                360                 :                :     {"tot", TZ, 46800},           /* Tonga Time */
                                361                 :                : #if 0
                                362                 :                :     tpt
                                363                 :                : #endif
                                364                 :                :     {"truk", TZ, 36000},      /* Truk Time */
                                365                 :                :     {"tue", DOW, 2},
                                366                 :                :     {"tues", DOW, 2},
                                367                 :                :     {"tuesday", DOW, 2},
                                368                 :                :     {"tvt", TZ, 43200},           /* Tuvalu Time */
                                369                 :                : #if 0
                                370                 :                :     uct
                                371                 :                : #endif
                                372                 :                :     {"ulast", DTZ, 32400},        /* Ulan Bator Summer Time */
                                373                 :                :     {"ulat", TZ, 28800},      /* Ulan Bator Time */
                                374                 :                :     {"ut", TZ, 0},
                                375                 :                :     {"utc", TZ, 0},
                                376                 :                :     {"uyst", DTZ, -7200},     /* Uruguay Summer Time */
                                377                 :                :     {"uyt", TZ, -10800},      /* Uruguay Time */
                                378                 :                :     {"uzst", DTZ, 21600},     /* Uzbekistan Summer Time */
                                379                 :                :     {"uzt", TZ, 18000},           /* Uzbekistan Time */
                                380                 :                :     {"vet", TZ, -14400},      /* Venezuela Time */
                                381                 :                :     {"vlast", DTZ, 39600},        /* Vladivostok Summer Time */
                                382                 :                :     {"vlat", TZ, 36000},      /* Vladivostok Time */
                                383                 :                : #if 0
                                384                 :                :     vust
                                385                 :                : #endif
                                386                 :                :     {"vut", TZ, 39600},           /* Vanuata Time */
                                387                 :                :     {"wadt", DTZ, 28800},     /* West Australian DST */
                                388                 :                :     {"wakt", TZ, 43200},      /* Wake Time */
                                389                 :                : #if 0
                                390                 :                :     warst
                                391                 :                : #endif
                                392                 :                :     {"wast", TZ, 25200},      /* West Australian Std Time */
                                393                 :                :     {"wat", TZ, -3600},           /* West Africa Time */
                                394                 :                :     {"wdt", DTZ, 32400},      /* West Australian DST */
                                395                 :                :     {"wed", DOW, 3},
                                396                 :                :     {"wednesday", DOW, 3},
                                397                 :                :     {"weds", DOW, 3},
                                398                 :                :     {"west", DTZ, 3600},      /* Western Europe Summer Time */
                                399                 :                :     {"wet", TZ, 0},               /* Western Europe */
                                400                 :                :     {"wetdst", DTZ, 3600},        /* Western Europe Daylight Savings Time */
                                401                 :                :     {"wft", TZ, 43200},           /* Wallis and Futuna Time */
                                402                 :                :     {"wgst", DTZ, -7200},     /* West Greenland Summer Time */
                                403                 :                :     {"wgt", TZ, -10800},      /* West Greenland Time */
                                404                 :                :     {"wst", TZ, 28800},           /* West Australian Standard Time */
                                405                 :                :     {"y", UNITS, DTK_YEAR},       /* "year" for ISO input */
                                406                 :                :     {"yakst", DTZ, 36000},        /* Yakutsk Summer Time */
                                407                 :                :     {"yakt", TZ, 32400},      /* Yakutsk Time */
                                408                 :                :     {"yapt", TZ, 36000},      /* Yap Time (Micronesia) */
                                409                 :                :     {"ydt", DTZ, -28800},     /* Yukon Daylight Time */
                                410                 :                :     {"yekst", DTZ, 21600},        /* Yekaterinburg Summer Time */
                                411                 :                :     {"yekt", TZ, 18000},      /* Yekaterinburg Time */
                                412                 :                :     {YESTERDAY, RESERV, DTK_YESTERDAY}, /* yesterday midnight */
                                413                 :                :     {"yst", TZ, -32400},      /* Yukon Standard Time */
                                414                 :                :     {"z", TZ, 0},             /* time zone tag per ISO-8601 */
                                415                 :                :     {"zp4", TZ, -14400},      /* UTC +4  hours. */
                                416                 :                :     {"zp5", TZ, -18000},      /* UTC +5  hours. */
                                417                 :                :     {"zp6", TZ, -21600},      /* UTC +6  hours. */
                                418                 :                :     {ZULU, TZ, 0},              /* UTC */
                                419                 :                : };
                                420                 :                : 
                                421                 :                : static const datetkn deltatktbl[] = {
                                422                 :                :     /* text, token, lexval */
                                423                 :                :     {"@", IGNORE_DTF, 0},     /* postgres relative prefix */
                                424                 :                :     {DAGO, AGO, 0},             /* "ago" indicates negative time offset */
                                425                 :                :     {"c", UNITS, DTK_CENTURY},    /* "century" relative */
                                426                 :                :     {"cent", UNITS, DTK_CENTURY}, /* "century" relative */
                                427                 :                :     {"centuries", UNITS, DTK_CENTURY},    /* "centuries" relative */
                                428                 :                :     {DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative */
                                429                 :                :     {"d", UNITS, DTK_DAY},        /* "day" relative */
                                430                 :                :     {DDAY, UNITS, DTK_DAY},     /* "day" relative */
                                431                 :                :     {"days", UNITS, DTK_DAY}, /* "days" relative */
                                432                 :                :     {"dec", UNITS, DTK_DECADE}, /* "decade" relative */
                                433                 :                :     {DDECADE, UNITS, DTK_DECADE},   /* "decade" relative */
                                434                 :                :     {"decades", UNITS, DTK_DECADE}, /* "decades" relative */
                                435                 :                :     {"decs", UNITS, DTK_DECADE},  /* "decades" relative */
                                436                 :                :     {"h", UNITS, DTK_HOUR},       /* "hour" relative */
                                437                 :                :     {DHOUR, UNITS, DTK_HOUR},   /* "hour" relative */
                                438                 :                :     {"hours", UNITS, DTK_HOUR}, /* "hours" relative */
                                439                 :                :     {"hr", UNITS, DTK_HOUR},  /* "hour" relative */
                                440                 :                :     {"hrs", UNITS, DTK_HOUR}, /* "hours" relative */
                                441                 :                :     {"m", UNITS, DTK_MINUTE}, /* "minute" relative */
                                442                 :                :     {"microsecon", UNITS, DTK_MICROSEC},  /* "microsecond" relative */
                                443                 :                :     {"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
                                444                 :                :     {"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
                                445                 :                :     {DMILLENNIUM, UNITS, DTK_MILLENNIUM},   /* "millennium" relative */
                                446                 :                :     {"millisecon", UNITS, DTK_MILLISEC},  /* relative */
                                447                 :                :     {"mils", UNITS, DTK_MILLENNIUM},  /* "millennia" relative */
                                448                 :                :     {"min", UNITS, DTK_MINUTE}, /* "minute" relative */
                                449                 :                :     {"mins", UNITS, DTK_MINUTE},  /* "minutes" relative */
                                450                 :                :     {DMINUTE, UNITS, DTK_MINUTE},   /* "minute" relative */
                                451                 :                :     {"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative */
                                452                 :                :     {"mon", UNITS, DTK_MONTH},    /* "months" relative */
                                453                 :                :     {"mons", UNITS, DTK_MONTH}, /* "months" relative */
                                454                 :                :     {DMONTH, UNITS, DTK_MONTH}, /* "month" relative */
                                455                 :                :     {"months", UNITS, DTK_MONTH},
                                456                 :                :     {"ms", UNITS, DTK_MILLISEC},
                                457                 :                :     {"msec", UNITS, DTK_MILLISEC},
                                458                 :                :     {DMILLISEC, UNITS, DTK_MILLISEC},
                                459                 :                :     {"mseconds", UNITS, DTK_MILLISEC},
                                460                 :                :     {"msecs", UNITS, DTK_MILLISEC},
                                461                 :                :     {"qtr", UNITS, DTK_QUARTER},  /* "quarter" relative */
                                462                 :                :     {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative */
                                463                 :                :     {"s", UNITS, DTK_SECOND},
                                464                 :                :     {"sec", UNITS, DTK_SECOND},
                                465                 :                :     {DSECOND, UNITS, DTK_SECOND},
                                466                 :                :     {"seconds", UNITS, DTK_SECOND},
                                467                 :                :     {"secs", UNITS, DTK_SECOND},
                                468                 :                :     {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
                                469                 :                :     {"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
                                470                 :                :     {"timezone_m", UNITS, DTK_TZ_MINUTE}, /* timezone minutes units */
                                471                 :                :     {"us", UNITS, DTK_MICROSEC},  /* "microsecond" relative */
                                472                 :                :     {"usec", UNITS, DTK_MICROSEC},    /* "microsecond" relative */
                                473                 :                :     {DMICROSEC, UNITS, DTK_MICROSEC},   /* "microsecond" relative */
                                474                 :                :     {"useconds", UNITS, DTK_MICROSEC},    /* "microseconds" relative */
                                475                 :                :     {"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
                                476                 :                :     {"w", UNITS, DTK_WEEK},       /* "week" relative */
                                477                 :                :     {DWEEK, UNITS, DTK_WEEK},   /* "week" relative */
                                478                 :                :     {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
                                479                 :                :     {"y", UNITS, DTK_YEAR},       /* "year" relative */
                                480                 :                :     {DYEAR, UNITS, DTK_YEAR},   /* "year" relative */
                                481                 :                :     {"years", UNITS, DTK_YEAR}, /* "years" relative */
                                482                 :                :     {"yr", UNITS, DTK_YEAR},  /* "year" relative */
                                483                 :                :     {"yrs", UNITS, DTK_YEAR}, /* "years" relative */
                                484                 :                : };
                                485                 :                : 
                                486                 :                : static const unsigned int szdatetktbl = lengthof(datetktbl);
                                487                 :                : static const unsigned int szdeltatktbl = lengthof(deltatktbl);
                                488                 :                : 
                                489                 :                : static const datetkn *datecache[MAXDATEFIELDS] = {NULL};
                                490                 :                : 
                                491                 :                : static const datetkn *deltacache[MAXDATEFIELDS] = {NULL};
                                492                 :                : 
                                493                 :                : char       *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
                                494                 :                : 
                                495                 :                : char       *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL};
                                496                 :                : 
                                497                 :                : char       *pgtypes_date_weekdays_short[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL};
                                498                 :                : 
                                499                 :                : char       *pgtypes_date_months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL};
                                500                 :                : 
                                501                 :                : static const datetkn *
 2568 tgl@sss.pgh.pa.us         502                 :CBC          45 : datebsearch(const char *key, const datetkn *base, unsigned int nel)
                                503                 :                : {
 5285                           504         [ +  - ]:             45 :     if (nel > 0)
                                505                 :                :     {
 2568                           506                 :             45 :         const datetkn *last = base + nel - 1,
                                507                 :                :                    *position;
                                508                 :                :         int         result;
                                509                 :                : 
 5285                           510         [ +  + ]:            293 :         while (last >= base)
                                511                 :                :         {
                                512                 :            288 :             position = base + ((last - base) >> 1);
                                513                 :                :             /* precheck the first character for a bit of extra speed */
 4030                           514                 :            288 :             result = (int) key[0] - (int) position->token[0];
 8121 bruce@momjian.us          515         [ +  + ]:            288 :             if (result == 0)
                                516                 :                :             {
                                517                 :                :                 /* use strncmp so that we match truncated tokens */
 5285 tgl@sss.pgh.pa.us         518                 :            141 :                 result = strncmp(key, position->token, TOKMAXLEN);
                                519         [ +  + ]:            141 :                 if (result == 0)
                                520                 :             40 :                     return position;
                                521                 :                :             }
                                522         [ +  + ]:            248 :             if (result < 0)
                                523                 :            116 :                 last = position - 1;
                                524                 :                :             else
                                525                 :            132 :                 base = position + 1;
                                526                 :                :         }
                                527                 :                :     }
 8121 bruce@momjian.us          528                 :              5 :     return NULL;
                                529                 :                : }
                                530                 :                : 
                                531                 :                : /* DecodeUnits()
                                532                 :                :  * Decode text string using lookup table.
                                533                 :                :  * This routine supports time interval decoding.
                                534                 :                :  */
                                535                 :                : int
 8248 meskes@postgresql.or      536                 :             44 : DecodeUnits(int field, char *lowtoken, int *val)
                                537                 :                : {
                                538                 :                :     int         type;
                                539                 :                :     const datetkn *tp;
                                540                 :                : 
                                541                 :                :     /* use strncmp so that we match truncated tokens */
 7462 bruce@momjian.us          542         [ +  + ]:             44 :     if (deltacache[field] != NULL &&
                                543         [ +  + ]:             30 :         strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0)
 8248 meskes@postgresql.or      544                 :             20 :         tp = deltacache[field];
                                545                 :                :     else
                                546                 :             24 :         tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
                                547                 :             44 :     deltacache[field] = tp;
                                548         [ +  + ]:             44 :     if (tp == NULL)
                                549                 :                :     {
                                550                 :              1 :         type = UNKNOWN_FIELD;
                                551                 :              1 :         *val = 0;
                                552                 :                :     }
                                553                 :                :     else
                                554                 :                :     {
                                555                 :             43 :         type = tp->type;
 4030 tgl@sss.pgh.pa.us         556                 :             43 :         *val = tp->value;
                                557                 :                :     }
                                558                 :                : 
 8248 meskes@postgresql.or      559                 :             44 :     return type;
                                560                 :                : }                               /* DecodeUnits() */
                                561                 :                : 
                                562                 :                : /*
                                563                 :                :  * Calendar time to Julian date conversions.
                                564                 :                :  * Julian date is commonly used in astronomical applications,
                                565                 :                :  *  since it is numerically accurate and computationally simple.
                                566                 :                :  * The algorithms here will accurately convert between Julian day
                                567                 :                :  *  and calendar date for all non-negative Julian days
                                568                 :                :  *  (i.e. from Nov 24, -4713 on).
                                569                 :                :  *
                                570                 :                :  * These routines will be used by other date/time packages
                                571                 :                :  * - thomas 97/02/25
                                572                 :                :  *
                                573                 :                :  * Rewritten to eliminate overflow problems. This now allows the
                                574                 :                :  * routines to work correctly for all Julian day counts from
                                575                 :                :  * 0 to 2147483647  (Nov 24, -4713 to Jun 3, 5874898) assuming
                                576                 :                :  * a 32-bit integer. Longer types should also work to the limits
                                577                 :                :  * of their precision.
                                578                 :                :  */
                                579                 :                : 
                                580                 :                : int
 8258                           581                 :            913 : date2j(int y, int m, int d)
                                582                 :                : {
                                583                 :                :     int         julian;
                                584                 :                :     int         century;
                                585                 :                : 
 8121 bruce@momjian.us          586         [ +  + ]:            913 :     if (m > 2)
                                587                 :                :     {
 8258 meskes@postgresql.or      588                 :             52 :         m += 1;
                                589                 :             52 :         y += 4800;
                                590                 :                :     }
                                591                 :                :     else
                                592                 :                :     {
                                593                 :            861 :         m += 13;
                                594                 :            861 :         y += 4799;
                                595                 :                :     }
                                596                 :                : 
 8121 bruce@momjian.us          597                 :            913 :     century = y / 100;
                                598                 :            913 :     julian = y * 365 - 32167;
                                599                 :            913 :     julian += y / 4 - century + century / 4;
                                600                 :            913 :     julian += 7834 * m / 256 + d;
                                601                 :                : 
 8258 meskes@postgresql.or      602                 :            913 :     return julian;
                                603                 :                : }                               /* date2j() */
                                604                 :                : 
                                605                 :                : void
                                606                 :            285 : j2date(int jd, int *year, int *month, int *day)
                                607                 :                : {
                                608                 :                :     unsigned int julian;
                                609                 :                :     unsigned int quad;
                                610                 :                :     unsigned int extra;
                                611                 :                :     int         y;
                                612                 :                : 
                                613                 :            285 :     julian = jd;
                                614                 :            285 :     julian += 32044;
 8121 bruce@momjian.us          615                 :            285 :     quad = julian / 146097;
                                616                 :            285 :     extra = (julian - quad * 146097) * 4 + 3;
                                617                 :            285 :     julian += 60 + quad * 3 + extra / 146097;
                                618                 :            285 :     quad = julian / 1461;
                                619                 :            285 :     julian -= quad * 1461;
 8258 meskes@postgresql.or      620                 :            285 :     y = julian * 4 / 1461;
 7462 bruce@momjian.us          621         [ +  + ]:            285 :     julian = ((y != 0) ? (julian + 305) % 365 : (julian + 306) % 366) + 123;
 8121                           622                 :            285 :     y += quad * 4;
 8258 meskes@postgresql.or      623                 :            285 :     *year = y - 4800;
                                624                 :            285 :     quad = julian * 2141 / 65536;
 8121 bruce@momjian.us          625                 :            285 :     *day = julian - 7834 * quad / 256;
 8258 meskes@postgresql.or      626                 :            285 :     *month = (quad + 10) % 12 + 1;
 3051 tgl@sss.pgh.pa.us         627                 :            285 : }                               /* j2date() */
                                628                 :                : 
                                629                 :                : /* DecodeSpecial()
                                630                 :                :  * Decode text string using lookup table.
                                631                 :                :  * Implement a cache lookup since it is likely that dates
                                632                 :                :  *  will be related in format.
                                633                 :                :  */
                                634                 :                : static int
 8258 meskes@postgresql.or      635                 :            114 : DecodeSpecial(int field, char *lowtoken, int *val)
                                636                 :                : {
                                637                 :                :     int         type;
                                638                 :                :     const datetkn *tp;
                                639                 :                : 
                                640                 :                :     /* use strncmp so that we match truncated tokens */
 7462 bruce@momjian.us          641         [ +  + ]:            114 :     if (datecache[field] != NULL &&
                                642         [ +  + ]:             99 :         strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0)
 8258 meskes@postgresql.or      643                 :             93 :         tp = datecache[field];
                                644                 :                :     else
                                645                 :                :     {
                                646                 :             21 :         tp = NULL;
                                647         [ +  - ]:             21 :         if (!tp)
                                648                 :             21 :             tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
                                649                 :                :     }
                                650                 :            114 :     datecache[field] = tp;
                                651         [ +  + ]:            114 :     if (tp == NULL)
                                652                 :                :     {
                                653                 :              4 :         type = UNKNOWN_FIELD;
                                654                 :              4 :         *val = 0;
                                655                 :                :     }
                                656                 :                :     else
                                657                 :                :     {
                                658                 :            110 :         type = tp->type;
 4030 tgl@sss.pgh.pa.us         659                 :            110 :         *val = tp->value;
                                660                 :                :     }
                                661                 :                : 
 8258 meskes@postgresql.or      662                 :            114 :     return type;
                                663                 :                : }                               /* DecodeSpecial() */
                                664                 :                : 
                                665                 :                : /* EncodeDateOnly()
                                666                 :                :  * Encode date as local time.
                                667                 :                :  */
                                668                 :                : void
 3051 tgl@sss.pgh.pa.us         669                 :             95 : EncodeDateOnly(struct tm *tm, int style, char *str, bool EuroDates)
                                670                 :                : {
 2969 peter_e@gmx.net           671   [ +  -  +  - ]:             95 :     Assert(tm->tm_mon >= 1 && tm->tm_mon <= MONTHS_PER_YEAR);
                                672                 :                : 
 8258 meskes@postgresql.or      673   [ +  -  -  - ]:             95 :     switch (style)
                                674                 :                :     {
                                675                 :             95 :         case USE_ISO_DATES:
                                676                 :                :             /* compatible with ISO date formats */
                                677         [ +  + ]:             95 :             if (tm->tm_year > 0)
                                678                 :             94 :                 sprintf(str, "%04d-%02d-%02d",
                                679                 :                :                         tm->tm_year, tm->tm_mon, tm->tm_mday);
                                680                 :                :             else
                                681                 :              1 :                 sprintf(str, "%04d-%02d-%02d %s",
 7318 bruce@momjian.us          682                 :              1 :                         -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
 8258 meskes@postgresql.or      683                 :             95 :             break;
                                684                 :                : 
 8258 meskes@postgresql.or      685                 :UBC           0 :         case USE_SQL_DATES:
                                686                 :                :             /* compatible with Oracle/Ingres date formats */
                                687         [ #  # ]:              0 :             if (EuroDates)
                                688                 :              0 :                 sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
                                689                 :                :             else
                                690                 :              0 :                 sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
                                691         [ #  # ]:              0 :             if (tm->tm_year > 0)
 7462 bruce@momjian.us          692                 :              0 :                 sprintf(str + 5, "/%04d", tm->tm_year);
                                693                 :                :             else
                                694                 :              0 :                 sprintf(str + 5, "/%04d %s", -(tm->tm_year - 1), "BC");
 8258 meskes@postgresql.or      695                 :              0 :             break;
                                696                 :                : 
                                697                 :              0 :         case USE_GERMAN_DATES:
                                698                 :                :             /* German-style date format */
                                699                 :              0 :             sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
                                700         [ #  # ]:              0 :             if (tm->tm_year > 0)
 7462 bruce@momjian.us          701                 :              0 :                 sprintf(str + 5, ".%04d", tm->tm_year);
                                702                 :                :             else
                                703                 :              0 :                 sprintf(str + 5, ".%04d %s", -(tm->tm_year - 1), "BC");
 8258 meskes@postgresql.or      704                 :              0 :             break;
                                705                 :                : 
                                706                 :              0 :         case USE_POSTGRES_DATES:
                                707                 :                :         default:
                                708                 :                :             /* traditional date-only style for Postgres */
                                709         [ #  # ]:              0 :             if (EuroDates)
                                710                 :              0 :                 sprintf(str, "%02d-%02d", tm->tm_mday, tm->tm_mon);
                                711                 :                :             else
                                712                 :              0 :                 sprintf(str, "%02d-%02d", tm->tm_mon, tm->tm_mday);
                                713         [ #  # ]:              0 :             if (tm->tm_year > 0)
 7462 bruce@momjian.us          714                 :              0 :                 sprintf(str + 5, "-%04d", tm->tm_year);
                                715                 :                :             else
                                716                 :              0 :                 sprintf(str + 5, "-%04d %s", -(tm->tm_year - 1), "BC");
 8258 meskes@postgresql.or      717                 :              0 :             break;
                                718                 :                :     }
 2969 peter_e@gmx.net           719                 :CBC          95 : }
                                720                 :                : 
                                721                 :                : void
 8258 meskes@postgresql.or      722                 :             34 : TrimTrailingZeros(char *str)
                                723                 :                : {
 8121 bruce@momjian.us          724                 :             34 :     int         len = strlen(str);
                                725                 :                : 
                                726                 :                :     /* chop off trailing zeros... but leave at least 2 fractional digits */
 7462                           727   [ +  +  +  - ]:             85 :     while (*(str + len - 1) == '0' && *(str + len - 3) != '.')
                                728                 :                :     {
 8121                           729                 :             51 :         len--;
                                730                 :             51 :         *(str + len) = '\0';
                                731                 :                :     }
 8258 meskes@postgresql.or      732                 :             34 : }
                                733                 :                : 
                                734                 :                : /* EncodeDateTime()
                                735                 :                :  * Encode date and time interpreted as local time.
                                736                 :                :  *
                                737                 :                :  * tm and fsec are the value to encode, print_tz determines whether to include
                                738                 :                :  * a time zone (the difference between timestamp and timestamptz types), tz is
                                739                 :                :  * the numeric time zone offset, tzn is the textual time zone, which if
                                740                 :                :  * specified will be used instead of tz by some styles, style is the date
                                741                 :                :  * style, str is where to write the output.
                                742                 :                :  *
                                743                 :                :  * Supported date styles:
                                744                 :                :  *  Postgres - day mon hh:mm:ss yyyy tz
                                745                 :                :  *  SQL - mm/dd/yyyy hh:mm:ss.ss tz
                                746                 :                :  *  ISO - yyyy-mm-dd hh:mm:ss+/-tz
                                747                 :                :  *  German - dd.mm.yyyy hh:mm:ss tz
                                748                 :                :  * Variants (affects order of month and day for Postgres and SQL styles):
                                749                 :                :  *  US - mm/dd/yyyy
                                750                 :                :  *  European - dd/mm/yyyy
                                751                 :                :  */
                                752                 :                : void
 3051 tgl@sss.pgh.pa.us         753                 :            159 : EncodeDateTime(struct tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str, bool EuroDates)
                                754                 :                : {
                                755                 :                :     int         day,
                                756                 :                :                 hour,
                                757                 :                :                 min;
                                758                 :                : 
                                759                 :                :     /*
                                760                 :                :      * Negative tm_isdst means we have no valid time zone translation.
                                761                 :                :      */
 4976 peter_e@gmx.net           762         [ +  - ]:            159 :     if (tm->tm_isdst < 0)
                                763                 :            159 :         print_tz = false;
                                764                 :                : 
 8258 meskes@postgresql.or      765   [ +  -  -  - ]:            159 :     switch (style)
                                766                 :                :     {
                                767                 :            159 :         case USE_ISO_DATES:
                                768                 :                :             /* Compatible with ISO-8601 date formats */
                                769                 :                : 
                                770                 :            159 :             sprintf(str, "%04d-%02d-%02d %02d:%02d",
 7318 bruce@momjian.us          771         [ +  + ]:            159 :                     (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
                                772                 :                :                     tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
                                773                 :                : 
                                774                 :                :             /*
                                775                 :                :              * Print fractional seconds if any.  The field widths here should
                                776                 :                :              * be at least equal to MAX_TIMESTAMP_PRECISION.
                                777                 :                :              */
 8258 meskes@postgresql.or      778         [ +  + ]:            159 :             if (fsec != 0)
                                779                 :                :             {
 7462 bruce@momjian.us          780                 :             34 :                 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
 8258 meskes@postgresql.or      781                 :             34 :                 TrimTrailingZeros(str);
                                782                 :                :             }
                                783                 :                :             else
 7462 bruce@momjian.us          784                 :            125 :                 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
                                785                 :                : 
 8258 meskes@postgresql.or      786         [ +  + ]:            159 :             if (tm->tm_year <= 0)
 7462 bruce@momjian.us          787                 :              5 :                 sprintf(str + strlen(str), " BC");
                                788                 :                : 
 4976 peter_e@gmx.net           789         [ -  + ]:            159 :             if (print_tz)
                                790                 :                :             {
 4976 peter_e@gmx.net           791                 :UBC           0 :                 hour = -(tz / SECS_PER_HOUR);
                                792                 :              0 :                 min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
 5613                           793         [ #  # ]:              0 :                 if (min != 0)
                                794                 :              0 :                     sprintf(str + strlen(str), "%+03d:%02d", hour, min);
                                795                 :                :                 else
                                796                 :              0 :                     sprintf(str + strlen(str), "%+03d", hour);
                                797                 :                :             }
 8258 meskes@postgresql.or      798                 :CBC         159 :             break;
                                799                 :                : 
 8258 meskes@postgresql.or      800                 :UBC           0 :         case USE_SQL_DATES:
                                801                 :                :             /* Compatible with Oracle/Ingres date formats */
                                802                 :                : 
                                803         [ #  # ]:              0 :             if (EuroDates)
                                804                 :              0 :                 sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
                                805                 :                :             else
                                806                 :              0 :                 sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
                                807                 :                : 
 7462 bruce@momjian.us          808                 :              0 :             sprintf(str + 5, "/%04d %02d:%02d",
 7318                           809         [ #  # ]:              0 :                     (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
                                810                 :                :                     tm->tm_hour, tm->tm_min);
                                811                 :                : 
                                812                 :                :             /*
                                813                 :                :              * Print fractional seconds if any.  The field widths here should
                                814                 :                :              * be at least equal to MAX_TIMESTAMP_PRECISION.
                                815                 :                :              */
 8258 meskes@postgresql.or      816         [ #  # ]:              0 :             if (fsec != 0)
                                817                 :                :             {
 7462 bruce@momjian.us          818                 :              0 :                 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
 8258 meskes@postgresql.or      819                 :              0 :                 TrimTrailingZeros(str);
                                820                 :                :             }
                                821                 :                :             else
 7462 bruce@momjian.us          822                 :              0 :                 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
                                823                 :                : 
 8258 meskes@postgresql.or      824         [ #  # ]:              0 :             if (tm->tm_year <= 0)
 7462 bruce@momjian.us          825                 :              0 :                 sprintf(str + strlen(str), " BC");
                                826                 :                : 
                                827                 :                :             /*
                                828                 :                :              * Note: the uses of %.*s in this function would be risky if the
                                829                 :                :              * timezone names ever contain non-ASCII characters, since we are
                                830                 :                :              * not being careful to do encoding-aware clipping.  However, all
                                831                 :                :              * TZ abbreviations in the IANA database are plain ASCII.
                                832                 :                :              */
                                833                 :                : 
 4976 peter_e@gmx.net           834         [ #  # ]:              0 :             if (print_tz)
                                835                 :                :             {
                                836         [ #  # ]:              0 :                 if (tzn)
                                837                 :              0 :                     sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                838                 :                :                 else
                                839                 :                :                 {
                                840                 :              0 :                     hour = -(tz / SECS_PER_HOUR);
                                841                 :              0 :                     min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
 5613                           842         [ #  # ]:              0 :                     if (min != 0)
                                843                 :              0 :                         sprintf(str + strlen(str), "%+03d:%02d", hour, min);
                                844                 :                :                     else
                                845                 :              0 :                         sprintf(str + strlen(str), "%+03d", hour);
                                846                 :                :                 }
                                847                 :                :             }
 8258 meskes@postgresql.or      848                 :              0 :             break;
                                849                 :                : 
                                850                 :              0 :         case USE_GERMAN_DATES:
                                851                 :                :             /* German variant on European style */
                                852                 :                : 
                                853                 :              0 :             sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
                                854                 :                : 
 7462 bruce@momjian.us          855                 :              0 :             sprintf(str + 5, ".%04d %02d:%02d",
 7318                           856         [ #  # ]:              0 :                     (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
                                857                 :                :                     tm->tm_hour, tm->tm_min);
                                858                 :                : 
                                859                 :                :             /*
                                860                 :                :              * Print fractional seconds if any.  The field widths here should
                                861                 :                :              * be at least equal to MAX_TIMESTAMP_PRECISION.
                                862                 :                :              */
 8258 meskes@postgresql.or      863         [ #  # ]:              0 :             if (fsec != 0)
                                864                 :                :             {
 7462 bruce@momjian.us          865                 :              0 :                 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
 8258 meskes@postgresql.or      866                 :              0 :                 TrimTrailingZeros(str);
                                867                 :                :             }
                                868                 :                :             else
 7462 bruce@momjian.us          869                 :              0 :                 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
                                870                 :                : 
 8258 meskes@postgresql.or      871         [ #  # ]:              0 :             if (tm->tm_year <= 0)
 7462 bruce@momjian.us          872                 :              0 :                 sprintf(str + strlen(str), " BC");
                                873                 :                : 
 4976 peter_e@gmx.net           874         [ #  # ]:              0 :             if (print_tz)
                                875                 :                :             {
                                876         [ #  # ]:              0 :                 if (tzn)
                                877                 :              0 :                     sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                878                 :                :                 else
                                879                 :                :                 {
                                880                 :              0 :                     hour = -(tz / SECS_PER_HOUR);
                                881                 :              0 :                     min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
 5613                           882         [ #  # ]:              0 :                     if (min != 0)
                                883                 :              0 :                         sprintf(str + strlen(str), "%+03d:%02d", hour, min);
                                884                 :                :                     else
                                885                 :              0 :                         sprintf(str + strlen(str), "%+03d", hour);
                                886                 :                :                 }
                                887                 :                :             }
 8258 meskes@postgresql.or      888                 :              0 :             break;
                                889                 :                : 
                                890                 :              0 :         case USE_POSTGRES_DATES:
                                891                 :                :         default:
                                892                 :                :             /* Backward-compatible with traditional Postgres abstime dates */
                                893                 :                : 
                                894                 :              0 :             day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
 8059                           895                 :              0 :             tm->tm_wday = (int) ((day + date2j(2000, 1, 1) + 1) % 7);
                                896                 :                : 
 3930 tgl@sss.pgh.pa.us         897                 :              0 :             memcpy(str, days[tm->tm_wday], 3);
 7462 bruce@momjian.us          898                 :              0 :             strcpy(str + 3, " ");
                                899                 :                : 
 8258 meskes@postgresql.or      900         [ #  # ]:              0 :             if (EuroDates)
 7462 bruce@momjian.us          901                 :              0 :                 sprintf(str + 4, "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]);
                                902                 :                :             else
                                903                 :              0 :                 sprintf(str + 4, "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday);
                                904                 :                : 
                                905                 :              0 :             sprintf(str + 10, " %02d:%02d", tm->tm_hour, tm->tm_min);
                                906                 :                : 
                                907                 :                :             /*
                                908                 :                :              * Print fractional seconds if any.  The field widths here should
                                909                 :                :              * be at least equal to MAX_TIMESTAMP_PRECISION.
                                910                 :                :              */
 8258 meskes@postgresql.or      911         [ #  # ]:              0 :             if (fsec != 0)
                                912                 :                :             {
 7462 bruce@momjian.us          913                 :              0 :                 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
 8258 meskes@postgresql.or      914                 :              0 :                 TrimTrailingZeros(str);
                                915                 :                :             }
                                916                 :                :             else
 7462 bruce@momjian.us          917                 :              0 :                 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
                                918                 :                : 
                                919                 :              0 :             sprintf(str + strlen(str), " %04d",
 7318                           920         [ #  # ]:              0 :                     (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1));
 8258 meskes@postgresql.or      921         [ #  # ]:              0 :             if (tm->tm_year <= 0)
 7462 bruce@momjian.us          922                 :              0 :                 sprintf(str + strlen(str), " BC");
                                923                 :                : 
 4976 peter_e@gmx.net           924         [ #  # ]:              0 :             if (print_tz)
                                925                 :                :             {
                                926         [ #  # ]:              0 :                 if (tzn)
                                927                 :              0 :                     sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
                                928                 :                :                 else
                                929                 :                :                 {
                                930                 :                :                     /*
                                931                 :                :                      * We have a time zone, but no string version. Use the
                                932                 :                :                      * numeric form, but be sure to include a leading space to
                                933                 :                :                      * avoid formatting something which would be rejected by
                                934                 :                :                      * the date/time parser later. - thomas 2001-10-19
                                935                 :                :                      */
                                936                 :              0 :                     hour = -(tz / SECS_PER_HOUR);
                                937                 :              0 :                     min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
 5613                           938         [ #  # ]:              0 :                     if (min != 0)
                                939                 :              0 :                         sprintf(str + strlen(str), " %+03d:%02d", hour, min);
                                940                 :                :                     else
                                941                 :              0 :                         sprintf(str + strlen(str), " %+03d", hour);
                                942                 :                :                 }
                                943                 :                :             }
 8258 meskes@postgresql.or      944                 :              0 :             break;
                                945                 :                :     }
 2969 peter_e@gmx.net           946                 :CBC         159 : }
                                947                 :                : 
                                948                 :                : int
 3051 tgl@sss.pgh.pa.us         949                 :UBC           0 : GetEpochTime(struct tm *tm)
                                950                 :                : {
                                951                 :                :     struct tm  *t0;
                                952                 :                :     struct tm   tmbuf;
 8258 meskes@postgresql.or      953                 :              0 :     time_t      epoch = 0;
                                954                 :                : 
  431 peter@eisentraut.org      955                 :              0 :     t0 = gmtime_r(&epoch, &tmbuf);
                                956                 :                : 
 6110 meskes@postgresql.or      957         [ #  # ]:              0 :     if (t0)
                                958                 :                :     {
                                959                 :              0 :         tm->tm_year = t0->tm_year + 1900;
                                960                 :              0 :         tm->tm_mon = t0->tm_mon + 1;
                                961                 :              0 :         tm->tm_mday = t0->tm_mday;
                                962                 :              0 :         tm->tm_hour = t0->tm_hour;
                                963                 :              0 :         tm->tm_min = t0->tm_min;
                                964                 :              0 :         tm->tm_sec = t0->tm_sec;
                                965                 :                : 
                                966                 :              0 :         return 0;
                                967                 :                :     }
                                968                 :                : 
                                969                 :              0 :     return -1;
                                970                 :                : }                               /* GetEpochTime() */
                                971                 :                : 
                                972                 :                : static void
 3051 tgl@sss.pgh.pa.us         973                 :CBC           1 : abstime2tm(AbsoluteTime _time, int *tzp, struct tm *tm, char **tzn)
                                974                 :                : {
 8258 meskes@postgresql.or      975                 :              1 :     time_t      time = (time_t) _time;
                                976                 :                :     struct tm  *tx;
                                977                 :                :     struct tm   tmbuf;
                                978                 :                : 
 6110                           979                 :              1 :     errno = 0;
 8258                           980         [ +  - ]:              1 :     if (tzp != NULL)
  431 peter@eisentraut.org      981                 :              1 :         tx = localtime_r(&time, &tmbuf);
                                982                 :                :     else
  431 peter@eisentraut.org      983                 :UBC           0 :         tx = gmtime_r(&time, &tmbuf);
                                984                 :                : 
 6110 meskes@postgresql.or      985         [ -  + ]:CBC           1 :     if (!tx)
                                986                 :                :     {
 6110 meskes@postgresql.or      987                 :UBC           0 :         errno = PGTYPES_TS_BAD_TIMESTAMP;
                                988                 :              0 :         return;
                                989                 :                :     }
                                990                 :                : 
 8258 meskes@postgresql.or      991                 :CBC           1 :     tm->tm_year = tx->tm_year + 1900;
                                992                 :              1 :     tm->tm_mon = tx->tm_mon + 1;
                                993                 :              1 :     tm->tm_mday = tx->tm_mday;
                                994                 :              1 :     tm->tm_hour = tx->tm_hour;
                                995                 :              1 :     tm->tm_min = tx->tm_min;
                                996                 :              1 :     tm->tm_sec = tx->tm_sec;
                                997                 :              1 :     tm->tm_isdst = tx->tm_isdst;
                                998                 :                : 
                                999                 :                : #if defined(HAVE_STRUCT_TM_TM_ZONE)
                               1000                 :              1 :     tm->tm_gmtoff = tx->tm_gmtoff;
                               1001                 :              1 :     tm->tm_zone = tx->tm_zone;
                               1002                 :                : 
                               1003         [ +  - ]:              1 :     if (tzp != NULL)
                               1004                 :                :     {
                               1005                 :                :         /*
                               1006                 :                :          * We have a brute force time zone per SQL99? Then use it without
                               1007                 :                :          * change since we have already rotated to the time zone.
                               1008                 :                :          */
 8121 bruce@momjian.us         1009                 :              1 :         *tzp = -tm->tm_gmtoff;   /* tm_gmtoff is Sun/DEC-ism */
                               1010                 :                : 
                               1011                 :                :         /*
                               1012                 :                :          * FreeBSD man pages indicate that this should work - tgl 97/04/23
                               1013                 :                :          */
 8258 meskes@postgresql.or     1014         [ -  + ]:              1 :         if (tzn != NULL)
                               1015                 :                :         {
                               1016                 :                :             /*
                               1017                 :                :              * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
                               1018                 :                :              * contains an error message, which doesn't fit in the buffer
                               1019                 :                :              */
 1905 peter@eisentraut.org     1020                 :UBC           0 :             strlcpy(*tzn, tm->tm_zone, MAXTZLEN + 1);
 8121 bruce@momjian.us         1021         [ #  # ]:              0 :             if (strlen(tm->tm_zone) > MAXTZLEN)
                               1022                 :              0 :                 tm->tm_isdst = -1;
                               1023                 :                :         }
                               1024                 :                :     }
                               1025                 :                :     else
 8258 meskes@postgresql.or     1026                 :              0 :         tm->tm_isdst = -1;
                               1027                 :                : #elif defined(HAVE_INT_TIMEZONE)
                               1028                 :                :     if (tzp != NULL)
                               1029                 :                :     {
                               1030                 :                :         *tzp = (tm->tm_isdst > 0) ? TIMEZONE_GLOBAL - SECS_PER_HOUR : TIMEZONE_GLOBAL;
                               1031                 :                : 
                               1032                 :                :         if (tzn != NULL)
                               1033                 :                :         {
                               1034                 :                :             /*
                               1035                 :                :              * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it
                               1036                 :                :              * contains an error message, which doesn't fit in the buffer
                               1037                 :                :              */
                               1038                 :                :             strlcpy(*tzn, TZNAME_GLOBAL[tm->tm_isdst], MAXTZLEN + 1);
                               1039                 :                :             if (strlen(TZNAME_GLOBAL[tm->tm_isdst]) > MAXTZLEN)
                               1040                 :                :                 tm->tm_isdst = -1;
                               1041                 :                :         }
                               1042                 :                :     }
                               1043                 :                :     else
                               1044                 :                :         tm->tm_isdst = -1;
                               1045                 :                : #else                           /* not (HAVE_STRUCT_TM_TM_ZONE ||
                               1046                 :                :                                  * HAVE_INT_TIMEZONE) */
                               1047                 :                :     if (tzp != NULL)
                               1048                 :                :     {
                               1049                 :                :         /* default to UTC */
                               1050                 :                :         *tzp = 0;
                               1051                 :                :         if (tzn != NULL)
                               1052                 :                :             *tzn = NULL;
                               1053                 :                :     }
                               1054                 :                :     else
                               1055                 :                :         tm->tm_isdst = -1;
                               1056                 :                : #endif
                               1057                 :                : }
                               1058                 :                : 
                               1059                 :                : void
 3051 tgl@sss.pgh.pa.us        1060                 :CBC           1 : GetCurrentDateTime(struct tm *tm)
                               1061                 :                : {
                               1062                 :                :     int         tz;
                               1063                 :                : 
 8258 meskes@postgresql.or     1064                 :              1 :     abstime2tm(time(NULL), &tz, tm, NULL);
                               1065                 :              1 : }
                               1066                 :                : 
                               1067                 :                : void
                               1068                 :            164 : dt2time(double jd, int *hour, int *min, int *sec, fsec_t *fsec)
                               1069                 :                : {
                               1070                 :                :     int64       time;
                               1071                 :                : 
                               1072                 :            164 :     time = jd;
 7462 bruce@momjian.us         1073                 :            164 :     *hour = time / USECS_PER_HOUR;
                               1074                 :            164 :     time -= (*hour) * USECS_PER_HOUR;
                               1075                 :            164 :     *min = time / USECS_PER_MINUTE;
                               1076                 :            164 :     time -= (*min) * USECS_PER_MINUTE;
                               1077                 :            164 :     *sec = time / USECS_PER_SEC;
                               1078                 :            164 :     *fsec = time - (*sec * USECS_PER_SEC);
 3051 tgl@sss.pgh.pa.us        1079                 :            164 : }                               /* dt2time() */
                               1080                 :                : 
                               1081                 :                : 
                               1082                 :                : 
                               1083                 :                : /* DecodeNumberField()
                               1084                 :                :  * Interpret numeric string as a concatenated date or time field.
                               1085                 :                :  * Use the context of previously decoded fields to help with
                               1086                 :                :  * the interpretation.
                               1087                 :                :  */
                               1088                 :                : static int
 8258 meskes@postgresql.or     1089                 :             15 : DecodeNumberField(int len, char *str, int fmask,
                               1090                 :                :                   int *tmask, struct tm *tm, fsec_t *fsec, bool *is2digits)
                               1091                 :                : {
                               1092                 :                :     char       *cp;
                               1093                 :                : 
                               1094                 :                :     /*
                               1095                 :                :      * Have a decimal point? Then this is a date or something with a seconds
                               1096                 :                :      * field...
                               1097                 :                :      */
                               1098         [ -  + ]:             15 :     if ((cp = strchr(str, '.')) != NULL)
                               1099                 :                :     {
                               1100                 :                :         char        fstr[7];
                               1101                 :                :         int         i;
                               1102                 :                : 
 4271 noah@leadboat.com        1103                 :UBC           0 :         cp++;
                               1104                 :                : 
                               1105                 :                :         /*
                               1106                 :                :          * OK, we have at most six digits to care about. Let's construct a
                               1107                 :                :          * string with those digits, zero-padded on the right, and then do the
                               1108                 :                :          * conversion to an integer.
                               1109                 :                :          *
                               1110                 :                :          * XXX This truncates the seventh digit, unlike rounding it as the
                               1111                 :                :          * backend does.
                               1112                 :                :          */
                               1113         [ #  # ]:              0 :         for (i = 0; i < 6; i++)
                               1114         [ #  # ]:              0 :             fstr[i] = *cp != '\0' ? *cp++ : '0';
                               1115                 :              0 :         fstr[i] = '\0';
 2310 meskes@postgresql.or     1116                 :              0 :         *fsec = strtoint(fstr, NULL, 10);
 8258                          1117                 :              0 :         *cp = '\0';
                               1118                 :              0 :         len = strlen(str);
                               1119                 :                :     }
                               1120                 :                :     /* No decimal point and no complete date yet? */
 8258 meskes@postgresql.or     1121         [ +  - ]:CBC          15 :     else if ((fmask & DTK_DATE_M) != DTK_DATE_M)
                               1122                 :                :     {
                               1123                 :                :         /* yyyymmdd? */
                               1124         [ +  + ]:             15 :         if (len == 8)
                               1125                 :                :         {
                               1126                 :              9 :             *tmask = DTK_DATE_M;
                               1127                 :                : 
                               1128                 :              9 :             tm->tm_mday = atoi(str + 6);
                               1129                 :              9 :             *(str + 6) = '\0';
                               1130                 :              9 :             tm->tm_mon = atoi(str + 4);
                               1131                 :              9 :             *(str + 4) = '\0';
                               1132                 :              9 :             tm->tm_year = atoi(str + 0);
                               1133                 :                : 
                               1134                 :              9 :             return DTK_DATE;
                               1135                 :                :         }
                               1136                 :                :         /* yymmdd? */
                               1137         [ +  - ]:              6 :         else if (len == 6)
                               1138                 :                :         {
                               1139                 :              6 :             *tmask = DTK_DATE_M;
                               1140                 :              6 :             tm->tm_mday = atoi(str + 4);
                               1141                 :              6 :             *(str + 4) = '\0';
                               1142                 :              6 :             tm->tm_mon = atoi(str + 2);
                               1143                 :              6 :             *(str + 2) = '\0';
                               1144                 :              6 :             tm->tm_year = atoi(str + 0);
 2995 peter_e@gmx.net          1145                 :              6 :             *is2digits = true;
                               1146                 :                : 
 8258 meskes@postgresql.or     1147                 :              6 :             return DTK_DATE;
                               1148                 :                :         }
                               1149                 :                :         /* yyddd? */
 8258 meskes@postgresql.or     1150         [ #  # ]:UBC           0 :         else if (len == 5)
                               1151                 :                :         {
                               1152                 :              0 :             *tmask = DTK_DATE_M;
                               1153                 :              0 :             tm->tm_mday = atoi(str + 2);
                               1154                 :              0 :             *(str + 2) = '\0';
                               1155                 :              0 :             tm->tm_mon = 1;
                               1156                 :              0 :             tm->tm_year = atoi(str + 0);
 2995 peter_e@gmx.net          1157                 :              0 :             *is2digits = true;
                               1158                 :                : 
 8258 meskes@postgresql.or     1159                 :              0 :             return DTK_DATE;
                               1160                 :                :         }
                               1161                 :                :     }
                               1162                 :                : 
                               1163                 :                :     /* not all time fields are specified? */
                               1164         [ #  # ]:              0 :     if ((fmask & DTK_TIME_M) != DTK_TIME_M)
                               1165                 :                :     {
                               1166                 :                :         /* hhmmss */
                               1167         [ #  # ]:              0 :         if (len == 6)
                               1168                 :                :         {
                               1169                 :              0 :             *tmask = DTK_TIME_M;
                               1170                 :              0 :             tm->tm_sec = atoi(str + 4);
                               1171                 :              0 :             *(str + 4) = '\0';
                               1172                 :              0 :             tm->tm_min = atoi(str + 2);
                               1173                 :              0 :             *(str + 2) = '\0';
                               1174                 :              0 :             tm->tm_hour = atoi(str + 0);
                               1175                 :                : 
                               1176                 :              0 :             return DTK_TIME;
                               1177                 :                :         }
                               1178                 :                :         /* hhmm? */
                               1179         [ #  # ]:              0 :         else if (len == 4)
                               1180                 :                :         {
                               1181                 :              0 :             *tmask = DTK_TIME_M;
                               1182                 :              0 :             tm->tm_sec = 0;
                               1183                 :              0 :             tm->tm_min = atoi(str + 2);
                               1184                 :              0 :             *(str + 2) = '\0';
                               1185                 :              0 :             tm->tm_hour = atoi(str + 0);
                               1186                 :                : 
                               1187                 :              0 :             return DTK_TIME;
                               1188                 :                :         }
                               1189                 :                :     }
                               1190                 :                : 
                               1191                 :              0 :     return -1;
                               1192                 :                : }                               /* DecodeNumberField() */
                               1193                 :                : 
                               1194                 :                : 
                               1195                 :                : /* DecodeNumber()
                               1196                 :                :  * Interpret plain numeric field as a date value in context.
                               1197                 :                :  */
                               1198                 :                : static int
 8258 meskes@postgresql.or     1199                 :CBC         398 : DecodeNumber(int flen, char *str, int fmask,
                               1200                 :                :              int *tmask, struct tm *tm, fsec_t *fsec, bool *is2digits, bool EuroDates)
                               1201                 :                : {
                               1202                 :                :     int         val;
                               1203                 :                :     char       *cp;
                               1204                 :                : 
                               1205                 :            398 :     *tmask = 0;
                               1206                 :                : 
 2310                          1207                 :            398 :     val = strtoint(str, &cp, 10);
 8258                          1208         [ -  + ]:            398 :     if (cp == str)
 8258 meskes@postgresql.or     1209                 :UBC           0 :         return -1;
                               1210                 :                : 
 8258 meskes@postgresql.or     1211         [ -  + ]:CBC         398 :     if (*cp == '.')
                               1212                 :                :     {
                               1213                 :                :         /*
                               1214                 :                :          * More than two digits? Then could be a date or a run-together time:
                               1215                 :                :          * 2001.360 20011225 040506.789
                               1216                 :                :          */
 7462 bruce@momjian.us         1217         [ #  # ]:UBC           0 :         if (cp - str > 2)
 8258 meskes@postgresql.or     1218                 :              0 :             return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),
                               1219                 :                :                                      tmask, tm, fsec, is2digits);
                               1220                 :                : 
  214 peter@eisentraut.org     1221                 :              0 :         *fsec = strtod(cp, &cp);
 8258 meskes@postgresql.or     1222         [ #  # ]:              0 :         if (*cp != '\0')
                               1223                 :              0 :             return -1;
                               1224                 :                :     }
 8258 meskes@postgresql.or     1225         [ -  + ]:CBC         398 :     else if (*cp != '\0')
 8258 meskes@postgresql.or     1226                 :UBC           0 :         return -1;
                               1227                 :                : 
                               1228                 :                :     /* Special case day of year? */
 7462 bruce@momjian.us         1229   [ +  +  +  -  :CBC         398 :     if (flen == 3 && (fmask & DTK_M(YEAR)) && val >= 1 && val <= 366)
                                        +  -  +  - ]
                               1230                 :                :     {
 8258 meskes@postgresql.or     1231                 :              6 :         *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY));
                               1232                 :              6 :         tm->tm_yday = val;
 7462 bruce@momjian.us         1233                 :              6 :         j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,
                               1234                 :                :                &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
                               1235                 :                :     }
                               1236                 :                : 
                               1237                 :                :     /***
                               1238                 :                :      * Enough digits to be unequivocal year? Used to test for 4 digits or
                               1239                 :                :      * more, but we now test first for a three-digit doy so anything
                               1240                 :                :      * bigger than two digits had better be an explicit year.
                               1241                 :                :      * - thomas 1999-01-09
                               1242                 :                :      * Back to requiring a 4 digit year. We accept a two digit
                               1243                 :                :      * year farther down. - thomas 2000-03-28
                               1244                 :                :      ***/
 8258 meskes@postgresql.or     1245         [ +  + ]:            392 :     else if (flen >= 4)
                               1246                 :                :     {
                               1247                 :            120 :         *tmask = DTK_M(YEAR);
                               1248                 :                : 
                               1249                 :                :         /* already have a year? then see if we can substitute... */
 7462 bruce@momjian.us         1250   [ -  +  -  - ]:            120 :         if ((fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)) &&
 7462 bruce@momjian.us         1251   [ #  #  #  # ]:UBC           0 :             tm->tm_year >= 1 && tm->tm_year <= 31)
                               1252                 :                :         {
 8258 meskes@postgresql.or     1253                 :              0 :             tm->tm_mday = tm->tm_year;
                               1254                 :              0 :             *tmask = DTK_M(DAY);
                               1255                 :                :         }
                               1256                 :                : 
 8258 meskes@postgresql.or     1257                 :CBC         120 :         tm->tm_year = val;
                               1258                 :                :     }
                               1259                 :                : 
                               1260                 :                :     /* already have year? then could be month */
 7404 bruce@momjian.us         1261   [ +  +  +  +  :            272 :     else if ((fmask & DTK_M(YEAR)) && !(fmask & DTK_M(MONTH)) && val >= 1 && val <= MONTHS_PER_YEAR)
                                        +  -  +  - ]
                               1262                 :                :     {
 8258 meskes@postgresql.or     1263                 :             56 :         *tmask = DTK_M(MONTH);
                               1264                 :             56 :         tm->tm_mon = val;
                               1265                 :                :     }
                               1266                 :                :     /* no year and EuroDates enabled? then could be day */
 7462 bruce@momjian.us         1267   [ +  -  +  + ]:            216 :     else if ((EuroDates || (fmask & DTK_M(MONTH))) &&
 7318                          1268   [ +  +  +  +  :            185 :              !(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)) &&
                                              +  - ]
                               1269         [ +  + ]:             87 :              val >= 1 && val <= 31)
                               1270                 :                :     {
 8258 meskes@postgresql.or     1271                 :             81 :         *tmask = DTK_M(DAY);
                               1272                 :             81 :         tm->tm_mday = val;
                               1273                 :                :     }
 7404 bruce@momjian.us         1274   [ +  +  +  -  :            135 :     else if (!(fmask & DTK_M(MONTH)) && val >= 1 && val <= MONTHS_PER_YEAR)
                                              +  + ]
                               1275                 :                :     {
 8258 meskes@postgresql.or     1276                 :             30 :         *tmask = DTK_M(MONTH);
                               1277                 :             30 :         tm->tm_mon = val;
                               1278                 :                :     }
 7462 bruce@momjian.us         1279   [ +  +  +  -  :            105 :     else if (!(fmask & DTK_M(DAY)) && val >= 1 && val <= 31)
                                              +  + ]
                               1280                 :                :     {
 8258 meskes@postgresql.or     1281                 :             68 :         *tmask = DTK_M(DAY);
                               1282                 :             68 :         tm->tm_mday = val;
                               1283                 :                :     }
                               1284                 :                : 
                               1285                 :                :     /*
                               1286                 :                :      * Check for 2 or 4 or more digits, but currently we reach here only if
                               1287                 :                :      * two digits. - thomas 2000-03-28
                               1288                 :                :      */
 7462 bruce@momjian.us         1289   [ +  -  +  -  :             37 :     else if (!(fmask & DTK_M(YEAR)) && (flen >= 4 || flen == 2))
                                              +  - ]
                               1290                 :                :     {
 8258 meskes@postgresql.or     1291                 :             37 :         *tmask = DTK_M(YEAR);
                               1292                 :             37 :         tm->tm_year = val;
                               1293                 :                : 
                               1294                 :                :         /* adjust ONLY if exactly two digits... */
                               1295                 :             37 :         *is2digits = (flen == 2);
                               1296                 :                :     }
                               1297                 :                :     else
 8258 meskes@postgresql.or     1298                 :UBC           0 :         return -1;
                               1299                 :                : 
 8258 meskes@postgresql.or     1300                 :CBC         398 :     return 0;
                               1301                 :                : }                               /* DecodeNumber() */
                               1302                 :                : 
                               1303                 :                : /* DecodeDate()
                               1304                 :                :  * Decode date string which includes delimiters.
                               1305                 :                :  * Insist on a complete set of fields.
                               1306                 :                :  */
                               1307                 :                : static int
 3051 tgl@sss.pgh.pa.us        1308                 :            133 : DecodeDate(char *str, int fmask, int *tmask, struct tm *tm, bool EuroDates)
                               1309                 :                : {
                               1310                 :                :     fsec_t      fsec;
                               1311                 :                : 
 8258 meskes@postgresql.or     1312                 :            133 :     int         nf = 0;
                               1313                 :                :     int         i,
                               1314                 :                :                 len;
 2995 peter_e@gmx.net          1315                 :            133 :     bool        bc = false;
                               1316                 :            133 :     bool        is2digits = false;
                               1317                 :                :     int         type,
                               1318                 :                :                 val,
 8258 meskes@postgresql.or     1319                 :            133 :                 dmask = 0;
                               1320                 :                :     char       *field[MAXDATEFIELDS];
                               1321                 :                : 
                               1322                 :                :     /* parse this string... */
 7462 bruce@momjian.us         1323   [ +  +  +  - ]:            524 :     while (*str != '\0' && nf < MAXDATEFIELDS)
                               1324                 :                :     {
                               1325                 :                :         /* skip field separators */
 8258 meskes@postgresql.or     1326         [ +  + ]:            439 :         while (!isalnum((unsigned char) *str))
                               1327                 :             48 :             str++;
                               1328                 :                : 
                               1329                 :            391 :         field[nf] = str;
                               1330         [ +  + ]:            391 :         if (isdigit((unsigned char) *str))
                               1331                 :                :         {
                               1332         [ +  + ]:           1203 :             while (isdigit((unsigned char) *str))
                               1333                 :            855 :                 str++;
                               1334                 :                :         }
                               1335         [ +  - ]:             43 :         else if (isalpha((unsigned char) *str))
                               1336                 :                :         {
                               1337         [ +  + ]:            273 :             while (isalpha((unsigned char) *str))
                               1338                 :            230 :                 str++;
                               1339                 :                :         }
                               1340                 :                : 
                               1341                 :                :         /* Just get rid of any non-digit, non-alpha characters... */
                               1342         [ +  + ]:            391 :         if (*str != '\0')
                               1343                 :            258 :             *str++ = '\0';
                               1344                 :            391 :         nf++;
                               1345                 :                :     }
                               1346                 :                : 
                               1347                 :                : #if 0
                               1348                 :                :     /* don't allow too many fields */
                               1349                 :                :     if (nf > 3)
                               1350                 :                :         return -1;
                               1351                 :                : #endif
                               1352                 :                : 
                               1353                 :            133 :     *tmask = 0;
                               1354                 :                : 
                               1355                 :                :     /* look first for text fields, since that will be unambiguous month */
                               1356         [ +  + ]:            523 :     for (i = 0; i < nf; i++)
                               1357                 :                :     {
                               1358         [ +  + ]:            391 :         if (isalpha((unsigned char) *field[i]))
                               1359                 :                :         {
                               1360                 :             43 :             type = DecodeSpecial(i, field[i], &val);
                               1361         [ -  + ]:             43 :             if (type == IGNORE_DTF)
 8258 meskes@postgresql.or     1362                 :UBC           0 :                 continue;
                               1363                 :                : 
 8258 meskes@postgresql.or     1364                 :CBC          43 :             dmask = DTK_M(type);
                               1365      [ +  -  + ]:             43 :             switch (type)
                               1366                 :                :             {
                               1367                 :             42 :                 case MONTH:
                               1368                 :             42 :                     tm->tm_mon = val;
                               1369                 :             42 :                     break;
                               1370                 :                : 
 8258 meskes@postgresql.or     1371                 :UBC           0 :                 case ADBC:
                               1372                 :              0 :                     bc = (val == BC);
                               1373                 :              0 :                     break;
                               1374                 :                : 
 8258 meskes@postgresql.or     1375                 :CBC           1 :                 default:
                               1376                 :              1 :                     return -1;
                               1377                 :                :             }
                               1378         [ -  + ]:             42 :             if (fmask & dmask)
 8258 meskes@postgresql.or     1379                 :UBC           0 :                 return -1;
                               1380                 :                : 
 8258 meskes@postgresql.or     1381                 :CBC          42 :             fmask |= dmask;
                               1382                 :             42 :             *tmask |= dmask;
                               1383                 :                : 
                               1384                 :                :             /* mark this field as being completed */
                               1385                 :             42 :             field[i] = NULL;
                               1386                 :                :         }
                               1387                 :                :     }
                               1388                 :                : 
                               1389                 :                :     /* now pick up remaining numeric fields */
                               1390         [ +  + ]:            522 :     for (i = 0; i < nf; i++)
                               1391                 :                :     {
                               1392         [ +  + ]:            390 :         if (field[i] == NULL)
                               1393                 :             42 :             continue;
                               1394                 :                : 
                               1395         [ -  + ]:            348 :         if ((len = strlen(field[i])) <= 0)
 8258 meskes@postgresql.or     1396                 :UBC           0 :             return -1;
                               1397                 :                : 
 8258 meskes@postgresql.or     1398         [ -  + ]:CBC         348 :         if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec, &is2digits, EuroDates) != 0)
 8258 meskes@postgresql.or     1399                 :UBC           0 :             return -1;
                               1400                 :                : 
 8258 meskes@postgresql.or     1401         [ -  + ]:CBC         348 :         if (fmask & dmask)
 8258 meskes@postgresql.or     1402                 :UBC           0 :             return -1;
                               1403                 :                : 
 8258 meskes@postgresql.or     1404                 :CBC         348 :         fmask |= dmask;
                               1405                 :            348 :         *tmask |= dmask;
                               1406                 :                :     }
                               1407                 :                : 
                               1408         [ -  + ]:            132 :     if ((fmask & ~(DTK_M(DOY) | DTK_M(TZ))) != DTK_DATE_M)
 8258 meskes@postgresql.or     1409                 :UBC           0 :         return -1;
                               1410                 :                : 
                               1411                 :                :     /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */
 8258 meskes@postgresql.or     1412         [ -  + ]:CBC         132 :     if (bc)
                               1413                 :                :     {
 8258 meskes@postgresql.or     1414         [ #  # ]:UBC           0 :         if (tm->tm_year > 0)
                               1415                 :              0 :             tm->tm_year = -(tm->tm_year - 1);
                               1416                 :                :         else
                               1417                 :              0 :             return -1;
                               1418                 :                :     }
 8258 meskes@postgresql.or     1419         [ +  + ]:CBC         132 :     else if (is2digits)
                               1420                 :                :     {
                               1421         [ +  + ]:             31 :         if (tm->tm_year < 70)
                               1422                 :             12 :             tm->tm_year += 2000;
                               1423         [ +  - ]:             19 :         else if (tm->tm_year < 100)
                               1424                 :             19 :             tm->tm_year += 1900;
                               1425                 :                :     }
                               1426                 :                : 
                               1427                 :            132 :     return 0;
                               1428                 :                : }                               /* DecodeDate() */
                               1429                 :                : 
                               1430                 :                : 
                               1431                 :                : /* DecodeTime()
                               1432                 :                :  * Decode time string which includes delimiters.
                               1433                 :                :  * Only check the lower limit on hours, since this same code
                               1434                 :                :  *  can be used to represent time spans.
                               1435                 :                :  */
                               1436                 :                : int
 3051 tgl@sss.pgh.pa.us        1437                 :            125 : DecodeTime(char *str, int *tmask, struct tm *tm, fsec_t *fsec)
                               1438                 :                : {
                               1439                 :                :     char       *cp;
                               1440                 :                : 
 8258 meskes@postgresql.or     1441                 :            125 :     *tmask = DTK_TIME_M;
                               1442                 :                : 
 2310                          1443                 :            125 :     tm->tm_hour = strtoint(str, &cp, 10);
 8258                          1444         [ -  + ]:            125 :     if (*cp != ':')
 8258 meskes@postgresql.or     1445                 :UBC           0 :         return -1;
 8258 meskes@postgresql.or     1446                 :CBC         125 :     str = cp + 1;
 2310                          1447                 :            125 :     tm->tm_min = strtoint(str, &cp, 10);
 8258                          1448         [ +  + ]:            125 :     if (*cp == '\0')
                               1449                 :                :     {
                               1450                 :             34 :         tm->tm_sec = 0;
                               1451                 :             34 :         *fsec = 0;
                               1452                 :                :     }
                               1453         [ -  + ]:             91 :     else if (*cp != ':')
 8258 meskes@postgresql.or     1454                 :UBC           0 :         return -1;
                               1455                 :                :     else
                               1456                 :                :     {
 8258 meskes@postgresql.or     1457                 :CBC          91 :         str = cp + 1;
 2310                          1458                 :             91 :         tm->tm_sec = strtoint(str, &cp, 10);
 8258                          1459         [ +  + ]:             91 :         if (*cp == '\0')
                               1460                 :             57 :             *fsec = 0;
                               1461         [ +  - ]:             34 :         else if (*cp == '.')
                               1462                 :                :         {
                               1463                 :                :             char        fstr[7];
                               1464                 :                :             int         i;
                               1465                 :                : 
 4271 noah@leadboat.com        1466                 :             34 :             cp++;
                               1467                 :                : 
                               1468                 :                :             /*
                               1469                 :                :              * OK, we have at most six digits to care about. Let's construct a
                               1470                 :                :              * string with those digits, zero-padded on the right, and then do
                               1471                 :                :              * the conversion to an integer.
                               1472                 :                :              *
                               1473                 :                :              * XXX This truncates the seventh digit, unlike rounding it as the
                               1474                 :                :              * backend does.
                               1475                 :                :              */
                               1476         [ +  + ]:            238 :             for (i = 0; i < 6; i++)
                               1477         [ +  + ]:            204 :                 fstr[i] = *cp != '\0' ? *cp++ : '0';
                               1478                 :             34 :             fstr[i] = '\0';
 2310 meskes@postgresql.or     1479                 :             34 :             *fsec = strtoint(fstr, &cp, 10);
 8258                          1480         [ -  + ]:             34 :             if (*cp != '\0')
 8258 meskes@postgresql.or     1481                 :UBC           0 :                 return -1;
                               1482                 :                :         }
                               1483                 :                :         else
                               1484                 :              0 :             return -1;
                               1485                 :                :     }
                               1486                 :                : 
                               1487                 :                :     /* do a sanity check */
 7462 bruce@momjian.us         1488   [ +  -  +  -  :CBC         125 :     if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
                                              +  - ]
                               1489   [ +  -  +  -  :            125 :         tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= USECS_PER_SEC)
                                              -  + ]
 8258 meskes@postgresql.or     1490                 :UBC           0 :         return -1;
                               1491                 :                : 
 8258 meskes@postgresql.or     1492                 :CBC         125 :     return 0;
                               1493                 :                : }                               /* DecodeTime() */
                               1494                 :                : 
                               1495                 :                : /* DecodeTimezone()
                               1496                 :                :  * Interpret string as a numeric timezone.
                               1497                 :                :  *
                               1498                 :                :  * Note: we allow timezone offsets up to 13:59.  There are places that
                               1499                 :                :  * use +1300 summer time.
                               1500                 :                :  */
                               1501                 :                : static int
                               1502                 :             59 : DecodeTimezone(char *str, int *tzp)
                               1503                 :                : {
                               1504                 :                :     int         tz;
                               1505                 :                :     int         hr,
                               1506                 :                :                 min;
                               1507                 :                :     char       *cp;
                               1508                 :                :     int         len;
                               1509                 :                : 
                               1510                 :                :     /* assume leading character is "+" or "-" */
 2310                          1511                 :             59 :     hr = strtoint(str + 1, &cp, 10);
                               1512                 :                : 
                               1513                 :                :     /* explicit delimiter? */
 8258                          1514         [ +  + ]:             59 :     if (*cp == ':')
 2310                          1515                 :             17 :         min = strtoint(cp + 1, &cp, 10);
                               1516                 :                :     /* otherwise, might have run things together... */
 7462 bruce@momjian.us         1517   [ +  -  +  + ]:             42 :     else if (*cp == '\0' && (len = strlen(str)) > 3)
                               1518                 :                :     {
 2310 meskes@postgresql.or     1519                 :              8 :         min = strtoint(str + len - 2, &cp, 10);
 7462 bruce@momjian.us         1520   [ +  -  -  + ]:              8 :         if (min < 0 || min >= 60)
 8258 meskes@postgresql.or     1521                 :UBC           0 :             return -1;
                               1522                 :                : 
 8258 meskes@postgresql.or     1523                 :CBC           8 :         *(str + len - 2) = '\0';
 2310                          1524                 :              8 :         hr = strtoint(str + 1, &cp, 10);
 7462 bruce@momjian.us         1525   [ +  -  -  + ]:              8 :         if (hr < 0 || hr > 13)
 8258 meskes@postgresql.or     1526                 :UBC           0 :             return -1;
                               1527                 :                :     }
                               1528                 :                :     else
 8258 meskes@postgresql.or     1529                 :CBC          34 :         min = 0;
                               1530                 :                : 
 7404 bruce@momjian.us         1531                 :             59 :     tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE;
 8258 meskes@postgresql.or     1532         [ +  + ]:             59 :     if (*str == '-')
                               1533                 :             17 :         tz = -tz;
                               1534                 :                : 
                               1535                 :             59 :     *tzp = -tz;
                               1536                 :             59 :     return *cp != '\0';
                               1537                 :                : }                               /* DecodeTimezone() */
                               1538                 :                : 
                               1539                 :                : 
                               1540                 :                : /* DecodePosixTimezone()
                               1541                 :                :  * Interpret string as a POSIX-compatible timezone:
                               1542                 :                :  *  PST-hh:mm
                               1543                 :                :  *  PST+h
                               1544                 :                :  * - thomas 2000-03-15
                               1545                 :                :  */
                               1546                 :                : static int
 8258 meskes@postgresql.or     1547                 :UBC           0 : DecodePosixTimezone(char *str, int *tzp)
                               1548                 :                : {
                               1549                 :                :     int         val,
                               1550                 :                :                 tz;
                               1551                 :                :     int         type;
                               1552                 :                :     char       *cp;
                               1553                 :                :     char        delim;
                               1554                 :                : 
                               1555                 :              0 :     cp = str;
 7462 bruce@momjian.us         1556   [ #  #  #  # ]:              0 :     while (*cp != '\0' && isalpha((unsigned char) *cp))
 8258 meskes@postgresql.or     1557                 :              0 :         cp++;
                               1558                 :                : 
                               1559         [ #  # ]:              0 :     if (DecodeTimezone(cp, &tz) != 0)
                               1560                 :              0 :         return -1;
                               1561                 :                : 
                               1562                 :              0 :     delim = *cp;
                               1563                 :              0 :     *cp = '\0';
                               1564                 :              0 :     type = DecodeSpecial(MAXDATEFIELDS - 1, str, &val);
                               1565                 :              0 :     *cp = delim;
                               1566                 :                : 
                               1567         [ #  # ]:              0 :     switch (type)
                               1568                 :                :     {
                               1569                 :              0 :         case DTZ:
                               1570                 :                :         case TZ:
 4030 tgl@sss.pgh.pa.us        1571                 :              0 :             *tzp = -(val + tz);
 8258 meskes@postgresql.or     1572                 :              0 :             break;
                               1573                 :                : 
                               1574                 :              0 :         default:
                               1575                 :              0 :             return -1;
                               1576                 :                :     }
                               1577                 :                : 
                               1578                 :              0 :     return 0;
                               1579                 :                : }                               /* DecodePosixTimezone() */
                               1580                 :                : 
                               1581                 :                : /* ParseDateTime()
                               1582                 :                :  * Break string into tokens based on a date/time context.
                               1583                 :                :  * Several field types are assigned:
                               1584                 :                :  *  DTK_NUMBER - digits and (possibly) a decimal point
                               1585                 :                :  *  DTK_DATE - digits and two delimiters, or digits and text
                               1586                 :                :  *  DTK_TIME - digits, colon delimiters, and possibly a decimal point
                               1587                 :                :  *  DTK_STRING - text (no digits)
                               1588                 :                :  *  DTK_SPECIAL - leading "+" or "-" followed by text
                               1589                 :                :  *  DTK_TZ - leading "+" or "-" followed by digits
                               1590                 :                :  * Note that some field types can hold unexpected items:
                               1591                 :                :  *  DTK_NUMBER can hold date fields (yy.ddd)
                               1592                 :                :  *  DTK_STRING can hold months (January) and time zones (PST)
                               1593                 :                :  *  DTK_DATE can hold Posix time zones (GMT-8)
                               1594                 :                :  *
                               1595                 :                :  * The "lowstr" work buffer must have at least strlen(timestr) + MAXDATEFIELDS
                               1596                 :                :  * bytes of space.  On output, field[] entries will point into it.
                               1597                 :                :  * The field[] and ftype[] arrays must have at least MAXDATEFIELDS entries.
                               1598                 :                :  */
                               1599                 :                : int
 8258 meskes@postgresql.or     1600                 :CBC         209 : ParseDateTime(char *timestr, char *lowstr,
                               1601                 :                :               char **field, int *ftype, int *numfields, char **endstr)
                               1602                 :                : {
                               1603                 :            209 :     int         nf = 0;
                               1604                 :            209 :     char       *lp = lowstr;
                               1605                 :                : 
                               1606                 :            209 :     *endstr = timestr;
                               1607                 :                :     /* outer loop through fields */
                               1608         [ +  + ]:           1137 :     while (*(*endstr) != '\0')
                               1609                 :                :     {
                               1610                 :                :         /* Record start of current field */
 4271 noah@leadboat.com        1611         [ +  + ]:            929 :         if (nf >= MAXDATEFIELDS)
                               1612                 :              1 :             return -1;
 4040 tgl@sss.pgh.pa.us        1613                 :            928 :         field[nf] = lp;
                               1614                 :                : 
                               1615                 :                :         /* leading digit? then date or time */
 8258 meskes@postgresql.or     1616         [ +  + ]:            928 :         if (isdigit((unsigned char) *(*endstr)))
                               1617                 :                :         {
                               1618                 :            362 :             *lp++ = *(*endstr)++;
                               1619         [ +  + ]:            936 :             while (isdigit((unsigned char) *(*endstr)))
                               1620                 :            574 :                 *lp++ = *(*endstr)++;
                               1621                 :                : 
                               1622                 :                :             /* time field? */
                               1623         [ +  + ]:            362 :             if (*(*endstr) == ':')
                               1624                 :                :             {
                               1625                 :            125 :                 ftype[nf] = DTK_TIME;
                               1626                 :            125 :                 *lp++ = *(*endstr)++;
                               1627                 :            125 :                 while (isdigit((unsigned char) *(*endstr)) ||
                               1628   [ +  +  +  +  :            886 :                        (*(*endstr) == ':') || (*(*endstr) == '.'))
                                              +  + ]
                               1629                 :            761 :                     *lp++ = *(*endstr)++;
                               1630                 :                :             }
                               1631                 :                :             /* date field? allow embedded text month */
 7462 bruce@momjian.us         1632   [ +  +  +  +  :            237 :             else if (*(*endstr) == '-' || *(*endstr) == '/' || *(*endstr) == '.')
                                              +  + ]
 8258 meskes@postgresql.or     1633                 :            120 :             {
                               1634                 :                :                 /* save delimiting character to use later */
                               1635                 :            120 :                 char       *dp = (*endstr);
                               1636                 :                : 
                               1637                 :            120 :                 *lp++ = *(*endstr)++;
                               1638                 :                :                 /* second field is all digits? then no embedded text month */
                               1639         [ +  + ]:            120 :                 if (isdigit((unsigned char) *(*endstr)))
                               1640                 :                :                 {
 7462 bruce@momjian.us         1641         [ +  + ]:             90 :                     ftype[nf] = (*dp == '.') ? DTK_NUMBER : DTK_DATE;
 8258 meskes@postgresql.or     1642         [ +  + ]:            249 :                     while (isdigit((unsigned char) *(*endstr)))
                               1643                 :            159 :                         *lp++ = *(*endstr)++;
                               1644                 :                : 
                               1645                 :                :                     /*
                               1646                 :                :                      * insist that the delimiters match to get a three-field
                               1647                 :                :                      * date.
                               1648                 :                :                      */
                               1649         [ +  + ]:             90 :                     if (*(*endstr) == *dp)
                               1650                 :                :                     {
                               1651                 :             84 :                         ftype[nf] = DTK_DATE;
                               1652                 :             84 :                         *lp++ = *(*endstr)++;
                               1653   [ +  +  -  + ]:            286 :                         while (isdigit((unsigned char) *(*endstr)) || (*(*endstr) == *dp))
                               1654                 :            202 :                             *lp++ = *(*endstr)++;
                               1655                 :                :                     }
                               1656                 :                :                 }
                               1657                 :                :                 else
                               1658                 :                :                 {
                               1659                 :             30 :                     ftype[nf] = DTK_DATE;
                               1660   [ +  +  +  + ]:            222 :                     while (isalnum((unsigned char) *(*endstr)) || (*(*endstr) == *dp))
 7844 tgl@sss.pgh.pa.us        1661                 :            192 :                         *lp++ = pg_tolower((unsigned char) *(*endstr)++);
                               1662                 :                :                 }
                               1663                 :                :             }
                               1664                 :                : 
                               1665                 :                :             /*
                               1666                 :                :              * otherwise, number only and will determine year, month, day, or
                               1667                 :                :              * concatenated fields later...
                               1668                 :                :              */
                               1669                 :                :             else
 8258 meskes@postgresql.or     1670                 :            117 :                 ftype[nf] = DTK_NUMBER;
                               1671                 :                :         }
                               1672                 :                :         /* Leading decimal point? Then fractional seconds... */
                               1673         [ +  + ]:            566 :         else if (*(*endstr) == '.')
                               1674                 :                :         {
                               1675                 :             49 :             *lp++ = *(*endstr)++;
                               1676         [ -  + ]:             49 :             while (isdigit((unsigned char) *(*endstr)))
 8258 meskes@postgresql.or     1677                 :UBC           0 :                 *lp++ = *(*endstr)++;
                               1678                 :                : 
 8258 meskes@postgresql.or     1679                 :CBC          49 :             ftype[nf] = DTK_NUMBER;
                               1680                 :                :         }
                               1681                 :                : 
                               1682                 :                :         /*
                               1683                 :                :          * text? then date string, month, day of week, special, or timezone
                               1684                 :                :          */
                               1685         [ +  + ]:            517 :         else if (isalpha((unsigned char) *(*endstr)))
                               1686                 :                :         {
                               1687                 :            130 :             ftype[nf] = DTK_STRING;
 7844 tgl@sss.pgh.pa.us        1688                 :            130 :             *lp++ = pg_tolower((unsigned char) *(*endstr)++);
 8258 meskes@postgresql.or     1689         [ +  + ]:            621 :             while (isalpha((unsigned char) *(*endstr)))
 7844 tgl@sss.pgh.pa.us        1690                 :            491 :                 *lp++ = pg_tolower((unsigned char) *(*endstr)++);
                               1691                 :                : 
                               1692                 :                :             /*
                               1693                 :                :              * Full date string with leading text month? Could also be a POSIX
                               1694                 :                :              * time zone...
                               1695                 :                :              */
 7462 bruce@momjian.us         1696   [ +  +  +  -  :            130 :             if (*(*endstr) == '-' || *(*endstr) == '/' || *(*endstr) == '.')
                                              -  + ]
                               1697                 :                :             {
 8258 meskes@postgresql.or     1698                 :             12 :                 char       *dp = (*endstr);
                               1699                 :                : 
                               1700                 :             12 :                 ftype[nf] = DTK_DATE;
                               1701                 :             12 :                 *lp++ = *(*endstr)++;
 7462 bruce@momjian.us         1702   [ +  +  +  + ]:             84 :                 while (isdigit((unsigned char) *(*endstr)) || *(*endstr) == *dp)
 8258 meskes@postgresql.or     1703                 :             72 :                     *lp++ = *(*endstr)++;
                               1704                 :                :             }
                               1705                 :                :         }
                               1706                 :                :         /* skip leading spaces */
                               1707         [ +  + ]:            387 :         else if (isspace((unsigned char) *(*endstr)))
                               1708                 :                :         {
                               1709                 :            314 :             (*endstr)++;
                               1710                 :            314 :             continue;
                               1711                 :                :         }
                               1712                 :                :         /* sign? then special or numeric timezone */
 7462 bruce@momjian.us         1713   [ +  +  +  + ]:             73 :         else if (*(*endstr) == '+' || *(*endstr) == '-')
                               1714                 :                :         {
 8258 meskes@postgresql.or     1715                 :             51 :             *lp++ = *(*endstr)++;
                               1716                 :                :             /* soak up leading whitespace */
                               1717         [ -  + ]:             51 :             while (isspace((unsigned char) *(*endstr)))
 8258 meskes@postgresql.or     1718                 :UBC           0 :                 (*endstr)++;
                               1719                 :                :             /* numeric timezone? */
 8258 meskes@postgresql.or     1720         [ +  - ]:CBC         102 :             if (isdigit((unsigned char) *(*endstr)))
                               1721                 :                :             {
                               1722                 :             51 :                 ftype[nf] = DTK_TZ;
                               1723                 :             51 :                 *lp++ = *(*endstr)++;
                               1724                 :             51 :                 while (isdigit((unsigned char) *(*endstr)) ||
                               1725   [ +  +  +  +  :            102 :                        (*(*endstr) == ':') || (*(*endstr) == '.'))
                                              -  + ]
                               1726                 :             51 :                     *lp++ = *(*endstr)++;
                               1727                 :                :             }
                               1728                 :                :             /* special? */
 8258 meskes@postgresql.or     1729         [ #  # ]:UBC           0 :             else if (isalpha((unsigned char) *(*endstr)))
                               1730                 :                :             {
                               1731                 :              0 :                 ftype[nf] = DTK_SPECIAL;
 7844 tgl@sss.pgh.pa.us        1732                 :              0 :                 *lp++ = pg_tolower((unsigned char) *(*endstr)++);
 8258 meskes@postgresql.or     1733         [ #  # ]:              0 :                 while (isalpha((unsigned char) *(*endstr)))
 7844 tgl@sss.pgh.pa.us        1734                 :              0 :                     *lp++ = pg_tolower((unsigned char) *(*endstr)++);
                               1735                 :                :             }
                               1736                 :                :             /* otherwise something wrong... */
                               1737                 :                :             else
 8258 meskes@postgresql.or     1738                 :              0 :                 return -1;
                               1739                 :                :         }
                               1740                 :                :         /* ignore punctuation but use as delimiter */
 8258 meskes@postgresql.or     1741         [ +  - ]:CBC          22 :         else if (ispunct((unsigned char) *(*endstr)))
                               1742                 :                :         {
                               1743                 :             22 :             (*endstr)++;
                               1744                 :             22 :             continue;
                               1745                 :                :         }
                               1746                 :                :         /* otherwise, something is not right... */
                               1747                 :                :         else
 8258 meskes@postgresql.or     1748                 :UBC           0 :             return -1;
                               1749                 :                : 
                               1750                 :                :         /* force in a delimiter after each field */
 8258 meskes@postgresql.or     1751                 :CBC         592 :         *lp++ = '\0';
                               1752                 :            592 :         nf++;
                               1753                 :                :     }
                               1754                 :                : 
                               1755                 :            208 :     *numfields = nf;
                               1756                 :                : 
                               1757                 :            208 :     return 0;
                               1758                 :                : }                               /* ParseDateTime() */
                               1759                 :                : 
                               1760                 :                : 
                               1761                 :                : /* DecodeDateTime()
                               1762                 :                :  * Interpret previously parsed fields for general date and time.
                               1763                 :                :  * Return 0 if full date, 1 if only time, and -1 if problems.
                               1764                 :                :  *      External format(s):
                               1765                 :                :  *              "<weekday> <month>-<day>-<year> <hour>:<minute>:<second>"
                               1766                 :                :  *              "Fri Feb-7-1997 15:23:27"
                               1767                 :                :  *              "Feb-7-1997 15:23:27"
                               1768                 :                :  *              "2-7-1997 15:23:27"
                               1769                 :                :  *              "1997-2-7 15:23:27"
                               1770                 :                :  *              "1997.038 15:23:27"       (day of year 1-366)
                               1771                 :                :  *      Also supports input in compact time:
                               1772                 :                :  *              "970207 152327"
                               1773                 :                :  *              "97038 152327"
                               1774                 :                :  *              "20011225T040506.789-07"
                               1775                 :                :  *
                               1776                 :                :  * Use the system-provided functions to get the current time zone
                               1777                 :                :  *  if not specified in the input string.
                               1778                 :                :  * If the date is outside the time_t system-supported time range,
                               1779                 :                :  *  then assume UTC time zone. - thomas 1997-05-27
                               1780                 :                :  */
                               1781                 :                : int
                               1782                 :            179 : DecodeDateTime(char **field, int *ftype, int nf,
                               1783                 :                :                int *dtype, struct tm *tm, fsec_t *fsec, bool EuroDates)
                               1784                 :                : {
                               1785                 :            179 :     int         fmask = 0,
                               1786                 :                :                 tmask,
                               1787                 :                :                 type;
 7318 bruce@momjian.us         1788                 :            179 :     int         ptype = 0;      /* "prefix type" for ISO y2001m02d04 format */
                               1789                 :                :     int         i;
                               1790                 :                :     int         val;
 8258 meskes@postgresql.or     1791                 :            179 :     int         mer = HR24;
 2995 peter_e@gmx.net          1792                 :            179 :     bool        haveTextMonth = false;
                               1793                 :            179 :     bool        is2digits = false;
                               1794                 :            179 :     bool        bc = false;
 6650 meskes@postgresql.or     1795                 :            179 :     int         t = 0;
 6557 bruce@momjian.us         1796                 :            179 :     int        *tzp = &t;
                               1797                 :                : 
                               1798                 :                :     /***
                               1799                 :                :      * We'll insist on at least all of the date fields, but initialize the
                               1800                 :                :      * remaining fields in case they are not set later...
                               1801                 :                :      ***/
 8258 meskes@postgresql.or     1802                 :            179 :     *dtype = DTK_DATE;
                               1803                 :            179 :     tm->tm_hour = 0;
                               1804                 :            179 :     tm->tm_min = 0;
                               1805                 :            179 :     tm->tm_sec = 0;
                               1806                 :            179 :     *fsec = 0;
                               1807                 :                :     /* don't know daylight savings time status apriori */
                               1808                 :            179 :     tm->tm_isdst = -1;
                               1809         [ +  - ]:            179 :     if (tzp != NULL)
                               1810                 :            179 :         *tzp = 0;
                               1811                 :                : 
                               1812         [ +  + ]:            624 :     for (i = 0; i < nf; i++)
                               1813                 :                :     {
                               1814   [ +  +  +  +  :            450 :         switch (ftype[i])
                                              +  - ]
                               1815                 :                :         {
                               1816                 :            126 :             case DTK_DATE:
                               1817                 :                :                 /***
                               1818                 :                :                  * Integral julian day with attached time zone?
                               1819                 :                :                  * All other forms with JD will be separated into
                               1820                 :                :                  * distinct fields, so we handle just this case here.
                               1821                 :                :                  ***/
                               1822         [ -  + ]:            126 :                 if (ptype == DTK_JULIAN)
                               1823                 :                :                 {
                               1824                 :                :                     char       *cp;
                               1825                 :                :                     int         jday;
                               1826                 :                : 
 8258 meskes@postgresql.or     1827         [ #  # ]:UBC           0 :                     if (tzp == NULL)
                               1828                 :              0 :                         return -1;
                               1829                 :                : 
 1119 drowley@postgresql.o     1830                 :              0 :                     jday = strtoint(field[i], &cp, 10);
 8258 meskes@postgresql.or     1831         [ #  # ]:              0 :                     if (*cp != '-')
                               1832                 :              0 :                         return -1;
                               1833                 :                : 
 1119 drowley@postgresql.o     1834                 :              0 :                     j2date(jday, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
                               1835                 :                :                     /* Get the time zone from the end of the string */
 8258 meskes@postgresql.or     1836         [ #  # ]:              0 :                     if (DecodeTimezone(cp, tzp) != 0)
                               1837                 :              0 :                         return -1;
                               1838                 :                : 
                               1839                 :              0 :                     tmask = DTK_DATE_M | DTK_TIME_M | DTK_M(TZ);
                               1840                 :              0 :                     ptype = 0;
                               1841                 :              0 :                     break;
                               1842                 :                :                 }
                               1843                 :                :                 /***
                               1844                 :                :                  * Already have a date? Then this might be a POSIX time
                               1845                 :                :                  * zone with an embedded dash (e.g. "PST-3" == "EST") or
                               1846                 :                :                  * a run-together time with trailing time zone (e.g. hhmmss-zz).
                               1847                 :                :                  * - thomas 2001-12-25
                               1848                 :                :                  ***/
 8258 meskes@postgresql.or     1849         [ +  - ]:CBC         126 :                 else if (((fmask & DTK_DATE_M) == DTK_DATE_M)
                               1850         [ -  + ]:            126 :                          || (ptype != 0))
                               1851                 :                :                 {
                               1852                 :                :                     /* No time zone accepted? Then quit... */
 8258 meskes@postgresql.or     1853         [ #  # ]:UBC           0 :                     if (tzp == NULL)
                               1854                 :              0 :                         return -1;
                               1855                 :                : 
                               1856   [ #  #  #  # ]:              0 :                     if (isdigit((unsigned char) *field[i]) || ptype != 0)
                               1857                 :              0 :                     {
                               1858                 :                :                         char       *cp;
                               1859                 :                : 
                               1860         [ #  # ]:              0 :                         if (ptype != 0)
                               1861                 :                :                         {
                               1862                 :                :                             /* Sanity check; should not fail this test */
                               1863         [ #  # ]:              0 :                             if (ptype != DTK_TIME)
                               1864                 :              0 :                                 return -1;
                               1865                 :              0 :                             ptype = 0;
                               1866                 :                :                         }
                               1867                 :                : 
                               1868                 :                :                         /*
                               1869                 :                :                          * Starts with a digit but we already have a time
                               1870                 :                :                          * field? Then we are in trouble with a date and time
                               1871                 :                :                          * already...
                               1872                 :                :                          */
                               1873         [ #  # ]:              0 :                         if ((fmask & DTK_TIME_M) == DTK_TIME_M)
                               1874                 :              0 :                             return -1;
                               1875                 :                : 
                               1876         [ #  # ]:              0 :                         if ((cp = strchr(field[i], '-')) == NULL)
                               1877                 :              0 :                             return -1;
                               1878                 :                : 
                               1879                 :                :                         /* Get the time zone from the end of the string */
                               1880         [ #  # ]:              0 :                         if (DecodeTimezone(cp, tzp) != 0)
                               1881                 :              0 :                             return -1;
                               1882                 :              0 :                         *cp = '\0';
                               1883                 :                : 
                               1884                 :                :                         /*
                               1885                 :                :                          * Then read the rest of the field as a concatenated
                               1886                 :                :                          * time
                               1887                 :                :                          */
                               1888         [ #  # ]:              0 :                         if ((ftype[i] = DecodeNumberField(strlen(field[i]), field[i], fmask,
                               1889                 :                :                                                           &tmask, tm, fsec, &is2digits)) < 0)
                               1890                 :              0 :                             return -1;
                               1891                 :                : 
                               1892                 :                :                         /*
                               1893                 :                :                          * modify tmask after returning from
                               1894                 :                :                          * DecodeNumberField()
                               1895                 :                :                          */
                               1896                 :              0 :                         tmask |= DTK_M(TZ);
                               1897                 :                :                     }
                               1898                 :                :                     else
                               1899                 :                :                     {
                               1900         [ #  # ]:              0 :                         if (DecodePosixTimezone(field[i], tzp) != 0)
                               1901                 :              0 :                             return -1;
                               1902                 :                : 
                               1903                 :              0 :                         ftype[i] = DTK_TZ;
                               1904                 :              0 :                         tmask = DTK_M(TZ);
                               1905                 :                :                     }
                               1906                 :                :                 }
 8258 meskes@postgresql.or     1907         [ -  + ]:CBC         126 :                 else if (DecodeDate(field[i], fmask, &tmask, tm, EuroDates) != 0)
 8258 meskes@postgresql.or     1908                 :UBC           0 :                     return -1;
 8258 meskes@postgresql.or     1909                 :CBC         126 :                 break;
                               1910                 :                : 
                               1911                 :            124 :             case DTK_TIME:
 6005                          1912         [ -  + ]:            124 :                 if (DecodeTime(field[i], &tmask, tm, fsec) != 0)
 8258 meskes@postgresql.or     1913                 :UBC           0 :                     return -1;
                               1914                 :                : 
                               1915                 :                :                 /*
                               1916                 :                :                  * Check upper limit on hours; other limits checked in
                               1917                 :                :                  * DecodeTime()
                               1918                 :                :                  */
                               1919                 :                :                 /* test for > 24:00:00 */
 7318 bruce@momjian.us         1920         [ +  + ]:CBC         124 :                 if (tm->tm_hour > 24 ||
                               1921   [ -  +  -  -  :            123 :                     (tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)))
                                              -  - ]
 8258 meskes@postgresql.or     1922                 :              1 :                     return -1;
                               1923                 :            123 :                 break;
                               1924                 :                : 
                               1925                 :             51 :             case DTK_TZ:
                               1926                 :                :                 {
                               1927                 :                :                     int         tz;
                               1928                 :                : 
                               1929         [ -  + ]:             51 :                     if (tzp == NULL)
 8258 meskes@postgresql.or     1930                 :UBC           0 :                         return -1;
                               1931                 :                : 
 8258 meskes@postgresql.or     1932         [ -  + ]:CBC          51 :                     if (DecodeTimezone(field[i], &tz) != 0)
 8258 meskes@postgresql.or     1933                 :UBC           0 :                         return -1;
                               1934                 :                : 
                               1935                 :                :                     /*
                               1936                 :                :                      * Already have a time zone? Then maybe this is the second
                               1937                 :                :                      * field of a POSIX time: EST+3 (equivalent to PST)
                               1938                 :                :                      */
 7462 bruce@momjian.us         1939   [ +  -  -  + ]:CBC          51 :                     if (i > 0 && (fmask & DTK_M(TZ)) != 0 &&
 7462 bruce@momjian.us         1940         [ #  # ]:UBC           0 :                         ftype[i - 1] == DTK_TZ &&
                               1941         [ #  # ]:              0 :                         isalpha((unsigned char) *field[i - 1]))
                               1942                 :                :                     {
 8258 meskes@postgresql.or     1943                 :              0 :                         *tzp -= tz;
                               1944                 :              0 :                         tmask = 0;
                               1945                 :                :                     }
                               1946                 :                :                     else
                               1947                 :                :                     {
 8258 meskes@postgresql.or     1948                 :CBC          51 :                         *tzp = tz;
                               1949                 :             51 :                         tmask = DTK_M(TZ);
                               1950                 :                :                     }
                               1951                 :                :                 }
                               1952                 :             51 :                 break;
                               1953                 :                : 
                               1954                 :             78 :             case DTK_NUMBER:
                               1955                 :                : 
                               1956                 :                :                 /*
                               1957                 :                :                  * Was this an "ISO date" with embedded field labels? An
                               1958                 :                :                  * example is "y2001m02d04" - thomas 2001-02-04
                               1959                 :                :                  */
                               1960         [ +  + ]:             78 :                 if (ptype != 0)
                               1961                 :                :                 {
                               1962                 :                :                     char       *cp;
                               1963                 :                :                     int         value;
                               1964                 :                : 
 1119 drowley@postgresql.o     1965                 :              6 :                     value = strtoint(field[i], &cp, 10);
                               1966                 :                : 
                               1967                 :                :                     /*
                               1968                 :                :                      * only a few kinds are allowed to have an embedded
                               1969                 :                :                      * decimal
                               1970                 :                :                      */
 8258 meskes@postgresql.or     1971         [ -  + ]:              6 :                     if (*cp == '.')
 8258 meskes@postgresql.or     1972         [ #  # ]:UBC           0 :                         switch (ptype)
                               1973                 :                :                         {
                               1974                 :              0 :                             case DTK_JULIAN:
                               1975                 :                :                             case DTK_TIME:
                               1976                 :                :                             case DTK_SECOND:
                               1977                 :              0 :                                 break;
                               1978                 :              0 :                             default:
                               1979                 :              0 :                                 return 1;
                               1980                 :                :                                 break;
                               1981                 :                :                         }
 8258 meskes@postgresql.or     1982         [ -  + ]:CBC           6 :                     else if (*cp != '\0')
 8258 meskes@postgresql.or     1983                 :UBC           0 :                         return -1;
                               1984                 :                : 
 8258 meskes@postgresql.or     1985   [ -  -  -  -  :CBC           6 :                     switch (ptype)
                                     -  -  -  +  -  
                                                 - ]
                               1986                 :                :                     {
 8258 meskes@postgresql.or     1987                 :UBC           0 :                         case DTK_YEAR:
 1119 drowley@postgresql.o     1988                 :              0 :                             tm->tm_year = value;
 8258 meskes@postgresql.or     1989                 :              0 :                             tmask = DTK_M(YEAR);
                               1990                 :              0 :                             break;
                               1991                 :                : 
                               1992                 :              0 :                         case DTK_MONTH:
                               1993                 :                : 
                               1994                 :                :                             /*
                               1995                 :                :                              * already have a month and hour? then assume
                               1996                 :                :                              * minutes
                               1997                 :                :                              */
 7462 bruce@momjian.us         1998         [ #  # ]:              0 :                             if ((fmask & DTK_M(MONTH)) != 0 &&
                               1999         [ #  # ]:              0 :                                 (fmask & DTK_M(HOUR)) != 0)
                               2000                 :                :                             {
 1119 drowley@postgresql.o     2001                 :              0 :                                 tm->tm_min = value;
 8258 meskes@postgresql.or     2002                 :              0 :                                 tmask = DTK_M(MINUTE);
                               2003                 :                :                             }
                               2004                 :                :                             else
                               2005                 :                :                             {
 1119 drowley@postgresql.o     2006                 :              0 :                                 tm->tm_mon = value;
 8258 meskes@postgresql.or     2007                 :              0 :                                 tmask = DTK_M(MONTH);
                               2008                 :                :                             }
                               2009                 :              0 :                             break;
                               2010                 :                : 
                               2011                 :              0 :                         case DTK_DAY:
 1119 drowley@postgresql.o     2012                 :              0 :                             tm->tm_mday = value;
 8258 meskes@postgresql.or     2013                 :              0 :                             tmask = DTK_M(DAY);
                               2014                 :              0 :                             break;
                               2015                 :                : 
                               2016                 :              0 :                         case DTK_HOUR:
 1119 drowley@postgresql.o     2017                 :              0 :                             tm->tm_hour = value;
 8258 meskes@postgresql.or     2018                 :              0 :                             tmask = DTK_M(HOUR);
                               2019                 :              0 :                             break;
                               2020                 :                : 
                               2021                 :              0 :                         case DTK_MINUTE:
 1119 drowley@postgresql.o     2022                 :              0 :                             tm->tm_min = value;
 8258 meskes@postgresql.or     2023                 :              0 :                             tmask = DTK_M(MINUTE);
                               2024                 :              0 :                             break;
                               2025                 :                : 
                               2026                 :              0 :                         case DTK_SECOND:
 1119 drowley@postgresql.o     2027                 :              0 :                             tm->tm_sec = value;
 8258 meskes@postgresql.or     2028                 :              0 :                             tmask = DTK_M(SECOND);
                               2029         [ #  # ]:              0 :                             if (*cp == '.')
                               2030                 :                :                             {
                               2031                 :                :                                 double      frac;
                               2032                 :                : 
  214 peter@eisentraut.org     2033                 :              0 :                                 frac = strtod(cp, &cp);
 8258 meskes@postgresql.or     2034         [ #  # ]:              0 :                                 if (*cp != '\0')
                               2035                 :              0 :                                     return -1;
                               2036                 :              0 :                                 *fsec = frac * 1000000;
                               2037                 :                :                             }
                               2038                 :              0 :                             break;
                               2039                 :                : 
                               2040                 :              0 :                         case DTK_TZ:
                               2041                 :              0 :                             tmask = DTK_M(TZ);
                               2042         [ #  # ]:              0 :                             if (DecodeTimezone(field[i], tzp) != 0)
                               2043                 :              0 :                                 return -1;
                               2044                 :              0 :                             break;
                               2045                 :                : 
 8258 meskes@postgresql.or     2046                 :CBC           6 :                         case DTK_JULIAN:
                               2047                 :                :                             /***
                               2048                 :                :                              * previous field was a label for "julian date"?
                               2049                 :                :                              ***/
                               2050                 :              6 :                             tmask = DTK_DATE_M;
 1119 drowley@postgresql.o     2051                 :              6 :                             j2date(value, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
                               2052                 :                :                             /* fractional Julian Day? */
 8258 meskes@postgresql.or     2053         [ -  + ]:              6 :                             if (*cp == '.')
                               2054                 :                :                             {
                               2055                 :                :                                 double      time;
                               2056                 :                : 
  214 peter@eisentraut.org     2057                 :UBC           0 :                                 time = strtod(cp, &cp);
 8258 meskes@postgresql.or     2058         [ #  # ]:              0 :                                 if (*cp != '\0')
                               2059                 :              0 :                                     return -1;
                               2060                 :                : 
                               2061                 :              0 :                                 tmask |= DTK_TIME_M;
 7463 bruce@momjian.us         2062                 :              0 :                                 dt2time((time * USECS_PER_DAY), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
                               2063                 :                :                             }
 8258 meskes@postgresql.or     2064                 :CBC           6 :                             break;
                               2065                 :                : 
 8258 meskes@postgresql.or     2066                 :UBC           0 :                         case DTK_TIME:
                               2067                 :                :                             /* previous field was "t" for ISO time */
                               2068         [ #  # ]:              0 :                             if ((ftype[i] = DecodeNumberField(strlen(field[i]), field[i], (fmask | DTK_DATE_M),
                               2069                 :                :                                                               &tmask, tm, fsec, &is2digits)) < 0)
                               2070                 :              0 :                                 return -1;
                               2071                 :                : 
                               2072         [ #  # ]:              0 :                             if (tmask != DTK_TIME_M)
                               2073                 :              0 :                                 return -1;
                               2074                 :              0 :                             break;
                               2075                 :                : 
                               2076                 :              0 :                         default:
                               2077                 :              0 :                             return -1;
                               2078                 :                :                             break;
                               2079                 :                :                     }
                               2080                 :                : 
 8258 meskes@postgresql.or     2081                 :CBC           6 :                     ptype = 0;
                               2082                 :              6 :                     *dtype = DTK_DATE;
                               2083                 :                :                 }
                               2084                 :                :                 else
                               2085                 :                :                 {
                               2086                 :                :                     char       *cp;
                               2087                 :                :                     int         flen;
                               2088                 :                : 
                               2089                 :             72 :                     flen = strlen(field[i]);
                               2090                 :             72 :                     cp = strchr(field[i], '.');
                               2091                 :                : 
                               2092                 :                :                     /* Embedded decimal and no date yet? */
 7462 bruce@momjian.us         2093   [ +  +  +  - ]:             72 :                     if (cp != NULL && !(fmask & DTK_DATE_M))
                               2094                 :                :                     {
 8258 meskes@postgresql.or     2095         [ +  + ]:              7 :                         if (DecodeDate(field[i], fmask, &tmask, tm, EuroDates) != 0)
                               2096                 :              1 :                             return -1;
                               2097                 :                :                     }
                               2098                 :                :                     /* embedded decimal and several digits before? */
 7462 bruce@momjian.us         2099   [ -  +  -  - ]:             65 :                     else if (cp != NULL && flen - strlen(cp) > 2)
                               2100                 :                :                     {
                               2101                 :                :                         /*
                               2102                 :                :                          * Interpret as a concatenated date or time Set the
                               2103                 :                :                          * type field to allow decoding other fields later.
                               2104                 :                :                          * Example: 20011223 or 040506
                               2105                 :                :                          */
 8258 meskes@postgresql.or     2106         [ #  # ]:UBC           0 :                         if ((ftype[i] = DecodeNumberField(flen, field[i], fmask,
                               2107                 :                :                                                           &tmask, tm, fsec, &is2digits)) < 0)
                               2108                 :              0 :                             return -1;
                               2109                 :                :                     }
 8258 meskes@postgresql.or     2110         [ +  + ]:CBC          65 :                     else if (flen > 4)
                               2111                 :                :                     {
                               2112         [ -  + ]:             15 :                         if ((ftype[i] = DecodeNumberField(flen, field[i], fmask,
                               2113                 :                :                                                           &tmask, tm, fsec, &is2digits)) < 0)
 8258 meskes@postgresql.or     2114                 :UBC           0 :                             return -1;
                               2115                 :                :                     }
                               2116                 :                :                     /* otherwise it is a single date/time field... */
 8258 meskes@postgresql.or     2117         [ -  + ]:CBC          50 :                     else if (DecodeNumber(flen, field[i], fmask,
                               2118                 :                :                                           &tmask, tm, fsec, &is2digits, EuroDates) != 0)
 8258 meskes@postgresql.or     2119                 :UBC           0 :                         return -1;
                               2120                 :                :                 }
 8258 meskes@postgresql.or     2121                 :CBC          77 :                 break;
                               2122                 :                : 
                               2123                 :             71 :             case DTK_STRING:
                               2124                 :                :             case DTK_SPECIAL:
                               2125                 :             71 :                 type = DecodeSpecial(i, field[i], &val);
                               2126         [ -  + ]:             71 :                 if (type == IGNORE_DTF)
 8258 meskes@postgresql.or     2127                 :UBC           0 :                     continue;
                               2128                 :                : 
 8258 meskes@postgresql.or     2129                 :CBC          71 :                 tmask = DTK_M(type);
                               2130   [ -  +  -  +  :             71 :                 switch (type)
                                     -  -  +  +  +  
                                           +  -  + ]
                               2131                 :                :                 {
 8258 meskes@postgresql.or     2132                 :UBC           0 :                     case RESERV:
                               2133   [ #  #  #  #  :              0 :                         switch (val)
                                              #  # ]
                               2134                 :                :                         {
                               2135                 :              0 :                             case DTK_NOW:
                               2136                 :              0 :                                 tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
                               2137                 :              0 :                                 *dtype = DTK_DATE;
                               2138                 :              0 :                                 GetCurrentDateTime(tm);
                               2139                 :              0 :                                 break;
                               2140                 :                : 
                               2141                 :              0 :                             case DTK_YESTERDAY:
                               2142                 :              0 :                                 tmask = DTK_DATE_M;
                               2143                 :              0 :                                 *dtype = DTK_DATE;
                               2144                 :              0 :                                 GetCurrentDateTime(tm);
 7462 bruce@momjian.us         2145                 :              0 :                                 j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1,
                               2146                 :                :                                        &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
 8258 meskes@postgresql.or     2147                 :              0 :                                 tm->tm_hour = 0;
                               2148                 :              0 :                                 tm->tm_min = 0;
                               2149                 :              0 :                                 tm->tm_sec = 0;
                               2150                 :              0 :                                 break;
                               2151                 :                : 
                               2152                 :              0 :                             case DTK_TODAY:
                               2153                 :              0 :                                 tmask = DTK_DATE_M;
                               2154                 :              0 :                                 *dtype = DTK_DATE;
                               2155                 :              0 :                                 GetCurrentDateTime(tm);
                               2156                 :              0 :                                 tm->tm_hour = 0;
                               2157                 :              0 :                                 tm->tm_min = 0;
                               2158                 :              0 :                                 tm->tm_sec = 0;
                               2159                 :              0 :                                 break;
                               2160                 :                : 
                               2161                 :              0 :                             case DTK_TOMORROW:
                               2162                 :              0 :                                 tmask = DTK_DATE_M;
                               2163                 :              0 :                                 *dtype = DTK_DATE;
                               2164                 :              0 :                                 GetCurrentDateTime(tm);
 7462 bruce@momjian.us         2165                 :              0 :                                 j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1,
                               2166                 :                :                                        &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
 8258 meskes@postgresql.or     2167                 :              0 :                                 tm->tm_hour = 0;
                               2168                 :              0 :                                 tm->tm_min = 0;
                               2169                 :              0 :                                 tm->tm_sec = 0;
                               2170                 :              0 :                                 break;
                               2171                 :                : 
                               2172                 :              0 :                             case DTK_ZULU:
                               2173                 :              0 :                                 tmask = (DTK_TIME_M | DTK_M(TZ));
                               2174                 :              0 :                                 *dtype = DTK_DATE;
                               2175                 :              0 :                                 tm->tm_hour = 0;
                               2176                 :              0 :                                 tm->tm_min = 0;
                               2177                 :              0 :                                 tm->tm_sec = 0;
                               2178         [ #  # ]:              0 :                                 if (tzp != NULL)
                               2179                 :              0 :                                     *tzp = 0;
                               2180                 :              0 :                                 break;
                               2181                 :                : 
                               2182                 :              0 :                             default:
                               2183                 :              0 :                                 *dtype = val;
                               2184                 :                :                         }
                               2185                 :                : 
                               2186                 :              0 :                         break;
                               2187                 :                : 
 8258 meskes@postgresql.or     2188                 :CBC          25 :                     case MONTH:
                               2189                 :                : 
                               2190                 :                :                         /*
                               2191                 :                :                          * already have a (numeric) month? then see if we can
                               2192                 :                :                          * substitute...
                               2193                 :                :                          */
 7462 bruce@momjian.us         2194   [ +  +  +  - ]:             25 :                         if ((fmask & DTK_M(MONTH)) && !haveTextMonth &&
                               2195   [ +  -  +  -  :              2 :                             !(fmask & DTK_M(DAY)) && tm->tm_mon >= 1 && tm->tm_mon <= 31)
                                              +  - ]
                               2196                 :                :                         {
 8258 meskes@postgresql.or     2197                 :              2 :                             tm->tm_mday = tm->tm_mon;
                               2198                 :              2 :                             tmask = DTK_M(DAY);
                               2199                 :                :                         }
 2995 peter_e@gmx.net          2200                 :             25 :                         haveTextMonth = true;
 8258 meskes@postgresql.or     2201                 :             25 :                         tm->tm_mon = val;
                               2202                 :             25 :                         break;
                               2203                 :                : 
 8258 meskes@postgresql.or     2204                 :UBC           0 :                     case DTZMOD:
                               2205                 :                : 
                               2206                 :                :                         /*
                               2207                 :                :                          * daylight savings time modifier (solves "MET DST"
                               2208                 :                :                          * syntax)
                               2209                 :                :                          */
                               2210                 :              0 :                         tmask |= DTK_M(DTZ);
                               2211                 :              0 :                         tm->tm_isdst = 1;
                               2212         [ #  # ]:              0 :                         if (tzp == NULL)
                               2213                 :              0 :                             return -1;
 4030 tgl@sss.pgh.pa.us        2214                 :              0 :                         *tzp -= val;
 8258 meskes@postgresql.or     2215                 :              0 :                         break;
                               2216                 :                : 
 8258 meskes@postgresql.or     2217                 :CBC          17 :                     case DTZ:
                               2218                 :                : 
                               2219                 :                :                         /*
                               2220                 :                :                          * set mask for TZ here _or_ check for DTZ later when
                               2221                 :                :                          * getting default timezone
                               2222                 :                :                          */
                               2223                 :             17 :                         tmask |= DTK_M(TZ);
                               2224                 :             17 :                         tm->tm_isdst = 1;
                               2225         [ -  + ]:             17 :                         if (tzp == NULL)
 8258 meskes@postgresql.or     2226                 :UBC           0 :                             return -1;
 4030 tgl@sss.pgh.pa.us        2227                 :CBC          17 :                         *tzp = -val;
 8258 meskes@postgresql.or     2228                 :             17 :                         ftype[i] = DTK_TZ;
                               2229                 :             17 :                         break;
                               2230                 :                : 
 8258 meskes@postgresql.or     2231                 :UBC           0 :                     case TZ:
                               2232                 :              0 :                         tm->tm_isdst = 0;
                               2233         [ #  # ]:              0 :                         if (tzp == NULL)
                               2234                 :              0 :                             return -1;
 4030 tgl@sss.pgh.pa.us        2235                 :              0 :                         *tzp = -val;
 8258 meskes@postgresql.or     2236                 :              0 :                         ftype[i] = DTK_TZ;
                               2237                 :              0 :                         break;
                               2238                 :                : 
                               2239                 :              0 :                     case IGNORE_DTF:
                               2240                 :              0 :                         break;
                               2241                 :                : 
 8258 meskes@postgresql.or     2242                 :CBC           1 :                     case AMPM:
                               2243                 :              1 :                         mer = val;
                               2244                 :              1 :                         break;
                               2245                 :                : 
                               2246                 :              6 :                     case ADBC:
                               2247                 :              6 :                         bc = (val == BC);
                               2248                 :              6 :                         break;
                               2249                 :                : 
                               2250                 :             13 :                     case DOW:
                               2251                 :             13 :                         tm->tm_wday = val;
                               2252                 :             13 :                         break;
                               2253                 :                : 
                               2254                 :              6 :                     case UNITS:
                               2255                 :              6 :                         tmask = 0;
                               2256                 :              6 :                         ptype = val;
                               2257                 :              6 :                         break;
                               2258                 :                : 
 8258 meskes@postgresql.or     2259                 :UBC           0 :                     case ISOTIME:
                               2260                 :                : 
                               2261                 :                :                         /*
                               2262                 :                :                          * This is a filler field "t" indicating that the next
                               2263                 :                :                          * field is time. Try to verify that this is sensible.
                               2264                 :                :                          */
                               2265                 :              0 :                         tmask = 0;
                               2266                 :                : 
                               2267                 :                :                         /* No preceding date? Then quit... */
                               2268         [ #  # ]:              0 :                         if ((fmask & DTK_DATE_M) != DTK_DATE_M)
                               2269                 :              0 :                             return -1;
                               2270                 :                : 
                               2271                 :                :                         /***
                               2272                 :                :                          * We will need one of the following fields:
                               2273                 :                :                          *  DTK_NUMBER should be hhmmss.fff
                               2274                 :                :                          *  DTK_TIME should be hh:mm:ss.fff
                               2275                 :                :                          *  DTK_DATE should be hhmmss-zz
                               2276                 :                :                          ***/
 7462 bruce@momjian.us         2277         [ #  # ]:              0 :                         if (i >= nf - 1 ||
                               2278         [ #  # ]:              0 :                             (ftype[i + 1] != DTK_NUMBER &&
 7318                          2279         [ #  # ]:              0 :                              ftype[i + 1] != DTK_TIME &&
                               2280         [ #  # ]:              0 :                              ftype[i + 1] != DTK_DATE))
 8258 meskes@postgresql.or     2281                 :              0 :                             return -1;
                               2282                 :                : 
                               2283                 :              0 :                         ptype = val;
                               2284                 :              0 :                         break;
                               2285                 :                : 
 8258 meskes@postgresql.or     2286                 :CBC           3 :                     default:
                               2287                 :              3 :                         return -1;
                               2288                 :                :                 }
                               2289                 :             68 :                 break;
                               2290                 :                : 
 8258 meskes@postgresql.or     2291                 :UBC           0 :             default:
                               2292                 :              0 :                 return -1;
                               2293                 :                :         }
                               2294                 :                : 
 8258 meskes@postgresql.or     2295         [ -  + ]:CBC         445 :         if (tmask & fmask)
 8258 meskes@postgresql.or     2296                 :UBC           0 :             return -1;
 8258 meskes@postgresql.or     2297                 :CBC         445 :         fmask |= tmask;
                               2298                 :                :     }
                               2299                 :                : 
                               2300                 :                :     /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */
                               2301         [ +  + ]:            174 :     if (bc)
                               2302                 :                :     {
                               2303         [ +  - ]:              6 :         if (tm->tm_year > 0)
                               2304                 :              6 :             tm->tm_year = -(tm->tm_year - 1);
                               2305                 :                :         else
 8258 meskes@postgresql.or     2306                 :UBC           0 :             return -1;
                               2307                 :                :     }
 8258 meskes@postgresql.or     2308         [ +  + ]:CBC         168 :     else if (is2digits)
                               2309                 :                :     {
                               2310         [ -  + ]:              6 :         if (tm->tm_year < 70)
 8258 meskes@postgresql.or     2311                 :UBC           0 :             tm->tm_year += 2000;
 8258 meskes@postgresql.or     2312         [ +  - ]:CBC           6 :         else if (tm->tm_year < 100)
                               2313                 :              6 :             tm->tm_year += 1900;
                               2314                 :                :     }
                               2315                 :                : 
 7462 bruce@momjian.us         2316   [ +  +  -  + ]:            174 :     if (mer != HR24 && tm->tm_hour > 12)
 8258 meskes@postgresql.or     2317                 :UBC           0 :         return -1;
 7462 bruce@momjian.us         2318   [ +  +  -  + ]:CBC         174 :     if (mer == AM && tm->tm_hour == 12)
 8258 meskes@postgresql.or     2319                 :UBC           0 :         tm->tm_hour = 0;
 7462 bruce@momjian.us         2320   [ -  +  -  - ]:CBC         174 :     else if (mer == PM && tm->tm_hour != 12)
 8258 meskes@postgresql.or     2321                 :UBC           0 :         tm->tm_hour += 12;
                               2322                 :                : 
                               2323                 :                :     /* do additional checking for full date specs... */
 8258 meskes@postgresql.or     2324         [ +  - ]:CBC         174 :     if (*dtype == DTK_DATE)
                               2325                 :                :     {
                               2326         [ -  + ]:            174 :         if ((fmask & DTK_DATE_M) != DTK_DATE_M)
 8258 meskes@postgresql.or     2327         [ #  # ]:UBC           0 :             return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
                               2328                 :                : 
                               2329                 :                :         /*
                               2330                 :                :          * check for valid day of month and month, now that we know for sure
                               2331                 :                :          * the month and year...
                               2332                 :                :          */
  370 michael@paquier.xyz      2333   [ +  +  +  -  :CBC         174 :         if (tm->tm_mon < 1 || tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
                                     +  +  +  +  +  
                                           +  -  + ]
 8258 meskes@postgresql.or     2334                 :              1 :             return -1;
                               2335                 :                : 
                               2336                 :                :         /*
                               2337                 :                :          * backend tried to find local timezone here but we don't use the
                               2338                 :                :          * result afterwards anyway so we only check for this error: daylight
                               2339                 :                :          * savings time modifier but no standard timezone?
                               2340                 :                :          */
 6735                          2341   [ +  -  +  -  :            173 :         if ((fmask & DTK_DATE_M) == DTK_DATE_M && tzp != NULL && !(fmask & DTK_M(TZ)) && (fmask & DTK_M(DTZMOD)))
                                        +  +  -  + ]
 6557 bruce@momjian.us         2342                 :UBC           0 :             return -1;
                               2343                 :                :     }
                               2344                 :                : 
 8258 meskes@postgresql.or     2345                 :CBC         173 :     return 0;
                               2346                 :                : }                               /* DecodeDateTime() */
                               2347                 :                : 
                               2348                 :                : /* Function works as follows:
                               2349                 :                :  *
                               2350                 :                :  *
                               2351                 :                :  * */
                               2352                 :                : 
                               2353                 :                : static char *
 8121 bruce@momjian.us         2354                 :            114 : find_end_token(char *str, char *fmt)
                               2355                 :                : {
                               2356                 :                :     /*
                               2357                 :                :      * str: here is28the day12the hour fmt: here is%dthe day%hthe hour
                               2358                 :                :      *
                               2359                 :                :      * we extract the 28, we read the percent sign and the type "d" then this
                               2360                 :                :      * functions gets called as find_end_token("28the day12the hour", "the
                               2361                 :                :      * day%hthehour")
                               2362                 :                :      *
                               2363                 :                :      * fmt points to "the day%hthehour", next_percent points to %hthehour and
                               2364                 :                :      * we have to find a match for everything between these positions ("the
                               2365                 :                :      * day"). We look for "the day" in str and know that the pattern we are
                               2366                 :                :      * about to scan ends where this string starts (right after the "28")
                               2367                 :                :      *
                               2368                 :                :      * At the end, *fmt is '\0' and *str isn't. end_position then is
                               2369                 :                :      * unchanged.
                               2370                 :                :      */
                               2371                 :            114 :     char       *end_position = NULL;
                               2372                 :                :     char       *next_percent,
                               2373                 :            114 :                *subst_location = NULL;
                               2374                 :            114 :     int         scan_offset = 0;
                               2375                 :                :     char        last_char;
                               2376                 :                : 
                               2377                 :                :     /* are we at the end? */
                               2378         [ +  + ]:            114 :     if (!*fmt)
                               2379                 :                :     {
 8124 meskes@postgresql.or     2380                 :             17 :         end_position = fmt;
                               2381                 :             17 :         return end_position;
                               2382                 :                :     }
                               2383                 :                : 
                               2384                 :                :     /* not at the end */
 8121 bruce@momjian.us         2385   [ +  +  +  - ]:             99 :     while (fmt[scan_offset] == '%' && fmt[scan_offset + 1])
                               2386                 :                :     {
                               2387                 :                :         /*
                               2388                 :                :          * there is no delimiter, skip to the next delimiter if we're reading
                               2389                 :                :          * a number and then something that is not a number "9:15pm", we might
                               2390                 :                :          * be able to recover with the strtol end pointer. Go for the next
                               2391                 :                :          * percent sign
                               2392                 :                :          */
 8124 meskes@postgresql.or     2393                 :              2 :         scan_offset += 2;
                               2394                 :                :     }
 8121 bruce@momjian.us         2395                 :             97 :     next_percent = strchr(fmt + scan_offset, '%');
                               2396         [ +  + ]:             97 :     if (next_percent)
                               2397                 :                :     {
                               2398                 :                :         /*
                               2399                 :                :          * we don't want to allocate extra memory, so we temporarily set the
                               2400                 :                :          * '%' sign to '\0' and call strstr However since we allow whitespace
                               2401                 :                :          * to float around everything, we have to shorten the pattern until we
                               2402                 :                :          * reach a non-whitespace character
                               2403                 :                :          */
                               2404                 :                : 
 8124 meskes@postgresql.or     2405                 :             94 :         subst_location = next_percent;
 8121 bruce@momjian.us         2406   [ +  +  +  + ]:            107 :         while (*(subst_location - 1) == ' ' && subst_location - 1 > fmt + scan_offset)
 8124 meskes@postgresql.or     2407                 :             13 :             subst_location--;
                               2408                 :             94 :         last_char = *subst_location;
                               2409                 :             94 :         *subst_location = '\0';
                               2410                 :                : 
                               2411                 :                :         /*
                               2412                 :                :          * the haystack is the str and the needle is the original fmt but it
                               2413                 :                :          * ends at the position where the next percent sign would be
                               2414                 :                :          */
                               2415                 :                : 
                               2416                 :                :         /*
                               2417                 :                :          * There is one special case. Imagine: str = " 2", fmt = "%d %...",
                               2418                 :                :          * since we want to allow blanks as "dynamic" padding we have to
                               2419                 :                :          * accept this. Now, we are called with a fmt of " %..." and look for
                               2420                 :                :          * " " in str. We find it at the first position and never read the
                               2421                 :                :          * 2...
                               2422                 :                :          */
 8121 bruce@momjian.us         2423         [ -  + ]:             94 :         while (*str == ' ')
 8121 bruce@momjian.us         2424                 :UBC           0 :             str++;
 8121 bruce@momjian.us         2425                 :CBC          94 :         end_position = strstr(str, fmt + scan_offset);
 8124 meskes@postgresql.or     2426                 :             94 :         *subst_location = last_char;
                               2427                 :                :     }
                               2428                 :                :     else
                               2429                 :                :     {
                               2430                 :                :         /*
                               2431                 :                :          * there is no other percent sign. So everything up to the end has to
                               2432                 :                :          * match.
                               2433                 :                :          */
                               2434                 :              3 :         end_position = str + strlen(str);
                               2435                 :                :     }
 8121 bruce@momjian.us         2436         [ +  + ]:             97 :     if (!end_position)
                               2437                 :                :     {
                               2438                 :                :         /*
                               2439                 :                :          * maybe we have the following case:
                               2440                 :                :          *
                               2441                 :                :          * str = "4:15am" fmt = "%M:%S %p"
                               2442                 :                :          *
                               2443                 :                :          * at this place we could have
                               2444                 :                :          *
                               2445                 :                :          * str = "15am" fmt = " %p"
                               2446                 :                :          *
                               2447                 :                :          * and have set fmt to " " because overwrote the % sign with a NULL
                               2448                 :                :          *
                               2449                 :                :          * In this case where we would have to match a space but can't find
                               2450                 :                :          * it, set end_position to the end of the string
                               2451                 :                :          */
                               2452   [ +  -  +  - ]:              1 :         if ((fmt + scan_offset)[0] == ' ' && fmt + scan_offset + 1 == subst_location)
 8124 meskes@postgresql.or     2453                 :              1 :             end_position = str + strlen(str);
                               2454                 :                :     }
                               2455                 :             97 :     return end_position;
                               2456                 :                : }
                               2457                 :                : 
                               2458                 :                : static int
 3051 tgl@sss.pgh.pa.us        2459                 :            114 : pgtypes_defmt_scan(union un_fmt_comb *scan_val, int scan_type, char **pstr, char *pfmt)
                               2460                 :                : {
                               2461                 :                :     /*
                               2462                 :                :      * scan everything between pstr and pstr_end. This is not including the
                               2463                 :                :      * last character so we might set it to '\0' for the parsing
                               2464                 :                :      */
                               2465                 :                : 
                               2466                 :                :     char        last_char;
 8121 bruce@momjian.us         2467                 :            114 :     int         err = 0;
                               2468                 :                :     char       *pstr_end;
                               2469                 :            114 :     char       *strtol_end = NULL;
                               2470                 :                : 
                               2471         [ -  + ]:            114 :     while (**pstr == ' ')
 8121 bruce@momjian.us         2472                 :UBC           0 :         pstr++;
 8124 meskes@postgresql.or     2473                 :CBC         114 :     pstr_end = find_end_token(*pstr, pfmt);
 8121 bruce@momjian.us         2474         [ -  + ]:            114 :     if (!pstr_end)
                               2475                 :                :     {
                               2476                 :                :         /* there was an error, no match */
 7424 neilc@samurai.com        2477                 :UBC           0 :         return 1;
                               2478                 :                :     }
 8124 meskes@postgresql.or     2479                 :CBC         114 :     last_char = *pstr_end;
                               2480                 :            114 :     *pstr_end = '\0';
                               2481                 :                : 
 8121 bruce@momjian.us         2482   [ +  +  +  - ]:            114 :     switch (scan_type)
                               2483                 :                :     {
 8124 meskes@postgresql.or     2484                 :            101 :         case PGTYPES_TYPE_UINT:
                               2485                 :                : 
                               2486                 :                :             /*
                               2487                 :                :              * numbers may be blank-padded, this is the only deviation from
                               2488                 :                :              * the fmt-string we accept
                               2489                 :                :              */
 8121 bruce@momjian.us         2490         [ -  + ]:            101 :             while (**pstr == ' ')
 8121 bruce@momjian.us         2491                 :UBC           0 :                 (*pstr)++;
 8124 meskes@postgresql.or     2492                 :CBC         101 :             errno = 0;
                               2493                 :            101 :             scan_val->uint_val = (unsigned int) strtol(*pstr, &strtol_end, 10);
 8121 bruce@momjian.us         2494         [ -  + ]:            101 :             if (errno)
 8121 bruce@momjian.us         2495                 :UBC           0 :                 err = 1;
 8124 meskes@postgresql.or     2496                 :CBC         101 :             break;
                               2497                 :              1 :         case PGTYPES_TYPE_UINT_LONG:
 8121 bruce@momjian.us         2498         [ -  + ]:              1 :             while (**pstr == ' ')
 8121 bruce@momjian.us         2499                 :UBC           0 :                 (*pstr)++;
 8124 meskes@postgresql.or     2500                 :CBC           1 :             errno = 0;
 6109                          2501                 :              1 :             scan_val->luint_val = (unsigned long int) strtol(*pstr, &strtol_end, 10);
 8121 bruce@momjian.us         2502         [ -  + ]:              1 :             if (errno)
 8121 bruce@momjian.us         2503                 :UBC           0 :                 err = 1;
 8124 meskes@postgresql.or     2504                 :CBC           1 :             break;
                               2505                 :             12 :         case PGTYPES_TYPE_STRING_MALLOCED:
 7424 neilc@samurai.com        2506                 :             12 :             scan_val->str_val = pgtypes_strdup(*pstr);
                               2507         [ -  + ]:             12 :             if (scan_val->str_val == NULL)
 7424 neilc@samurai.com        2508                 :UBC           0 :                 err = 1;
 7424 neilc@samurai.com        2509                 :CBC          12 :             break;
                               2510                 :                :     }
 8121 bruce@momjian.us         2511   [ +  +  +  + ]:            114 :     if (strtol_end && *strtol_end)
 8124 meskes@postgresql.or     2512                 :              9 :         *pstr = strtol_end;
                               2513                 :                :     else
                               2514                 :            105 :         *pstr = pstr_end;
                               2515                 :            114 :     *pstr_end = last_char;
                               2516                 :            114 :     return err;
                               2517                 :                : }
                               2518                 :                : 
                               2519                 :                : /* XXX range checking */
                               2520                 :                : int
 7318 bruce@momjian.us         2521                 :             24 : PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d,
                               2522                 :                :                             int *year, int *month, int *day,
                               2523                 :                :                             int *hour, int *minute, int *second,
                               2524                 :                :                             int *tz)
                               2525                 :                : {
                               2526                 :                :     union un_fmt_comb scan_val;
                               2527                 :                :     int         scan_type;
                               2528                 :                : 
                               2529                 :                :     char       *pstr,
                               2530                 :                :                *pfmt,
                               2531                 :                :                *tmp;
 5983                          2532                 :             24 :     int         err = 1;
                               2533                 :                :     unsigned int j;
                               2534                 :                :     struct tm   tm;
                               2535                 :                : 
 8124 meskes@postgresql.or     2536                 :             24 :     pfmt = fmt;
                               2537                 :             24 :     pstr = *str;
                               2538                 :                : 
 8121 bruce@momjian.us         2539         [ +  + ]:            274 :     while (*pfmt)
                               2540                 :                :     {
 8124 meskes@postgresql.or     2541                 :            252 :         err = 0;
 8121 bruce@momjian.us         2542         [ +  + ]:            354 :         while (*pfmt == ' ')
                               2543                 :            102 :             pfmt++;
                               2544         [ +  + ]:            375 :         while (*pstr == ' ')
                               2545                 :            123 :             pstr++;
                               2546         [ +  + ]:            252 :         if (*pfmt != '%')
                               2547                 :                :         {
                               2548         [ +  + ]:             98 :             if (*pfmt == *pstr)
                               2549                 :                :             {
 8124 meskes@postgresql.or     2550                 :             96 :                 pfmt++;
                               2551                 :             96 :                 pstr++;
                               2552                 :                :             }
                               2553                 :                :             else
                               2554                 :                :             {
                               2555                 :                :                 /* Error: no match */
                               2556                 :              2 :                 err = 1;
                               2557                 :              2 :                 return err;
                               2558                 :                :             }
                               2559                 :             96 :             continue;
                               2560                 :                :         }
                               2561                 :                :         /* here *pfmt equals '%' */
                               2562                 :            154 :         pfmt++;
 8121 bruce@momjian.us         2563   [ +  -  +  +  :            154 :         switch (*pfmt)
                                     -  +  +  -  +  
                                     +  -  +  -  +  
                                     +  +  +  -  -  
                                     +  +  -  -  -  
                                     -  -  -  -  -  
                                     +  +  +  -  +  
                                                 + ]
                               2564                 :                :         {
 8124 meskes@postgresql.or     2565                 :              9 :             case 'a':
                               2566                 :              9 :                 pfmt++;
                               2567                 :                : 
                               2568                 :                :                 /*
                               2569                 :                :                  * we parse the day and see if it is a week day but we do not
                               2570                 :                :                  * check if the week day really matches the date
                               2571                 :                :                  */
 8121 bruce@momjian.us         2572                 :              9 :                 err = 1;
                               2573                 :              9 :                 j = 0;
                               2574         [ +  - ]:             25 :                 while (pgtypes_date_weekdays_short[j])
                               2575                 :                :                 {
 8124 meskes@postgresql.or     2576                 :             25 :                     if (strncmp(pgtypes_date_weekdays_short[j], pstr,
 7318 bruce@momjian.us         2577         [ +  + ]:             25 :                                 strlen(pgtypes_date_weekdays_short[j])) == 0)
                               2578                 :                :                     {
                               2579                 :                :                         /* found it */
 8124 meskes@postgresql.or     2580                 :              9 :                         err = 0;
                               2581                 :              9 :                         pstr += strlen(pgtypes_date_weekdays_short[j]);
                               2582                 :              9 :                         break;
                               2583                 :                :                     }
                               2584                 :             16 :                     j++;
                               2585                 :                :                 }
                               2586                 :              9 :                 break;
 8124 meskes@postgresql.or     2587                 :UBC           0 :             case 'A':
                               2588                 :                :                 /* see note above */
                               2589                 :              0 :                 pfmt++;
 8121 bruce@momjian.us         2590                 :              0 :                 err = 1;
                               2591                 :              0 :                 j = 0;
                               2592         [ #  # ]:              0 :                 while (days[j])
                               2593                 :                :                 {
                               2594         [ #  # ]:              0 :                     if (strncmp(days[j], pstr, strlen(days[j])) == 0)
                               2595                 :                :                     {
                               2596                 :                :                         /* found it */
 8124 meskes@postgresql.or     2597                 :              0 :                         err = 0;
                               2598                 :              0 :                         pstr += strlen(days[j]);
                               2599                 :              0 :                         break;
                               2600                 :                :                     }
                               2601                 :              0 :                     j++;
                               2602                 :                :                 }
                               2603                 :              0 :                 break;
 8124 meskes@postgresql.or     2604                 :CBC          12 :             case 'b':
                               2605                 :                :             case 'h':
                               2606                 :             12 :                 pfmt++;
 8121 bruce@momjian.us         2607                 :             12 :                 err = 1;
                               2608                 :             12 :                 j = 0;
                               2609         [ +  - ]:             74 :                 while (months[j])
                               2610                 :                :                 {
                               2611         [ +  + ]:             74 :                     if (strncmp(months[j], pstr, strlen(months[j])) == 0)
                               2612                 :                :                     {
                               2613                 :                :                         /* found it */
 8124 meskes@postgresql.or     2614                 :             12 :                         err = 0;
                               2615                 :             12 :                         pstr += strlen(months[j]);
 8121 bruce@momjian.us         2616                 :             12 :                         *month = j + 1;
 8124 meskes@postgresql.or     2617                 :             12 :                         break;
                               2618                 :                :                     }
                               2619                 :             62 :                     j++;
                               2620                 :                :                 }
                               2621                 :             12 :                 break;
                               2622                 :              7 :             case 'B':
                               2623                 :                :                 /* see note above */
                               2624                 :              7 :                 pfmt++;
 8121 bruce@momjian.us         2625                 :              7 :                 err = 1;
                               2626                 :              7 :                 j = 0;
                               2627         [ +  - ]:             57 :                 while (pgtypes_date_months[j])
                               2628                 :                :                 {
                               2629         [ +  + ]:             57 :                     if (strncmp(pgtypes_date_months[j], pstr, strlen(pgtypes_date_months[j])) == 0)
                               2630                 :                :                     {
                               2631                 :                :                         /* found it */
 8124 meskes@postgresql.or     2632                 :              7 :                         err = 0;
                               2633                 :              7 :                         pstr += strlen(pgtypes_date_months[j]);
 8121 bruce@momjian.us         2634                 :              7 :                         *month = j + 1;
 8124 meskes@postgresql.or     2635                 :              7 :                         break;
                               2636                 :                :                     }
                               2637                 :             50 :                     j++;
                               2638                 :                :                 }
                               2639                 :              7 :                 break;
 8124 meskes@postgresql.or     2640                 :UBC           0 :             case 'c':
                               2641                 :                :                 /* XXX */
                               2642                 :              0 :                 break;
 8124 meskes@postgresql.or     2643                 :CBC           2 :             case 'C':
                               2644                 :              2 :                 pfmt++;
                               2645                 :              2 :                 scan_type = PGTYPES_TYPE_UINT;
                               2646                 :              2 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2647                 :              2 :                 *year = scan_val.uint_val * 100;
                               2648                 :              2 :                 break;
                               2649                 :             21 :             case 'd':
                               2650                 :                :             case 'e':
                               2651                 :             21 :                 pfmt++;
                               2652                 :             21 :                 scan_type = PGTYPES_TYPE_UINT;
                               2653                 :             21 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2654                 :             21 :                 *day = scan_val.uint_val;
                               2655                 :             21 :                 break;
 8124 meskes@postgresql.or     2656                 :UBC           0 :             case 'D':
                               2657                 :                : 
                               2658                 :                :                 /*
                               2659                 :                :                  * we have to concatenate the strings in order to be able to
                               2660                 :                :                  * find the end of the substitution
                               2661                 :                :                  */
                               2662                 :              0 :                 pfmt++;
                               2663                 :              0 :                 tmp = pgtypes_alloc(strlen("%m/%d/%y") + strlen(pstr) + 1);
  617 michael@paquier.xyz      2664         [ #  # ]:              0 :                 if (!tmp)
                               2665                 :              0 :                     return 1;
 8124 meskes@postgresql.or     2666                 :              0 :                 strcpy(tmp, "%m/%d/%y");
                               2667                 :              0 :                 strcat(tmp, pfmt);
                               2668                 :              0 :                 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
                               2669                 :              0 :                 free(tmp);
                               2670                 :              0 :                 return err;
 8124 meskes@postgresql.or     2671                 :CBC           2 :             case 'm':
                               2672                 :              2 :                 pfmt++;
                               2673                 :              2 :                 scan_type = PGTYPES_TYPE_UINT;
                               2674                 :              2 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2675                 :              2 :                 *month = scan_val.uint_val;
                               2676                 :              2 :                 break;
                               2677                 :              2 :             case 'y':
                               2678                 :                :             case 'g':           /* XXX difference to y (ISO) */
                               2679                 :              2 :                 pfmt++;
                               2680                 :              2 :                 scan_type = PGTYPES_TYPE_UINT;
                               2681                 :              2 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 8121 bruce@momjian.us         2682         [ +  + ]:              2 :                 if (*year < 0)
                               2683                 :                :                 {
                               2684                 :                :                     /* not yet set */
 8124 meskes@postgresql.or     2685                 :              1 :                     *year = scan_val.uint_val;
                               2686                 :                :                 }
                               2687                 :                :                 else
 8121 bruce@momjian.us         2688                 :              1 :                     *year += scan_val.uint_val;
                               2689         [ +  + ]:              2 :                 if (*year < 100)
                               2690                 :              1 :                     *year += 1900;
 8124 meskes@postgresql.or     2691                 :              2 :                 break;
 8124 meskes@postgresql.or     2692                 :UBC           0 :             case 'G':
                               2693                 :                :                 /* XXX difference to %V (ISO) */
                               2694                 :              0 :                 pfmt++;
                               2695                 :              0 :                 scan_type = PGTYPES_TYPE_UINT;
                               2696                 :              0 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2697                 :              0 :                 *year = scan_val.uint_val;
                               2698                 :              0 :                 break;
 8124 meskes@postgresql.or     2699                 :CBC          21 :             case 'H':
                               2700                 :                :             case 'I':
                               2701                 :                :             case 'k':
                               2702                 :                :             case 'l':
                               2703                 :             21 :                 pfmt++;
                               2704                 :             21 :                 scan_type = PGTYPES_TYPE_UINT;
                               2705                 :             21 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2706                 :             21 :                 *hour += scan_val.uint_val;
                               2707                 :             21 :                 break;
 8124 meskes@postgresql.or     2708                 :UBC           0 :             case 'j':
                               2709                 :              0 :                 pfmt++;
                               2710                 :              0 :                 scan_type = PGTYPES_TYPE_UINT;
                               2711                 :              0 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2712                 :                : 
                               2713                 :                :                 /*
                               2714                 :                :                  * XXX what should we do with that? We could say that it's
                               2715                 :                :                  * sufficient if we have the year and the day within the year
                               2716                 :                :                  * to get at least a specific day.
                               2717                 :                :                  */
                               2718                 :              0 :                 break;
 8124 meskes@postgresql.or     2719                 :CBC          20 :             case 'M':
                               2720                 :             20 :                 pfmt++;
                               2721                 :             20 :                 scan_type = PGTYPES_TYPE_UINT;
                               2722                 :             20 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2723                 :             20 :                 *minute = scan_val.uint_val;
                               2724                 :             20 :                 break;
                               2725                 :              2 :             case 'n':
                               2726                 :              2 :                 pfmt++;
 8121 bruce@momjian.us         2727         [ +  - ]:              2 :                 if (*pstr == '\n')
                               2728                 :              2 :                     pstr++;
                               2729                 :                :                 else
 8121 bruce@momjian.us         2730                 :UBC           0 :                     err = 1;
 8124 meskes@postgresql.or     2731                 :CBC           2 :                 break;
                               2732                 :              4 :             case 'p':
                               2733                 :              4 :                 err = 1;
                               2734                 :              4 :                 pfmt++;
 8121 bruce@momjian.us         2735         [ +  + ]:              4 :                 if (strncmp(pstr, "am", 2) == 0)
                               2736                 :                :                 {
                               2737                 :              3 :                     *hour += 0;
                               2738                 :              3 :                     err = 0;
                               2739                 :              3 :                     pstr += 2;
                               2740                 :                :                 }
                               2741         [ -  + ]:              4 :                 if (strncmp(pstr, "a.m.", 4) == 0)
                               2742                 :                :                 {
 8121 bruce@momjian.us         2743                 :UBC           0 :                     *hour += 0;
                               2744                 :              0 :                     err = 0;
                               2745                 :              0 :                     pstr += 4;
                               2746                 :                :                 }
 8121 bruce@momjian.us         2747         [ +  + ]:CBC           4 :                 if (strncmp(pstr, "pm", 2) == 0)
                               2748                 :                :                 {
                               2749                 :              1 :                     *hour += 12;
                               2750                 :              1 :                     err = 0;
                               2751                 :              1 :                     pstr += 2;
                               2752                 :                :                 }
                               2753         [ -  + ]:              4 :                 if (strncmp(pstr, "p.m.", 4) == 0)
                               2754                 :                :                 {
 8121 bruce@momjian.us         2755                 :UBC           0 :                     *hour += 12;
                               2756                 :              0 :                     err = 0;
                               2757                 :              0 :                     pstr += 4;
                               2758                 :                :                 }
 8121 bruce@momjian.us         2759                 :CBC           4 :                 break;
 8124 meskes@postgresql.or     2760                 :              1 :             case 'P':
                               2761                 :              1 :                 err = 1;
                               2762                 :              1 :                 pfmt++;
 8121 bruce@momjian.us         2763         [ -  + ]:              1 :                 if (strncmp(pstr, "AM", 2) == 0)
                               2764                 :                :                 {
 8121 bruce@momjian.us         2765                 :UBC           0 :                     *hour += 0;
                               2766                 :              0 :                     err = 0;
                               2767                 :              0 :                     pstr += 2;
                               2768                 :                :                 }
 8121 bruce@momjian.us         2769         [ -  + ]:CBC           1 :                 if (strncmp(pstr, "A.M.", 4) == 0)
                               2770                 :                :                 {
 8121 bruce@momjian.us         2771                 :UBC           0 :                     *hour += 0;
                               2772                 :              0 :                     err = 0;
                               2773                 :              0 :                     pstr += 4;
                               2774                 :                :                 }
 8121 bruce@momjian.us         2775         [ -  + ]:CBC           1 :                 if (strncmp(pstr, "PM", 2) == 0)
                               2776                 :                :                 {
 8121 bruce@momjian.us         2777                 :UBC           0 :                     *hour += 12;
                               2778                 :              0 :                     err = 0;
                               2779                 :              0 :                     pstr += 2;
                               2780                 :                :                 }
 8121 bruce@momjian.us         2781         [ +  - ]:CBC           1 :                 if (strncmp(pstr, "P.M.", 4) == 0)
                               2782                 :                :                 {
                               2783                 :              1 :                     *hour += 12;
                               2784                 :              1 :                     err = 0;
                               2785                 :              1 :                     pstr += 4;
                               2786                 :                :                 }
 8124 meskes@postgresql.or     2787                 :              1 :                 break;
 8124 meskes@postgresql.or     2788                 :UBC           0 :             case 'r':
                               2789                 :              0 :                 pfmt++;
                               2790                 :              0 :                 tmp = pgtypes_alloc(strlen("%I:%M:%S %p") + strlen(pstr) + 1);
  617 michael@paquier.xyz      2791         [ #  # ]:              0 :                 if (!tmp)
                               2792                 :              0 :                     return 1;
 8124 meskes@postgresql.or     2793                 :              0 :                 strcpy(tmp, "%I:%M:%S %p");
                               2794                 :              0 :                 strcat(tmp, pfmt);
                               2795                 :              0 :                 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
                               2796                 :              0 :                 free(tmp);
                               2797                 :              0 :                 return err;
                               2798                 :              0 :             case 'R':
                               2799                 :              0 :                 pfmt++;
                               2800                 :              0 :                 tmp = pgtypes_alloc(strlen("%H:%M") + strlen(pstr) + 1);
  617 michael@paquier.xyz      2801         [ #  # ]:              0 :                 if (!tmp)
                               2802                 :              0 :                     return 1;
 8124 meskes@postgresql.or     2803                 :              0 :                 strcpy(tmp, "%H:%M");
                               2804                 :              0 :                 strcat(tmp, pfmt);
                               2805                 :              0 :                 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
                               2806                 :              0 :                 free(tmp);
                               2807                 :              0 :                 return err;
 8124 meskes@postgresql.or     2808                 :CBC           1 :             case 's':
                               2809                 :              1 :                 pfmt++;
                               2810                 :              1 :                 scan_type = PGTYPES_TYPE_UINT_LONG;
                               2811                 :              1 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2812                 :                :                 /* number of seconds in scan_val.luint_val */
                               2813                 :                :                 {
                               2814                 :                :                     struct tm  *tms;
                               2815                 :                :                     struct tm   tmbuf;
 8121 bruce@momjian.us         2816                 :              1 :                     time_t      et = (time_t) scan_val.luint_val;
                               2817                 :                : 
  431 peter@eisentraut.org     2818                 :              1 :                     tms = gmtime_r(&et, &tmbuf);
                               2819                 :                : 
 6110 meskes@postgresql.or     2820         [ +  - ]:              1 :                     if (tms)
                               2821                 :                :                     {
                               2822                 :              1 :                         *year = tms->tm_year + 1900;
                               2823                 :              1 :                         *month = tms->tm_mon + 1;
                               2824                 :              1 :                         *day = tms->tm_mday;
                               2825                 :              1 :                         *hour = tms->tm_hour;
                               2826                 :              1 :                         *minute = tms->tm_min;
                               2827                 :              1 :                         *second = tms->tm_sec;
                               2828                 :                :                     }
                               2829                 :                :                     else
 6110 meskes@postgresql.or     2830                 :UBC           0 :                         err = 1;
                               2831                 :                :                 }
 8124 meskes@postgresql.or     2832                 :CBC           1 :                 break;
                               2833                 :             15 :             case 'S':
                               2834                 :             15 :                 pfmt++;
                               2835                 :             15 :                 scan_type = PGTYPES_TYPE_UINT;
                               2836                 :             15 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2837                 :             15 :                 *second = scan_val.uint_val;
                               2838                 :             15 :                 break;
 8124 meskes@postgresql.or     2839                 :UBC           0 :             case 't':
                               2840                 :              0 :                 pfmt++;
 8121 bruce@momjian.us         2841         [ #  # ]:              0 :                 if (*pstr == '\t')
                               2842                 :              0 :                     pstr++;
                               2843                 :                :                 else
                               2844                 :              0 :                     err = 1;
 8124 meskes@postgresql.or     2845                 :              0 :                 break;
                               2846                 :              0 :             case 'T':
                               2847                 :              0 :                 pfmt++;
                               2848                 :              0 :                 tmp = pgtypes_alloc(strlen("%H:%M:%S") + strlen(pstr) + 1);
  617 michael@paquier.xyz      2849         [ #  # ]:              0 :                 if (!tmp)
                               2850                 :              0 :                     return 1;
 8124 meskes@postgresql.or     2851                 :              0 :                 strcpy(tmp, "%H:%M:%S");
                               2852                 :              0 :                 strcat(tmp, pfmt);
                               2853                 :              0 :                 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
                               2854                 :              0 :                 free(tmp);
                               2855                 :              0 :                 return err;
                               2856                 :              0 :             case 'u':
                               2857                 :              0 :                 pfmt++;
                               2858                 :              0 :                 scan_type = PGTYPES_TYPE_UINT;
                               2859                 :              0 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 8121 bruce@momjian.us         2860   [ #  #  #  # ]:              0 :                 if (scan_val.uint_val < 1 || scan_val.uint_val > 7)
                               2861                 :              0 :                     err = 1;
 8124 meskes@postgresql.or     2862                 :              0 :                 break;
                               2863                 :              0 :             case 'U':
                               2864                 :              0 :                 pfmt++;
                               2865                 :              0 :                 scan_type = PGTYPES_TYPE_UINT;
                               2866                 :              0 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 6005                          2867         [ #  # ]:              0 :                 if (scan_val.uint_val > 53)
 8121 bruce@momjian.us         2868                 :              0 :                     err = 1;
 8124 meskes@postgresql.or     2869                 :              0 :                 break;
                               2870                 :              0 :             case 'V':
                               2871                 :              0 :                 pfmt++;
                               2872                 :              0 :                 scan_type = PGTYPES_TYPE_UINT;
                               2873                 :              0 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 8121 bruce@momjian.us         2874   [ #  #  #  # ]:              0 :                 if (scan_val.uint_val < 1 || scan_val.uint_val > 53)
                               2875                 :              0 :                     err = 1;
 8124 meskes@postgresql.or     2876                 :              0 :                 break;
                               2877                 :              0 :             case 'w':
                               2878                 :              0 :                 pfmt++;
                               2879                 :              0 :                 scan_type = PGTYPES_TYPE_UINT;
                               2880                 :              0 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 6005                          2881         [ #  # ]:              0 :                 if (scan_val.uint_val > 6)
 8121 bruce@momjian.us         2882                 :              0 :                     err = 1;
 8124 meskes@postgresql.or     2883                 :              0 :                 break;
                               2884                 :              0 :             case 'W':
                               2885                 :              0 :                 pfmt++;
                               2886                 :              0 :                 scan_type = PGTYPES_TYPE_UINT;
                               2887                 :              0 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 6005                          2888         [ #  # ]:              0 :                 if (scan_val.uint_val > 53)
 8121 bruce@momjian.us         2889                 :              0 :                     err = 1;
 8124 meskes@postgresql.or     2890                 :              0 :                 break;
                               2891                 :              0 :             case 'x':
                               2892                 :                :             case 'X':
                               2893                 :                :                 /* XXX */
                               2894                 :              0 :                 break;
 8124 meskes@postgresql.or     2895                 :CBC          18 :             case 'Y':
                               2896                 :             18 :                 pfmt++;
                               2897                 :             18 :                 scan_type = PGTYPES_TYPE_UINT;
                               2898                 :             18 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
                               2899                 :             18 :                 *year = scan_val.uint_val;
                               2900                 :             18 :                 break;
                               2901                 :              8 :             case 'z':
                               2902                 :              8 :                 pfmt++;
                               2903                 :              8 :                 scan_type = PGTYPES_TYPE_STRING_MALLOCED;
                               2904                 :              8 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 8121 bruce@momjian.us         2905         [ +  - ]:              8 :                 if (!err)
                               2906                 :                :                 {
 8124 meskes@postgresql.or     2907                 :              8 :                     err = DecodeTimezone(scan_val.str_val, tz);
                               2908                 :              8 :                     free(scan_val.str_val);
                               2909                 :                :                 }
                               2910                 :              8 :                 break;
                               2911                 :              4 :             case 'Z':
                               2912                 :              4 :                 pfmt++;
                               2913                 :              4 :                 scan_type = PGTYPES_TYPE_STRING_MALLOCED;
                               2914                 :              4 :                 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
 4030 tgl@sss.pgh.pa.us        2915         [ +  - ]:              4 :                 if (!err)
                               2916                 :                :                 {
                               2917                 :                :                     /*
                               2918                 :                :                      * XXX use DecodeSpecial instead?  Do we need strcasecmp
                               2919                 :                :                      * here?
                               2920                 :                :                      */
                               2921                 :              4 :                     err = 1;
                               2922         [ +  - ]:            200 :                     for (j = 0; j < szdatetktbl; j++)
                               2923                 :                :                     {
                               2924   [ +  +  +  +  :            360 :                         if ((datetktbl[j].type == TZ || datetktbl[j].type == DTZ) &&
                                              +  + ]
                               2925                 :            160 :                             pg_strcasecmp(datetktbl[j].token,
                               2926                 :            160 :                                           scan_val.str_val) == 0)
                               2927                 :                :                         {
                               2928                 :              4 :                             *tz = -datetktbl[j].value;
                               2929                 :              4 :                             err = 0;
                               2930                 :              4 :                             break;
                               2931                 :                :                         }
                               2932                 :                :                     }
                               2933                 :              4 :                     free(scan_val.str_val);
                               2934                 :                :                 }
 8124 meskes@postgresql.or     2935                 :              4 :                 break;
 8124 meskes@postgresql.or     2936                 :UBC           0 :             case '+':
                               2937                 :                :                 /* XXX */
                               2938                 :              0 :                 break;
 8124 meskes@postgresql.or     2939                 :CBC           4 :             case '%':
                               2940                 :              4 :                 pfmt++;
 8121 bruce@momjian.us         2941         [ +  - ]:              4 :                 if (*pstr == '%')
                               2942                 :              4 :                     pstr++;
                               2943                 :                :                 else
 8121 bruce@momjian.us         2944                 :UBC           0 :                     err = 1;
 8124 meskes@postgresql.or     2945                 :CBC           4 :                 break;
                               2946                 :              1 :             default:
                               2947                 :              1 :                 err = 1;
                               2948                 :                :         }
                               2949                 :                :     }
 8121 bruce@momjian.us         2950         [ +  + ]:             22 :     if (!err)
                               2951                 :                :     {
                               2952         [ +  + ]:             21 :         if (*second < 0)
                               2953                 :              5 :             *second = 0;
                               2954         [ -  + ]:             21 :         if (*minute < 0)
 8121 bruce@momjian.us         2955                 :UBC           0 :             *minute = 0;
 8121 bruce@momjian.us         2956         [ -  + ]:CBC          21 :         if (*hour < 0)
 8121 bruce@momjian.us         2957                 :UBC           0 :             *hour = 0;
 8121 bruce@momjian.us         2958         [ -  + ]:CBC          21 :         if (*day < 0)
                               2959                 :                :         {
 8121 bruce@momjian.us         2960                 :UBC           0 :             err = 1;
                               2961                 :              0 :             *day = 1;
                               2962                 :                :         }
 8121 bruce@momjian.us         2963         [ -  + ]:CBC          21 :         if (*month < 0)
                               2964                 :                :         {
 8121 bruce@momjian.us         2965                 :UBC           0 :             err = 1;
                               2966                 :              0 :             *month = 1;
                               2967                 :                :         }
 8121 bruce@momjian.us         2968         [ -  + ]:CBC          21 :         if (*year < 0)
                               2969                 :                :         {
 8121 bruce@momjian.us         2970                 :UBC           0 :             err = 1;
                               2971                 :              0 :             *year = 1970;
                               2972                 :                :         }
                               2973                 :                : 
 8121 bruce@momjian.us         2974         [ -  + ]:CBC          21 :         if (*second > 59)
                               2975                 :                :         {
 8121 bruce@momjian.us         2976                 :UBC           0 :             err = 1;
                               2977                 :              0 :             *second = 0;
                               2978                 :                :         }
 8121 bruce@momjian.us         2979         [ -  + ]:CBC          21 :         if (*minute > 59)
                               2980                 :                :         {
 8121 bruce@momjian.us         2981                 :UBC           0 :             err = 1;
                               2982                 :              0 :             *minute = 0;
                               2983                 :                :         }
 7318 bruce@momjian.us         2984         [ +  - ]:CBC          21 :         if (*hour > 24 ||        /* test for > 24:00:00 */
 7319                          2985   [ -  +  -  -  :             21 :             (*hour == 24 && (*minute > 0 || *second > 0)))
                                              -  - ]
                               2986                 :                :         {
 8121 bruce@momjian.us         2987                 :UBC           0 :             err = 1;
                               2988                 :              0 :             *hour = 0;
                               2989                 :                :         }
 7404 bruce@momjian.us         2990         [ -  + ]:CBC          21 :         if (*month > MONTHS_PER_YEAR)
                               2991                 :                :         {
 8121 bruce@momjian.us         2992                 :UBC           0 :             err = 1;
                               2993                 :              0 :             *month = 1;
                               2994                 :                :         }
 8121 bruce@momjian.us         2995   [ +  +  +  +  :CBC          21 :         if (*day > day_tab[isleap(*year)][*month - 1])
                                        +  +  +  + ]
                               2996                 :                :         {
                               2997   [ +  +  +  +  :              4 :             *day = day_tab[isleap(*year)][*month - 1];
                                              -  + ]
 8124 meskes@postgresql.or     2998                 :              4 :             err = 1;
                               2999                 :                :         }
                               3000                 :                : 
                               3001                 :             21 :         tm.tm_sec = *second;
                               3002                 :             21 :         tm.tm_min = *minute;
                               3003                 :             21 :         tm.tm_hour = *hour;
                               3004                 :             21 :         tm.tm_mday = *day;
                               3005                 :             21 :         tm.tm_mon = *month;
                               3006                 :             21 :         tm.tm_year = *year;
                               3007                 :                : 
                               3008                 :             21 :         tm2timestamp(&tm, 0, tz, d);
                               3009                 :                :     }
                               3010                 :             22 :     return err;
                               3011                 :                : }
                               3012                 :                : 
                               3013                 :                : /* XXX: 1900 is compiled in as the base for years */
        

Generated by: LCOV version 2.4-beta