12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675 |
- /*
- * The MIT License (MIT)
- *
- * Copyright (c) 2015-2019 Derick Rethans
- * Copyright (c) 2018 MongoDB, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- #include "timelib.h"
- #include "timelib_private.h"
- #include <ctype.h>
- #include <math.h>
- #include <assert.h>
- #include <limits.h>
- #if defined(_MSC_VER)
- # define strtoll(s, f, b) _atoi64(s)
- #elif !defined(HAVE_STRTOLL)
- # if defined(HAVE_ATOLL)
- # define strtoll(s, f, b) atoll(s)
- # else
- # define strtoll(s, f, b) strtol(s, f, b)
- # endif
- #endif
- #define EOI 257
- #define TIME 258
- #define DATE 259
- #define TIMELIB_XMLRPC_SOAP 260
- #define TIMELIB_TIME12 261
- #define TIMELIB_TIME24 262
- #define TIMELIB_GNU_NOCOLON 263
- #define TIMELIB_GNU_NOCOLON_TZ 264
- #define TIMELIB_ISO_NOCOLON 265
- #define TIMELIB_AMERICAN 266
- #define TIMELIB_ISO_DATE 267
- #define TIMELIB_DATE_FULL 268
- #define TIMELIB_DATE_TEXT 269
- #define TIMELIB_DATE_NOCOLON 270
- #define TIMELIB_PG_YEARDAY 271
- #define TIMELIB_PG_TEXT 272
- #define TIMELIB_PG_REVERSE 273
- #define TIMELIB_CLF 274
- #define TIMELIB_DATE_NO_DAY 275
- #define TIMELIB_SHORTDATE_WITH_TIME 276
- #define TIMELIB_DATE_FULL_POINTED 277
- #define TIMELIB_TIME24_WITH_ZONE 278
- #define TIMELIB_ISO_WEEK 279
- #define TIMELIB_LF_DAY_OF_MONTH 280
- #define TIMELIB_WEEK_DAY_OF_MONTH 281
- #define TIMELIB_TIMEZONE 300
- #define TIMELIB_AGO 301
- #define TIMELIB_RELATIVE 310
- #define TIMELIB_ERROR 999
- /* Some compilers like AIX, defines uchar in sys/types.h */
- #undef uchar
- typedef unsigned char uchar;
- #define BSIZE 8192
- #define YYCTYPE uchar
- #define YYCURSOR cursor
- #define YYLIMIT s->lim
- #define YYMARKER s->ptr
- #define YYFILL(n) return EOI;
- #define RET(i) {s->cur = cursor; return i;}
- #define timelib_string_free timelib_free
- #define TIMELIB_HAVE_TIME() { if (s->time->have_time) { add_error(s, TIMELIB_ERR_DOUBLE_TIME, "Double time specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_time = 1; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->us = 0; } }
- #define TIMELIB_UNHAVE_TIME() { s->time->have_time = 0; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->us = 0; }
- #define TIMELIB_HAVE_DATE() { if (s->time->have_date) { add_error(s, TIMELIB_ERR_DOUBLE_DATE, "Double date specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_date = 1; } }
- #define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
- #define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; }
- #define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_relative = 1; s->time->relative.have_weekday_relative = 1; }
- #define TIMELIB_HAVE_SPECIAL_RELATIVE() { s->time->have_relative = 1; s->time->relative.have_special_relative = 1; }
- #define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { s->time->have_zone > 1 ? add_error(s, TIMELIB_ERR_DOUBLE_TZ, "Double timezone specification") : add_warning(s, TIMELIB_WARN_DOUBLE_TZ, "Double timezone specification"); timelib_string_free(str); s->time->have_zone++; return TIMELIB_ERROR; } else { s->time->have_zone++; } }
- #define TIMELIB_INIT s->cur = cursor; str = timelib_string(s); ptr = str
- #define TIMELIB_DEINIT timelib_string_free(str)
- #define TIMELIB_ADJUST_RELATIVE_WEEKDAY() if (in->time.have_weekday_relative && (in.rel.d > 0)) { in.rel.d -= 7; }
- #define TIMELIB_PROCESS_YEAR(x, l) { \
- if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
- /* (x) = 0; */ \
- } else if ((x) < 100) { \
- if ((x) < 70) { \
- (x) += 2000; \
- } else { \
- (x) += 1900; \
- } \
- } \
- }
- #ifdef DEBUG_PARSER
- #define DEBUG_OUTPUT(s) printf("%s\n", s);
- #define YYDEBUG(s,c) { if (s != -1) { printf("state: %d ", s); printf("[%c]\n", c); } }
- #else
- #define DEBUG_OUTPUT(s)
- #define YYDEBUG(s,c)
- #endif
- typedef struct _timelib_elems {
- unsigned int c; /* Number of elements */
- char **v; /* Values */
- } timelib_elems;
- typedef struct _Scanner {
- int fd;
- uchar *lim, *str, *ptr, *cur, *tok, *pos;
- unsigned int line, len;
- timelib_error_container *errors;
- timelib_time *time;
- const timelib_tzdb *tzdb;
- } Scanner;
- typedef struct _timelib_lookup_table {
- const char *name;
- int type;
- int value;
- } timelib_lookup_table;
- typedef struct _timelib_relunit {
- const char *name;
- int unit;
- int multiplier;
- } timelib_relunit;
- /* The timezone table. */
- static const timelib_tz_lookup_table timelib_timezone_lookup[] = {
- #include "timezonemap.h"
- { NULL, 0, 0, NULL },
- };
- static const timelib_tz_lookup_table timelib_timezone_fallbackmap[] = {
- #include "fallbackmap.h"
- { NULL, 0, 0, NULL },
- };
- static const timelib_tz_lookup_table timelib_timezone_utc[] = {
- { "utc", 0, 0, "UTC" },
- };
- #if defined(_POSIX_TZNAME_MAX)
- # define MAX_ABBR_LEN _POSIX_TZNAME_MAX
- #elif defined(TZNAME_MAX)
- # define MAX_ABBR_LEN TZNAME_MAX
- #else
- # define MAX_ABBR_LEN 6
- #endif
- static timelib_relunit const timelib_relunit_lookup[] = {
- { "ms", TIMELIB_MICROSEC, 1000 },
- { "msec", TIMELIB_MICROSEC, 1000 },
- { "msecs", TIMELIB_MICROSEC, 1000 },
- { "millisecond", TIMELIB_MICROSEC, 1000 },
- { "milliseconds", TIMELIB_MICROSEC, 1000 },
- { "µs", TIMELIB_MICROSEC, 1 },
- { "usec", TIMELIB_MICROSEC, 1 },
- { "usecs", TIMELIB_MICROSEC, 1 },
- { "µsec", TIMELIB_MICROSEC, 1 },
- { "µsecs", TIMELIB_MICROSEC, 1 },
- { "microsecond", TIMELIB_MICROSEC, 1 },
- { "microseconds", TIMELIB_MICROSEC, 1 },
- { "sec", TIMELIB_SECOND, 1 },
- { "secs", TIMELIB_SECOND, 1 },
- { "second", TIMELIB_SECOND, 1 },
- { "seconds", TIMELIB_SECOND, 1 },
- { "min", TIMELIB_MINUTE, 1 },
- { "mins", TIMELIB_MINUTE, 1 },
- { "minute", TIMELIB_MINUTE, 1 },
- { "minutes", TIMELIB_MINUTE, 1 },
- { "hour", TIMELIB_HOUR, 1 },
- { "hours", TIMELIB_HOUR, 1 },
- { "day", TIMELIB_DAY, 1 },
- { "days", TIMELIB_DAY, 1 },
- { "week", TIMELIB_DAY, 7 },
- { "weeks", TIMELIB_DAY, 7 },
- { "fortnight", TIMELIB_DAY, 14 },
- { "fortnights", TIMELIB_DAY, 14 },
- { "forthnight", TIMELIB_DAY, 14 },
- { "forthnights", TIMELIB_DAY, 14 },
- { "month", TIMELIB_MONTH, 1 },
- { "months", TIMELIB_MONTH, 1 },
- { "year", TIMELIB_YEAR, 1 },
- { "years", TIMELIB_YEAR, 1 },
- { "mondays", TIMELIB_WEEKDAY, 1 },
- { "monday", TIMELIB_WEEKDAY, 1 },
- { "mon", TIMELIB_WEEKDAY, 1 },
- { "tuesdays", TIMELIB_WEEKDAY, 2 },
- { "tuesday", TIMELIB_WEEKDAY, 2 },
- { "tue", TIMELIB_WEEKDAY, 2 },
- { "wednesdays", TIMELIB_WEEKDAY, 3 },
- { "wednesday", TIMELIB_WEEKDAY, 3 },
- { "wed", TIMELIB_WEEKDAY, 3 },
- { "thursdays", TIMELIB_WEEKDAY, 4 },
- { "thursday", TIMELIB_WEEKDAY, 4 },
- { "thu", TIMELIB_WEEKDAY, 4 },
- { "fridays", TIMELIB_WEEKDAY, 5 },
- { "friday", TIMELIB_WEEKDAY, 5 },
- { "fri", TIMELIB_WEEKDAY, 5 },
- { "saturdays", TIMELIB_WEEKDAY, 6 },
- { "saturday", TIMELIB_WEEKDAY, 6 },
- { "sat", TIMELIB_WEEKDAY, 6 },
- { "sundays", TIMELIB_WEEKDAY, 0 },
- { "sunday", TIMELIB_WEEKDAY, 0 },
- { "sun", TIMELIB_WEEKDAY, 0 },
- { "weekday", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
- { "weekdays", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
- { NULL, 0, 0 }
- };
- /* The relative text table. */
- static timelib_lookup_table const timelib_reltext_lookup[] = {
- { "first", 0, 1 },
- { "next", 0, 1 },
- { "second", 0, 2 },
- { "third", 0, 3 },
- { "fourth", 0, 4 },
- { "fifth", 0, 5 },
- { "sixth", 0, 6 },
- { "seventh", 0, 7 },
- { "eight", 0, 8 },
- { "eighth", 0, 8 },
- { "ninth", 0, 9 },
- { "tenth", 0, 10 },
- { "eleventh", 0, 11 },
- { "twelfth", 0, 12 },
- { "last", 0, -1 },
- { "previous", 0, -1 },
- { "this", 1, 0 },
- { NULL, 1, 0 }
- };
- /* The month table. */
- static timelib_lookup_table const timelib_month_lookup[] = {
- { "jan", 0, 1 },
- { "feb", 0, 2 },
- { "mar", 0, 3 },
- { "apr", 0, 4 },
- { "may", 0, 5 },
- { "jun", 0, 6 },
- { "jul", 0, 7 },
- { "aug", 0, 8 },
- { "sep", 0, 9 },
- { "sept", 0, 9 },
- { "oct", 0, 10 },
- { "nov", 0, 11 },
- { "dec", 0, 12 },
- { "i", 0, 1 },
- { "ii", 0, 2 },
- { "iii", 0, 3 },
- { "iv", 0, 4 },
- { "v", 0, 5 },
- { "vi", 0, 6 },
- { "vii", 0, 7 },
- { "viii", 0, 8 },
- { "ix", 0, 9 },
- { "x", 0, 10 },
- { "xi", 0, 11 },
- { "xii", 0, 12 },
- { "january", 0, 1 },
- { "february", 0, 2 },
- { "march", 0, 3 },
- { "april", 0, 4 },
- { "may", 0, 5 },
- { "june", 0, 6 },
- { "july", 0, 7 },
- { "august", 0, 8 },
- { "september", 0, 9 },
- { "october", 0, 10 },
- { "november", 0, 11 },
- { "december", 0, 12 },
- { NULL, 0, 0 }
- };
- #if 0
- static char* timelib_ltrim(char *s)
- {
- char *ptr = s;
- while (ptr[0] == ' ' || ptr[0] == '\t') {
- ptr++;
- }
- return ptr;
- }
- #endif
- #if 0
- uchar *fill(Scanner *s, uchar *cursor){
- if(!s->eof){
- unsigned int cnt = s->tok - s->bot;
- if(cnt){
- memcpy(s->bot, s->tok, s->lim - s->tok);
- s->tok = s->bot;
- s->ptr -= cnt;
- cursor -= cnt;
- s->pos -= cnt;
- s->lim -= cnt;
- }
- if((s->top - s->lim) < BSIZE){
- uchar *buf = (uchar*) timelib_malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
- memcpy(buf, s->tok, s->lim - s->tok);
- s->tok = buf;
- s->ptr = &buf[s->ptr - s->bot];
- cursor = &buf[cursor - s->bot];
- s->pos = &buf[s->pos - s->bot];
- s->lim = &buf[s->lim - s->bot];
- s->top = &s->lim[BSIZE];
- timelib_free(s->bot);
- s->bot = buf;
- }
- if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
- s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
- }
- s->lim += cnt;
- }
- return cursor;
- }
- #endif
- static timelib_error_message *alloc_error_message(timelib_error_message **messages, int *count)
- {
- /* Realloc in power of two increments */
- int is_pow2 = (*count & (*count - 1)) == 0;
- if (is_pow2) {
- size_t alloc_size = *count ? (*count * 2) : 1;
- *messages = timelib_realloc(*messages, alloc_size * sizeof(timelib_error_message));
- }
- return *messages + (*count)++;
- }
- static void add_warning(Scanner *s, int error_code, const char *error)
- {
- timelib_error_message *message = alloc_error_message(&s->errors->warning_messages, &s->errors->warning_count);
- message->error_code = error_code;
- message->position = s->tok ? s->tok - s->str : 0;
- message->character = s->tok ? *s->tok : 0;
- message->message = timelib_strdup(error);
- }
- static void add_error(Scanner *s, int error_code, const char *error)
- {
- timelib_error_message *message = alloc_error_message(&s->errors->error_messages, &s->errors->error_count);
- message->error_code = error_code;
- message->position = s->tok ? s->tok - s->str : 0;
- message->character = s->tok ? *s->tok : 0;
- message->message = timelib_strdup(error);
- }
- static void add_pbf_warning(Scanner *s, int error_code, const char *error, const char *sptr, const char *cptr)
- {
- timelib_error_message *message = alloc_error_message(&s->errors->warning_messages, &s->errors->warning_count);
- message->error_code = error_code;
- message->position = cptr - sptr;
- message->character = *cptr;
- message->message = timelib_strdup(error);
- }
- static void add_pbf_error(Scanner *s, int error_code, const char *error, const char *sptr, const char *cptr)
- {
- timelib_error_message *message = alloc_error_message(&s->errors->error_messages, &s->errors->error_count);
- message->error_code = error_code;
- message->position = cptr - sptr;
- message->character = *cptr;
- message->message = timelib_strdup(error);
- }
- static timelib_sll timelib_meridian(const char **ptr, timelib_sll h)
- {
- timelib_sll retval = 0;
- while (!strchr("AaPp", **ptr)) {
- ++*ptr;
- }
- if (**ptr == 'a' || **ptr == 'A') {
- if (h == 12) {
- retval = -12;
- }
- } else if (h != 12) {
- retval = 12;
- }
- ++*ptr;
- if (**ptr == '.') {
- ++*ptr;
- }
- if (**ptr == 'M' || **ptr == 'm') {
- ++*ptr;
- }
- if (**ptr == '.') {
- ++*ptr;
- }
- return retval;
- }
- static timelib_sll timelib_meridian_with_check(const char **ptr, timelib_sll h)
- {
- timelib_sll retval = 0;
- while (**ptr && !strchr("AaPp", **ptr)) {
- ++*ptr;
- }
- if(!**ptr) {
- return TIMELIB_UNSET;
- }
- if (**ptr == 'a' || **ptr == 'A') {
- if (h == 12) {
- retval = -12;
- }
- } else if (h != 12) {
- retval = 12;
- }
- ++*ptr;
- if (**ptr == '.') {
- ++*ptr;
- if (**ptr != 'm' && **ptr != 'M') {
- return TIMELIB_UNSET;
- }
- ++*ptr;
- if (**ptr != '.' ) {
- return TIMELIB_UNSET;
- }
- ++*ptr;
- } else if (**ptr == 'm' || **ptr == 'M') {
- ++*ptr;
- } else {
- return TIMELIB_UNSET;
- }
- return retval;
- }
- static char *timelib_string(Scanner *s)
- {
- char *tmp = timelib_calloc(1, s->cur - s->tok + 1);
- memcpy(tmp, s->tok, s->cur - s->tok);
- return tmp;
- }
- static timelib_sll timelib_get_nr_ex(const char **ptr, int max_length, int *scanned_length)
- {
- const char *begin, *end;
- char *str;
- timelib_sll tmp_nr = TIMELIB_UNSET;
- int len = 0;
- while ((**ptr < '0') || (**ptr > '9')) {
- if (**ptr == '\0') {
- return TIMELIB_UNSET;
- }
- ++*ptr;
- }
- begin = *ptr;
- while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) {
- ++*ptr;
- ++len;
- }
- end = *ptr;
- if (scanned_length) {
- *scanned_length = end - begin;
- }
- str = timelib_calloc(1, end - begin + 1);
- memcpy(str, begin, end - begin);
- tmp_nr = strtoll(str, NULL, 10);
- timelib_free(str);
- return tmp_nr;
- }
- static timelib_sll timelib_get_nr(const char **ptr, int max_length)
- {
- return timelib_get_nr_ex(ptr, max_length, NULL);
- }
- static void timelib_skip_day_suffix(const char **ptr)
- {
- if (isspace(**ptr)) {
- return;
- }
- if (!timelib_strncasecmp(*ptr, "nd", 2) || !timelib_strncasecmp(*ptr, "rd", 2) ||!timelib_strncasecmp(*ptr, "st", 2) || !timelib_strncasecmp(*ptr, "th", 2)) {
- *ptr += 2;
- }
- }
- static timelib_sll timelib_get_frac_nr(const char **ptr)
- {
- const char *begin, *end;
- char *str;
- double tmp_nr = TIMELIB_UNSET;
- while ((**ptr != '.') && (**ptr != ':') && ((**ptr < '0') || (**ptr > '9'))) {
- if (**ptr == '\0') {
- return TIMELIB_UNSET;
- }
- ++*ptr;
- }
- begin = *ptr;
- while ((**ptr == '.') || (**ptr == ':') || ((**ptr >= '0') && (**ptr <= '9'))) {
- ++*ptr;
- }
- end = *ptr;
- str = timelib_calloc(1, end - begin);
- memcpy(str, begin + 1, end - begin - 1);
- tmp_nr = strtod(str, NULL) * pow(10, 7 - (end - begin));
- timelib_free(str);
- return tmp_nr;
- }
- static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_length)
- {
- timelib_ull dir = 1;
- while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
- if (**ptr == '\0') {
- add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data");
- return 0;
- }
- ++*ptr;
- }
- while (**ptr == '+' || **ptr == '-')
- {
- if (**ptr == '-') {
- dir *= -1;
- }
- ++*ptr;
- }
- return dir * timelib_get_nr(ptr, max_length);
- }
- static timelib_sll timelib_lookup_relative_text(const char **ptr, int *behavior)
- {
- char *word;
- const char *begin = *ptr, *end;
- timelib_sll value = 0;
- const timelib_lookup_table *tp;
- while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
- ++*ptr;
- }
- end = *ptr;
- word = timelib_calloc(1, end - begin + 1);
- memcpy(word, begin, end - begin);
- for (tp = timelib_reltext_lookup; tp->name; tp++) {
- if (timelib_strcasecmp(word, tp->name) == 0) {
- value = tp->value;
- *behavior = tp->type;
- }
- }
- timelib_free(word);
- return value;
- }
- static timelib_sll timelib_get_relative_text(const char **ptr, int *behavior)
- {
- while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '/') {
- ++*ptr;
- }
- return timelib_lookup_relative_text(ptr, behavior);
- }
- static timelib_long timelib_lookup_month(const char **ptr)
- {
- char *word;
- const char *begin = *ptr, *end;
- timelib_long value = 0;
- const timelib_lookup_table *tp;
- while ((**ptr >= 'A' && **ptr <= 'Z') || (**ptr >= 'a' && **ptr <= 'z')) {
- ++*ptr;
- }
- end = *ptr;
- word = timelib_calloc(1, end - begin + 1);
- memcpy(word, begin, end - begin);
- for (tp = timelib_month_lookup; tp->name; tp++) {
- if (timelib_strcasecmp(word, tp->name) == 0) {
- value = tp->value;
- }
- }
- timelib_free(word);
- return value;
- }
- static timelib_long timelib_get_month(const char **ptr)
- {
- while (**ptr == ' ' || **ptr == '\t' || **ptr == '-' || **ptr == '.' || **ptr == '/') {
- ++*ptr;
- }
- return timelib_lookup_month(ptr);
- }
- static void timelib_eat_spaces(const char **ptr)
- {
- while (**ptr == ' ' || **ptr == '\t') {
- ++*ptr;
- }
- }
- static void timelib_eat_until_separator(const char **ptr)
- {
- ++*ptr;
- while (strchr(" \t.,:;/-0123456789", **ptr) == NULL) {
- ++*ptr;
- }
- }
- static const timelib_relunit* timelib_lookup_relunit(const char **ptr)
- {
- char *word;
- const char *begin = *ptr, *end;
- const timelib_relunit *tp, *value = NULL;
- while (**ptr != '\0' && **ptr != ' ' && **ptr != ',' && **ptr != '\t' && **ptr != ';' && **ptr != ':' &&
- **ptr != '/' && **ptr != '.' && **ptr != '-' && **ptr != '(' && **ptr != ')' ) {
- ++*ptr;
- }
- end = *ptr;
- word = timelib_calloc(1, end - begin + 1);
- memcpy(word, begin, end - begin);
- for (tp = timelib_relunit_lookup; tp->name; tp++) {
- if (timelib_strcasecmp(word, tp->name) == 0) {
- value = tp;
- break;
- }
- }
- timelib_free(word);
- return value;
- }
- /**
- * The time_part parameter is a flag. It can be TIMELIB_TIME_PART_KEEP in case
- * the time portion should not be reset to midnight, or
- * TIMELIB_TIME_PART_DONT_KEEP in case it does need to be reset. This is used
- * for not overwriting the time portion for 'X weekday'.
- */
- static void timelib_set_relative(const char **ptr, timelib_sll amount, int behavior, Scanner *s, int time_part)
- {
- const timelib_relunit* relunit;
- if (!(relunit = timelib_lookup_relunit(ptr))) {
- return;
- }
- switch (relunit->unit) {
- case TIMELIB_MICROSEC: s->time->relative.us += amount * relunit->multiplier; break;
- case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break;
- case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break;
- case TIMELIB_HOUR: s->time->relative.h += amount * relunit->multiplier; break;
- case TIMELIB_DAY: s->time->relative.d += amount * relunit->multiplier; break;
- case TIMELIB_MONTH: s->time->relative.m += amount * relunit->multiplier; break;
- case TIMELIB_YEAR: s->time->relative.y += amount * relunit->multiplier; break;
- case TIMELIB_WEEKDAY:
- TIMELIB_HAVE_WEEKDAY_RELATIVE();
- if (time_part != TIMELIB_TIME_PART_KEEP) {
- TIMELIB_UNHAVE_TIME();
- }
- s->time->relative.d += (amount > 0 ? amount - 1 : amount) * 7;
- s->time->relative.weekday = relunit->multiplier;
- s->time->relative.weekday_behavior = behavior;
- break;
- case TIMELIB_SPECIAL:
- TIMELIB_HAVE_SPECIAL_RELATIVE();
- if (time_part != TIMELIB_TIME_PART_KEEP) {
- TIMELIB_UNHAVE_TIME();
- }
- s->time->relative.special.type = relunit->multiplier;
- s->time->relative.special.amount = amount;
- }
- }
- static const timelib_tz_lookup_table* abbr_search(const char *word, timelib_long gmtoffset, int isdst)
- {
- int first_found = 0;
- const timelib_tz_lookup_table *tp, *first_found_elem = NULL;
- const timelib_tz_lookup_table *fmp;
- if (timelib_strcasecmp("utc", word) == 0 || timelib_strcasecmp("gmt", word) == 0) {
- return timelib_timezone_utc;
- }
- for (tp = timelib_timezone_lookup; tp->name; tp++) {
- if (timelib_strcasecmp(word, tp->name) == 0) {
- if (!first_found) {
- first_found = 1;
- first_found_elem = tp;
- if (gmtoffset == -1) {
- return tp;
- }
- }
- if (tp->gmtoffset == gmtoffset) {
- return tp;
- }
- }
- }
- if (first_found) {
- return first_found_elem;
- }
- /* Still didn't find anything, let's find the zone solely based on
- * offset/isdst then */
- for (fmp = timelib_timezone_fallbackmap; fmp->name; fmp++) {
- if (fmp->gmtoffset == gmtoffset && fmp->type == isdst) {
- return fmp;
- }
- }
- return NULL;
- }
- static timelib_long timelib_lookup_abbr(const char **ptr, int *dst, char **tz_abbr, int *found)
- {
- char *word;
- const char *begin = *ptr, *end;
- timelib_long value = 0;
- const timelib_tz_lookup_table *tp;
- while (**ptr != '\0' && **ptr != ')' && **ptr != ' ') {
- ++*ptr;
- }
- end = *ptr;
- word = timelib_calloc(1, end - begin + 1);
- memcpy(word, begin, end - begin);
- if (end - begin < MAX_ABBR_LEN && (tp = abbr_search(word, -1, 0))) {
- value = tp->gmtoffset;
- *dst = tp->type;
- value -= tp->type * 3600;
- *found = 1;
- } else {
- *found = 0;
- }
- *tz_abbr = word;
- return value;
- }
- #define sHOUR(a) (int)(a * 3600)
- #define sMIN(a) (int)(a * 60)
- static timelib_long timelib_parse_tz_cor(const char **ptr, int *tz_not_found)
- {
- const char *begin = *ptr, *end;
- timelib_long tmp;
- *tz_not_found = 1;
- while (isdigit(**ptr) || **ptr == ':') {
- ++*ptr;
- }
- end = *ptr;
- switch (end - begin) {
- case 1: /* H */
- case 2: /* HH */
- *tz_not_found = 0;
- return sHOUR(strtol(begin, NULL, 10));
- case 3: /* H:M */
- case 4: /* H:MM, HH:M, HHMM */
- if (begin[1] == ':') {
- *tz_not_found = 0;
- tmp = sHOUR(strtol(begin, NULL, 10)) + sMIN(strtol(begin + 2, NULL, 10));
- return tmp;
- } else if (begin[2] == ':') {
- *tz_not_found = 0;
- tmp = sHOUR(strtol(begin, NULL, 10)) + sMIN(strtol(begin + 3, NULL, 10));
- return tmp;
- } else {
- *tz_not_found = 0;
- tmp = strtol(begin, NULL, 10);
- return sHOUR(tmp / 100) + sMIN(tmp % 100);
- }
- case 5: /* HH:MM */
- if (begin[2] != ':') {
- break;
- }
- *tz_not_found = 0;
- tmp = sHOUR(strtol(begin, NULL, 10)) + sMIN(strtol(begin + 3, NULL, 10));
- return tmp;
- case 6: /* HHMMSS */
- *tz_not_found = 0;
- tmp = strtol(begin, NULL, 10);
- tmp = sHOUR(tmp / 10000) + sMIN((tmp / 100) % 100) + (tmp % 100);
- return tmp;
- case 8: /* HH:MM:SS */
- if (begin[2] != ':' || begin[5] != ':') {
- break;
- }
- *tz_not_found = 0;
- tmp = sHOUR(strtol(begin, NULL, 10)) + sMIN(strtol(begin + 3, NULL, 10)) + strtol(begin + 6, NULL, 10);
- return tmp;
- }
- return 0;
- }
- static timelib_long timelib_parse_tz_minutes(const char **ptr, timelib_time *t)
- {
- timelib_long retval = TIMELIB_UNSET;
- const char *begin = *ptr;
- /* First character must be +/- */
- if (**ptr != '+' && **ptr != '-') {
- return retval;
- }
- ++*ptr;
- while (isdigit(**ptr)) {
- ++*ptr;
- }
- if (*begin == '+') {
- t->is_localtime = 1;
- t->zone_type = TIMELIB_ZONETYPE_OFFSET;
- t->dst = 0;
- retval = sMIN(strtol(begin + 1, NULL, 10));
- } else if (*begin == '-') {
- t->is_localtime = 1;
- t->zone_type = TIMELIB_ZONETYPE_OFFSET;
- t->dst = 0;
- retval = -1 * sMIN(strtol(begin + 1, NULL, 10));
- }
- return retval;
- }
- timelib_long timelib_parse_zone(const char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper)
- {
- timelib_tzinfo *res;
- timelib_long retval = 0;
- *tz_not_found = 0;
- while (**ptr == ' ' || **ptr == '\t' || **ptr == '(') {
- ++*ptr;
- }
- if ((*ptr)[0] == 'G' && (*ptr)[1] == 'M' && (*ptr)[2] == 'T' && ((*ptr)[3] == '+' || (*ptr)[3] == '-')) {
- *ptr += 3;
- }
- if (**ptr == '+') {
- ++*ptr;
- t->is_localtime = 1;
- t->zone_type = TIMELIB_ZONETYPE_OFFSET;
- t->dst = 0;
- retval = timelib_parse_tz_cor(ptr, tz_not_found);
- } else if (**ptr == '-') {
- ++*ptr;
- t->is_localtime = 1;
- t->zone_type = TIMELIB_ZONETYPE_OFFSET;
- t->dst = 0;
- retval = -1 * timelib_parse_tz_cor(ptr, tz_not_found);
- } else {
- int found = 0;
- timelib_long offset = 0;
- char *tz_abbr;
- t->is_localtime = 1;
- /* First, we lookup by abbreviation only */
- offset = timelib_lookup_abbr(ptr, dst, &tz_abbr, &found);
- if (found) {
- t->zone_type = TIMELIB_ZONETYPE_ABBR;
- t->dst = *dst;
- timelib_time_tz_abbr_update(t, tz_abbr);
- }
- /* Otherwise, we look if we have a TimeZone identifier */
- if (!found || strcmp("UTC", tz_abbr) == 0) {
- int dummy_error_code;
- if ((res = tz_wrapper(tz_abbr, tzdb, &dummy_error_code)) != NULL) {
- t->tz_info = res;
- t->zone_type = TIMELIB_ZONETYPE_ID;
- found++;
- }
- }
- timelib_free(tz_abbr);
- *tz_not_found = (found == 0);
- retval = offset;
- }
- while (**ptr == ')') {
- ++*ptr;
- }
- return retval;
- }
- #define timelib_split_free(arg) { \
- int i; \
- for (i = 0; i < arg.c; i++) { \
- timelib_free(arg.v[i]); \
- } \
- if (arg.v) { \
- timelib_free(arg.v); \
- } \
- }
- static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
- {
- uchar *cursor = s->cur;
- char *str;
- const char *ptr = NULL;
- std:
- s->tok = cursor;
- s->len = 0;
- /*!re2c
- any = [\000-\377];
- space = [ \t]+;
- frac = "."[0-9]+;
- ago = 'ago';
- hour24 = [01]?[0-9] | "2"[0-4];
- hour24lz = [01][0-9] | "2"[0-4];
- hour12 = "0"?[1-9] | "1"[0-2];
- minute = [0-5]?[0-9];
- minutelz = [0-5][0-9];
- second = minute | "60";
- secondlz = minutelz | "60";
- meridian = ([AaPp] "."? [Mm] "."?) [\000\t ];
- tz = "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/-][A-Za-z]+)+;
- tzcorrection = "GMT"? [+-] ((hour24 (":"? minute)?) | (hour24lz minutelz secondlz) | (hour24lz ":" minutelz ":" secondlz));
- daysuf = "st" | "nd" | "rd" | "th";
- month = "0"? [0-9] | "1"[0-2];
- day = (([0-2]?[0-9]) | ("3"[01])) daysuf?;
- year = [0-9]{1,4};
- year2 = [0-9]{2};
- year4 = [0-9]{4};
- year4withsign = [+-]? [0-9]{4};
- yearx = [+-] [0-9]{5,19};
- dayofyear = "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6];
- weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
- monthlz = "0" [0-9] | "1" [0-2];
- daylz = "0" [0-9] | [1-2][0-9] | "3" [01];
- dayfulls = 'sundays' | 'mondays' | 'tuesdays' | 'wednesdays' | 'thursdays' | 'fridays' | 'saturdays';
- dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
- dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
- dayspecial = 'weekday' | 'weekdays';
- daytext = dayfulls | dayfull | dayabbr | dayspecial;
- monthfull = 'january' | 'february' | 'march' | 'april' | 'may' | 'june' | 'july' | 'august' | 'september' | 'october' | 'november' | 'december';
- monthabbr = 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec';
- monthroman = "I" | "II" | "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII";
- monthtext = monthfull | monthabbr | monthroman;
- /* Time formats */
- timetiny12 = hour12 space? meridian;
- timeshort12 = hour12[:.]minutelz space? meridian;
- timelong12 = hour12[:.]minute[:.]secondlz space? meridian;
- timetiny24 = 't' hour24;
- timeshort24 = 't'? hour24[:.]minute;
- timelong24 = 't'? hour24[:.]minute[:.]second;
- iso8601long = 't'? hour24 [:.] minute [:.] second frac;
- /* iso8601shorttz = hour24 [:] minutelz space? (tzcorrection | tz); */
- iso8601normtz = 't'? hour24 [:.] minute [:.] secondlz space? (tzcorrection | tz);
- /* iso8601longtz = hour24 [:] minute [:] secondlz frac space? (tzcorrection | tz); */
- gnunocolon = 't'? hour24lz minutelz;
- /* gnunocolontz = hour24lz minutelz space? (tzcorrection | tz); */
- iso8601nocolon = 't'? hour24lz minutelz secondlz;
- /* iso8601nocolontz = hour24lz minutelz secondlz space? (tzcorrection | tz); */
- /* Date formats */
- americanshort = month "/" day;
- american = month "/" day "/" year;
- iso8601dateslash = year4 "/" monthlz "/" daylz "/"?;
- dateslash = year4 "/" month "/" day;
- iso8601date4 = year4withsign "-" monthlz "-" daylz;
- iso8601date2 = year2 "-" monthlz "-" daylz;
- iso8601datex = yearx "-" monthlz "-" daylz;
- gnudateshorter = year4 "-" month;
- gnudateshort = year "-" month "-" day;
- pointeddate4 = day [.\t-] month [.-] year4;
- pointeddate2 = day [.\t] month "." year2;
- datefull = day ([ \t.-])* monthtext ([ \t.-])* year;
- datenoday = monthtext ([ .\t-])* year4;
- datenodayrev = year4 ([ .\t-])* monthtext;
- datetextual = monthtext ([ .\t-])* day [,.stndrh\t ]+ year;
- datenoyear = monthtext ([ .\t-])* day ([,.stndrh\t ]+|[\000]);
- datenoyearrev = day ([ .\t-])* monthtext;
- datenocolon = year4 monthlz daylz;
- /* Special formats */
- soap = year4 "-" monthlz "-" daylz "T" hour24lz ":" minutelz ":" secondlz frac tzcorrection?;
- xmlrpc = year4 monthlz daylz "T" hour24 ":" minutelz ":" secondlz;
- xmlrpcnocolon = year4 monthlz daylz 't' hour24 minutelz secondlz;
- wddx = year4 "-" month "-" day "T" hour24 ":" minute ":" second;
- pgydotd = year4 [.-]? dayofyear;
- pgtextshort = monthabbr "-" daylz "-" year;
- pgtextreverse = year "-" monthabbr "-" daylz;
- mssqltime = hour12 ":" minutelz ":" secondlz [:.] [0-9]+ meridian;
- isoweekday = year4 "-"? "W" weekofyear "-"? [0-7];
- isoweek = year4 "-"? "W" weekofyear;
- exif = year4 ":" monthlz ":" daylz " " hour24lz ":" minutelz ":" secondlz;
- firstdayof = 'first day of';
- lastdayof = 'last day of';
- backof = 'back of ' hour24 (space? meridian)?;
- frontof = 'front of ' hour24 (space? meridian)?;
- /* Common Log Format: 10/Oct/2000:13:55:36 -0700 */
- clf = day "/" monthabbr "/" year4 ":" hour24lz ":" minutelz ":" secondlz space tzcorrection;
- /* Timestamp format: @1126396800 */
- timestamp = "@" "-"? [0-9]+;
- timestampms = "@" "-"? [0-9]+ "." [0-9]{0,6};
- /* To fix some ambiguities */
- dateshortwithtimeshort12 = datenoyear timeshort12;
- dateshortwithtimelong12 = datenoyear timelong12;
- dateshortwithtimeshort = datenoyear timeshort24;
- dateshortwithtimelong = datenoyear timelong24;
- dateshortwithtimelongtz = datenoyear iso8601normtz;
- /*
- * Relative regexps
- */
- reltextnumber = 'first'|'second'|'third'|'fourth'|'fifth'|'sixth'|'seventh'|'eight'|'eighth'|'ninth'|'tenth'|'eleventh'|'twelfth';
- reltexttext = 'next'|'last'|'previous'|'this';
- reltextunit = 'ms' | 'µs' | (('msec'|'millisecond'|'µsec'|'microsecond'|'usec'|'sec'|'second'|'min'|'minute'|'hour'|'day'|'fortnight'|'forthnight'|'month'|'year') 's'?) | 'weeks' | daytext;
- relnumber = ([+-]*[ \t]*[0-9]{1,13});
- relative = relnumber space? (reltextunit | 'week' );
- relativetext = (reltextnumber|reltexttext) space reltextunit;
- relativetextweek = reltexttext space 'week';
- weekdayof = (reltextnumber|reltexttext) space (dayfulls|dayfull|dayabbr) space 'of';
- */
- /*!re2c
- /* so that vim highlights correctly */
- 'yesterday'
- {
- DEBUG_OUTPUT("yesterday");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- TIMELIB_UNHAVE_TIME();
- s->time->relative.d = -1;
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- 'now'
- {
- DEBUG_OUTPUT("now");
- TIMELIB_INIT;
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- 'noon'
- {
- DEBUG_OUTPUT("noon");
- TIMELIB_INIT;
- TIMELIB_UNHAVE_TIME();
- TIMELIB_HAVE_TIME();
- s->time->h = 12;
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- 'midnight' | 'today'
- {
- DEBUG_OUTPUT("midnight | today");
- TIMELIB_INIT;
- TIMELIB_UNHAVE_TIME();
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- 'tomorrow'
- {
- DEBUG_OUTPUT("tomorrow");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- TIMELIB_UNHAVE_TIME();
- s->time->relative.d = 1;
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- timestamp
- {
- timelib_ull i;
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- TIMELIB_UNHAVE_DATE();
- TIMELIB_UNHAVE_TIME();
- TIMELIB_HAVE_TZ();
- i = timelib_get_signed_nr(s, &ptr, 24);
- s->time->y = 1970;
- s->time->m = 1;
- s->time->d = 1;
- s->time->h = s->time->i = s->time->s = 0;
- s->time->us = 0;
- s->time->relative.s += i;
- s->time->is_localtime = 1;
- s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
- s->time->z = 0;
- s->time->dst = 0;
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- timestampms
- {
- timelib_sll i;
- timelib_ull us;
- const char *ptr_before;
- bool is_negative;
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- TIMELIB_UNHAVE_DATE();
- TIMELIB_UNHAVE_TIME();
- TIMELIB_HAVE_TZ();
- is_negative = *(ptr + 1) == '-';
- i = timelib_get_signed_nr(s, &ptr, 24);
- ptr_before = ptr;
- us = timelib_get_signed_nr(s, &ptr, 6);
- us = us * pow(10, 7 - (ptr - ptr_before));
- if (is_negative) {
- us *= -1;
- }
- s->time->y = 1970;
- s->time->m = 1;
- s->time->d = 1;
- s->time->h = s->time->i = s->time->s = 0;
- s->time->us = 0;
- s->time->relative.s += i;
- s->time->relative.us = us;
- s->time->is_localtime = 1;
- s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
- s->time->z = 0;
- s->time->dst = 0;
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- firstdayof | lastdayof
- {
- DEBUG_OUTPUT("firstdayof | lastdayof");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- /* skip "last day of" or "first day of" */
- if (*ptr == 'l' || *ptr == 'L') {
- s->time->relative.first_last_day_of = TIMELIB_SPECIAL_LAST_DAY_OF_MONTH;
- } else {
- s->time->relative.first_last_day_of = TIMELIB_SPECIAL_FIRST_DAY_OF_MONTH;
- }
- TIMELIB_DEINIT;
- return TIMELIB_LF_DAY_OF_MONTH;
- }
- backof | frontof
- {
- DEBUG_OUTPUT("backof | frontof");
- TIMELIB_INIT;
- TIMELIB_UNHAVE_TIME();
- TIMELIB_HAVE_TIME();
- if (*ptr == 'b') {
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = 15;
- } else {
- s->time->h = timelib_get_nr(&ptr, 2) - 1;
- s->time->i = 45;
- }
- if (*ptr != '\0' ) {
- timelib_eat_spaces(&ptr);
- s->time->h += timelib_meridian(&ptr, s->time->h);
- }
- TIMELIB_DEINIT;
- return TIMELIB_LF_DAY_OF_MONTH;
- }
- weekdayof
- {
- timelib_sll i;
- int behavior = 0;
- DEBUG_OUTPUT("weekdayof");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- TIMELIB_HAVE_SPECIAL_RELATIVE();
- i = timelib_get_relative_text(&ptr, &behavior);
- timelib_eat_spaces(&ptr);
- if (i > 0) { /* first, second... etc */
- s->time->relative.special.type = TIMELIB_SPECIAL_DAY_OF_WEEK_IN_MONTH;
- timelib_set_relative(&ptr, i, 1, s, TIMELIB_TIME_PART_DONT_KEEP);
- } else { /* last */
- s->time->relative.special.type = TIMELIB_SPECIAL_LAST_DAY_OF_WEEK_IN_MONTH;
- timelib_set_relative(&ptr, i, behavior, s, TIMELIB_TIME_PART_DONT_KEEP);
- }
- TIMELIB_DEINIT;
- return TIMELIB_WEEK_DAY_OF_MONTH;
- }
- timetiny12 | timeshort12 | timelong12
- {
- DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
- TIMELIB_INIT;
- TIMELIB_HAVE_TIME();
- s->time->h = timelib_get_nr(&ptr, 2);
- if (*ptr == ':' || *ptr == '.') {
- s->time->i = timelib_get_nr(&ptr, 2);
- if (*ptr == ':' || *ptr == '.') {
- s->time->s = timelib_get_nr(&ptr, 2);
- }
- }
- s->time->h += timelib_meridian(&ptr, s->time->h);
- TIMELIB_DEINIT;
- return TIMELIB_TIME12;
- }
- mssqltime
- {
- DEBUG_OUTPUT("mssqltime");
- TIMELIB_INIT;
- TIMELIB_HAVE_TIME();
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- if (*ptr == ':' || *ptr == '.') {
- s->time->s = timelib_get_nr(&ptr, 2);
- if (*ptr == ':' || *ptr == '.') {
- s->time->us = timelib_get_frac_nr(&ptr);
- }
- }
- timelib_eat_spaces(&ptr);
- s->time->h += timelib_meridian(&ptr, s->time->h);
- TIMELIB_DEINIT;
- return TIMELIB_TIME24_WITH_ZONE;
- }
- timetiny24 | timeshort24 | timelong24 /* | iso8601short | iso8601norm */ | iso8601long /*| iso8601shorttz | iso8601normtz | iso8601longtz*/
- {
- int tz_not_found;
- DEBUG_OUTPUT("timetiny24 | timeshort24 | timelong24 | iso8601long");
- TIMELIB_INIT;
- TIMELIB_HAVE_TIME();
- s->time->h = timelib_get_nr(&ptr, 2);
- if (*ptr == ':' || *ptr == '.') {
- s->time->i = timelib_get_nr(&ptr, 2);
- if (*ptr == ':' || *ptr == '.') {
- s->time->s = timelib_get_nr(&ptr, 2);
- if (*ptr == '.') {
- s->time->us = timelib_get_frac_nr(&ptr);
- }
- }
- }
- if (*ptr != '\0') {
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
- if (tz_not_found) {
- add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
- }
- }
- TIMELIB_DEINIT;
- return TIMELIB_TIME24_WITH_ZONE;
- }
- gnunocolon
- {
- DEBUG_OUTPUT("gnunocolon");
- TIMELIB_INIT;
- switch (s->time->have_time) {
- case 0:
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- s->time->s = 0;
- break;
- case 1:
- s->time->y = timelib_get_nr(&ptr, 4);
- break;
- default:
- TIMELIB_DEINIT;
- add_error(s, TIMELIB_ERR_DOUBLE_TIME, "Double time specification");
- return TIMELIB_ERROR;
- }
- s->time->have_time++;
- TIMELIB_DEINIT;
- return TIMELIB_GNU_NOCOLON;
- }
- /*
- gnunocolontz
- {
- DEBUG_OUTPUT("gnunocolontz");
- TIMELIB_INIT;
- switch (s->time->have_time) {
- case 0:
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- s->time->s = 0;
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, s->tzdb, tz_get_wrapper);
- break;
- case 1:
- s->time->y = timelib_get_nr(&ptr, 4);
- break;
- default:
- TIMELIB_DEINIT;
- return TIMELIB_ERROR;
- }
- s->time->have_time++;
- TIMELIB_DEINIT;
- return TIMELIB_GNU_NOCOLON_TZ;
- }
- */
- iso8601nocolon /*| iso8601nocolontz*/
- {
- int tz_not_found;
- DEBUG_OUTPUT("iso8601nocolon");
- TIMELIB_INIT;
- TIMELIB_HAVE_TIME();
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- s->time->s = timelib_get_nr(&ptr, 2);
- if (*ptr != '\0') {
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
- if (tz_not_found) {
- add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
- }
- }
- TIMELIB_DEINIT;
- return TIMELIB_ISO_NOCOLON;
- }
- americanshort | american
- {
- int length = 0;
- DEBUG_OUTPUT("americanshort | american");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = timelib_get_nr(&ptr, 2);
- if (*ptr == '/') {
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- }
- TIMELIB_DEINIT;
- return TIMELIB_AMERICAN;
- }
- iso8601date4 | iso8601dateslash | dateslash
- {
- DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_signed_nr(s, &ptr, 4);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_DEINIT;
- return TIMELIB_ISO_DATE;
- }
- iso8601date2
- {
- int length = 0;
- DEBUG_OUTPUT("iso8601date2");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_ISO_DATE;
- }
- iso8601datex
- {
- DEBUG_OUTPUT("iso8601datex");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_signed_nr(s, &ptr, 19);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_DEINIT;
- return TIMELIB_ISO_DATE;
- }
- gnudateshorter
- {
- int length = 0;
- DEBUG_OUTPUT("gnudateshorter");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = 1;
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_ISO_DATE;
- }
- gnudateshort
- {
- int length = 0;
- DEBUG_OUTPUT("gnudateshort");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_ISO_DATE;
- }
- datefull
- {
- int length = 0;
- DEBUG_OUTPUT("datefull");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->d = timelib_get_nr(&ptr, 2);
- timelib_skip_day_suffix(&ptr);
- s->time->m = timelib_get_month(&ptr);
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_FULL;
- }
- pointeddate4
- {
- DEBUG_OUTPUT("pointed date YYYY");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->d = timelib_get_nr(&ptr, 2);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->y = timelib_get_nr(&ptr, 4);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_FULL_POINTED;
- }
- pointeddate2
- {
- int length = 0;
- DEBUG_OUTPUT("pointed date YY");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->d = timelib_get_nr(&ptr, 2);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->y = timelib_get_nr_ex(&ptr, 2, &length);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_FULL_POINTED;
- }
- datenoday
- {
- int length = 0;
- DEBUG_OUTPUT("datenoday");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->m = timelib_get_month(&ptr);
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- s->time->d = 1;
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_NO_DAY;
- }
- datenodayrev
- {
- int length = 0;
- DEBUG_OUTPUT("datenodayrev");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- s->time->m = timelib_get_month(&ptr);
- s->time->d = 1;
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_NO_DAY;
- }
- datetextual | datenoyear
- {
- int length = 0;
- DEBUG_OUTPUT("datetextual | datenoyear");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->m = timelib_get_month(&ptr);
- s->time->d = timelib_get_nr(&ptr, 2);
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_TEXT;
- }
- datenoyearrev
- {
- DEBUG_OUTPUT("datenoyearrev");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->d = timelib_get_nr(&ptr, 2);
- timelib_skip_day_suffix(&ptr);
- s->time->m = timelib_get_month(&ptr);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_TEXT;
- }
- datenocolon
- {
- DEBUG_OUTPUT("datenocolon");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr(&ptr, 4);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_NOCOLON;
- }
- xmlrpc | xmlrpcnocolon | soap | wddx | exif
- {
- int tz_not_found;
- DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
- TIMELIB_INIT;
- TIMELIB_HAVE_TIME();
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr(&ptr, 4);
- s->time->m = timelib_get_nr(&ptr, 2);
- s->time->d = timelib_get_nr(&ptr, 2);
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- s->time->s = timelib_get_nr(&ptr, 2);
- if (*ptr == '.') {
- s->time->us = timelib_get_frac_nr(&ptr);
- if (*ptr) { /* timezone is optional */
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
- if (tz_not_found) {
- add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
- }
- }
- }
- TIMELIB_DEINIT;
- return TIMELIB_XMLRPC_SOAP;
- }
- pgydotd
- {
- int length = 0;
- DEBUG_OUTPUT("pgydotd");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- s->time->d = timelib_get_nr(&ptr, 3);
- s->time->m = 1;
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_PG_YEARDAY;
- }
- isoweekday
- {
- timelib_sll w, d;
- DEBUG_OUTPUT("isoweekday");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- TIMELIB_HAVE_RELATIVE();
- s->time->y = timelib_get_nr(&ptr, 4);
- w = timelib_get_nr(&ptr, 2);
- d = timelib_get_nr(&ptr, 1);
- s->time->m = 1;
- s->time->d = 1;
- s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
- TIMELIB_DEINIT;
- return TIMELIB_ISO_WEEK;
- }
- isoweek
- {
- timelib_sll w, d;
- DEBUG_OUTPUT("isoweek");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- TIMELIB_HAVE_RELATIVE();
- s->time->y = timelib_get_nr(&ptr, 4);
- w = timelib_get_nr(&ptr, 2);
- d = 1;
- s->time->m = 1;
- s->time->d = 1;
- s->time->relative.d = timelib_daynr_from_weeknr(s->time->y, w, d);
- TIMELIB_DEINIT;
- return TIMELIB_ISO_WEEK;
- }
- pgtextshort
- {
- int length = 0;
- DEBUG_OUTPUT("pgtextshort");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->m = timelib_get_month(&ptr);
- s->time->d = timelib_get_nr(&ptr, 2);
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_PG_TEXT;
- }
- pgtextreverse
- {
- int length = 0;
- DEBUG_OUTPUT("pgtextreverse");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->y = timelib_get_nr_ex(&ptr, 4, &length);
- s->time->m = timelib_get_month(&ptr);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- TIMELIB_DEINIT;
- return TIMELIB_PG_TEXT;
- }
- clf
- {
- int tz_not_found;
- DEBUG_OUTPUT("clf");
- TIMELIB_INIT;
- TIMELIB_HAVE_TIME();
- TIMELIB_HAVE_DATE();
- s->time->d = timelib_get_nr(&ptr, 2);
- s->time->m = timelib_get_month(&ptr);
- s->time->y = timelib_get_nr(&ptr, 4);
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- s->time->s = timelib_get_nr(&ptr, 2);
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
- if (tz_not_found) {
- add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
- }
- TIMELIB_DEINIT;
- return TIMELIB_CLF;
- }
- year4
- {
- DEBUG_OUTPUT("year4");
- TIMELIB_INIT;
- s->time->y = timelib_get_nr(&ptr, 4);
- TIMELIB_DEINIT;
- return TIMELIB_CLF;
- }
- ago
- {
- DEBUG_OUTPUT("ago");
- TIMELIB_INIT;
- s->time->relative.y = 0 - s->time->relative.y;
- s->time->relative.m = 0 - s->time->relative.m;
- s->time->relative.d = 0 - s->time->relative.d;
- s->time->relative.h = 0 - s->time->relative.h;
- s->time->relative.i = 0 - s->time->relative.i;
- s->time->relative.s = 0 - s->time->relative.s;
- s->time->relative.weekday = 0 - s->time->relative.weekday;
- if (s->time->relative.weekday == 0) {
- s->time->relative.weekday = -7;
- }
- if (s->time->relative.have_special_relative && s->time->relative.special.type == TIMELIB_SPECIAL_WEEKDAY) {
- s->time->relative.special.amount = 0 - s->time->relative.special.amount;
- }
- TIMELIB_DEINIT;
- return TIMELIB_AGO;
- }
- daytext
- {
- const timelib_relunit* relunit;
- DEBUG_OUTPUT("daytext");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- TIMELIB_HAVE_WEEKDAY_RELATIVE();
- TIMELIB_UNHAVE_TIME();
- relunit = timelib_lookup_relunit(&ptr);
- s->time->relative.weekday = relunit->multiplier;
- if (s->time->relative.weekday_behavior != 2) {
- s->time->relative.weekday_behavior = 1;
- }
- TIMELIB_DEINIT;
- return TIMELIB_WEEKDAY;
- }
- relativetextweek
- {
- timelib_sll i;
- int behavior = 0;
- DEBUG_OUTPUT("relativetextweek");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- while(*ptr) {
- i = timelib_get_relative_text(&ptr, &behavior);
- timelib_eat_spaces(&ptr);
- timelib_set_relative(&ptr, i, behavior, s, TIMELIB_TIME_PART_DONT_KEEP);
- s->time->relative.weekday_behavior = 2;
- /* to handle the format weekday + last/this/next week */
- if (s->time->relative.have_weekday_relative == 0) {
- TIMELIB_HAVE_WEEKDAY_RELATIVE();
- s->time->relative.weekday = 1;
- }
- }
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- relativetext
- {
- timelib_sll i;
- int behavior = 0;
- DEBUG_OUTPUT("relativetext");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- while(*ptr) {
- i = timelib_get_relative_text(&ptr, &behavior);
- timelib_eat_spaces(&ptr);
- timelib_set_relative(&ptr, i, behavior, s, TIMELIB_TIME_PART_DONT_KEEP);
- }
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- monthfull | monthabbr
- {
- DEBUG_OUTPUT("monthtext");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->m = timelib_lookup_month(&ptr);
- TIMELIB_DEINIT;
- return TIMELIB_DATE_TEXT;
- }
- tzcorrection | tz
- {
- int tz_not_found;
- DEBUG_OUTPUT("tzcorrection | tz");
- TIMELIB_INIT;
- TIMELIB_HAVE_TZ();
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
- if (tz_not_found) {
- add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
- }
- TIMELIB_DEINIT;
- return TIMELIB_TIMEZONE;
- }
- dateshortwithtimeshort12 | dateshortwithtimelong12
- {
- DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->m = timelib_get_month(&ptr);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_HAVE_TIME();
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- if (*ptr == ':' || *ptr == '.') {
- s->time->s = timelib_get_nr(&ptr, 2);
- if (*ptr == '.') {
- s->time->us = timelib_get_frac_nr(&ptr);
- }
- }
- s->time->h += timelib_meridian(&ptr, s->time->h);
- TIMELIB_DEINIT;
- return TIMELIB_SHORTDATE_WITH_TIME;
- }
- dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz
- {
- int tz_not_found;
- DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz");
- TIMELIB_INIT;
- TIMELIB_HAVE_DATE();
- s->time->m = timelib_get_month(&ptr);
- s->time->d = timelib_get_nr(&ptr, 2);
- TIMELIB_HAVE_TIME();
- s->time->h = timelib_get_nr(&ptr, 2);
- s->time->i = timelib_get_nr(&ptr, 2);
- if (*ptr == ':') {
- s->time->s = timelib_get_nr(&ptr, 2);
- if (*ptr == '.') {
- s->time->us = timelib_get_frac_nr(&ptr);
- }
- }
- if (*ptr != '\0') {
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
- if (tz_not_found) {
- add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
- }
- }
- TIMELIB_DEINIT;
- return TIMELIB_SHORTDATE_WITH_TIME;
- }
- relative
- {
- timelib_ull i;
- DEBUG_OUTPUT("relative");
- TIMELIB_INIT;
- TIMELIB_HAVE_RELATIVE();
- while(*ptr) {
- i = timelib_get_signed_nr(s, &ptr, 24);
- timelib_eat_spaces(&ptr);
- timelib_set_relative(&ptr, i, 1, s, TIMELIB_TIME_PART_KEEP);
- }
- TIMELIB_DEINIT;
- return TIMELIB_RELATIVE;
- }
- [ .,\t]
- {
- goto std;
- }
- "\000"|"\n"
- {
- s->pos = cursor; s->line++;
- goto std;
- }
- any
- {
- add_error(s, TIMELIB_ERR_UNEXPECTED_CHARACTER, "Unexpected character");
- goto std;
- }
- */
- }
- /*!max:re2c */
- timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
- {
- Scanner in;
- int t;
- const char *e = s + len - 1;
- memset(&in, 0, sizeof(in));
- in.errors = timelib_malloc(sizeof(timelib_error_container));
- in.errors->warning_count = 0;
- in.errors->warning_messages = NULL;
- in.errors->error_count = 0;
- in.errors->error_messages = NULL;
- if (len > 0) {
- while (isspace(*s) && s < e) {
- s++;
- }
- while (isspace(*e) && e > s) {
- e--;
- }
- }
- if (e - s < 0) {
- in.time = timelib_time_ctor();
- add_error(&in, TIMELIB_ERR_EMPTY_STRING, "Empty string");
- if (errors) {
- *errors = in.errors;
- } else {
- timelib_error_container_dtor(in.errors);
- }
- in.time->y = in.time->d = in.time->m = in.time->h = in.time->i = in.time->s = in.time->us = in.time->dst = in.time->z = TIMELIB_UNSET;
- in.time->is_localtime = in.time->zone_type = 0;
- return in.time;
- }
- e++;
- in.str = timelib_malloc((e - s) + YYMAXFILL);
- memset(in.str, 0, (e - s) + YYMAXFILL);
- memcpy(in.str, s, (e - s));
- in.lim = in.str + (e - s) + YYMAXFILL;
- in.cur = in.str;
- in.time = timelib_time_ctor();
- in.time->y = TIMELIB_UNSET;
- in.time->d = TIMELIB_UNSET;
- in.time->m = TIMELIB_UNSET;
- in.time->h = TIMELIB_UNSET;
- in.time->i = TIMELIB_UNSET;
- in.time->s = TIMELIB_UNSET;
- in.time->us = TIMELIB_UNSET;
- in.time->z = TIMELIB_UNSET;
- in.time->dst = TIMELIB_UNSET;
- in.tzdb = tzdb;
- in.time->is_localtime = 0;
- in.time->zone_type = 0;
- in.time->relative.days = TIMELIB_UNSET;
- do {
- t = scan(&in, tz_get_wrapper);
- #ifdef DEBUG_PARSER
- printf("%d\n", t);
- #endif
- } while(t != EOI);
- /* do funky checking whether the parsed time was valid time */
- if (in.time->have_time && !timelib_valid_time( in.time->h, in.time->i, in.time->s)) {
- add_warning(&in, TIMELIB_WARN_INVALID_TIME, "The parsed time was invalid");
- }
- /* do funky checking whether the parsed date was valid date */
- if (in.time->have_date && !timelib_valid_date( in.time->y, in.time->m, in.time->d)) {
- add_warning(&in, TIMELIB_WARN_INVALID_DATE, "The parsed date was invalid");
- }
- timelib_free(in.str);
- if (errors) {
- *errors = in.errors;
- } else {
- timelib_error_container_dtor(in.errors);
- }
- return in.time;
- }
- #define TIMELIB_CHECK_NUMBER \
- if (strchr("0123456789", *ptr) == NULL) \
- { \
- add_pbf_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Unexpected data found.", string, begin); \
- }
- #define TIMELIB_CHECK_SIGNED_NUMBER \
- if (strchr("-0123456789", *ptr) == NULL) \
- { \
- add_pbf_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Unexpected data found.", string, begin); \
- }
- static void timelib_time_reset_fields(timelib_time *time)
- {
- assert(time != NULL);
- time->y = 1970;
- time->m = 1;
- time->d = 1;
- time->h = time->i = time->s = 0;
- time->us = 0;
- time->tz_info = NULL;
- }
- static void timelib_time_reset_unset_fields(timelib_time *time)
- {
- assert(time != NULL);
- if (time->y == TIMELIB_UNSET ) time->y = 1970;
- if (time->m == TIMELIB_UNSET ) time->m = 1;
- if (time->d == TIMELIB_UNSET ) time->d = 1;
- if (time->h == TIMELIB_UNSET ) time->h = 0;
- if (time->i == TIMELIB_UNSET ) time->i = 0;
- if (time->s == TIMELIB_UNSET ) time->s = 0;
- if (time->us == TIMELIB_UNSET ) time->us = 0;
- }
- static const timelib_format_specifier default_format_map[] = {
- {'+', TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS},
- {'#', TIMELIB_FORMAT_ANY_SEPARATOR},
- {'j', TIMELIB_FORMAT_DAY_TWO_DIGIT},
- {'d', TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED},
- {'z', TIMELIB_FORMAT_DAY_OF_YEAR},
- {'S', TIMELIB_FORMAT_DAY_SUFFIX},
- {'U', TIMELIB_FORMAT_EPOCH_SECONDS},
- {'\\', TIMELIB_FORMAT_ESCAPE},
- {'h', TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX},
- {'g', TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED},
- {'H', TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX},
- {'G', TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED},
- {'a', TIMELIB_FORMAT_MERIDIAN},
- {'A', TIMELIB_FORMAT_MERIDIAN},
- {'u', TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT},
- {'v', TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT},
- {'i', TIMELIB_FORMAT_MINUTE_TWO_DIGIT},
- {'n', TIMELIB_FORMAT_MONTH_TWO_DIGIT},
- {'m', TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED},
- {'?', TIMELIB_FORMAT_RANDOM_CHAR},
- {'!', TIMELIB_FORMAT_RESET_ALL},
- {'|', TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET},
- {'s', TIMELIB_FORMAT_SECOND_TWO_DIGIT},
- {';', TIMELIB_FORMAT_SEPARATOR},
- {':', TIMELIB_FORMAT_SEPARATOR},
- {'/', TIMELIB_FORMAT_SEPARATOR},
- {'.', TIMELIB_FORMAT_SEPARATOR},
- {',', TIMELIB_FORMAT_SEPARATOR},
- {'-', TIMELIB_FORMAT_SEPARATOR},
- {'(', TIMELIB_FORMAT_SEPARATOR},
- {')', TIMELIB_FORMAT_SEPARATOR},
- {'*', TIMELIB_FORMAT_SKIP_TO_SEPARATOR},
- {'D', TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER},
- {'l', TIMELIB_FORMAT_TEXTUAL_DAY_FULL},
- {'M', TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER},
- {'F', TIMELIB_FORMAT_TEXTUAL_MONTH_FULL},
- {'e', TIMELIB_FORMAT_TIMEZONE_OFFSET},
- {'P', TIMELIB_FORMAT_TIMEZONE_OFFSET},
- {'p', TIMELIB_FORMAT_TIMEZONE_OFFSET},
- {'T', TIMELIB_FORMAT_TIMEZONE_OFFSET},
- {'O', TIMELIB_FORMAT_TIMEZONE_OFFSET},
- {' ', TIMELIB_FORMAT_WHITESPACE},
- {'y', TIMELIB_FORMAT_YEAR_TWO_DIGIT},
- {'Y', TIMELIB_FORMAT_YEAR_FOUR_DIGIT},
- {'\0', TIMELIB_FORMAT_END}
- };
- static const timelib_format_config default_format_config = {
- default_format_map,
- // No prefix required by default.
- '\0'
- };
- static timelib_format_specifier_code timelib_lookup_format(char input, const timelib_format_specifier* format_map)
- {
- while (format_map && format_map->specifier != '\0') {
- if (format_map->specifier == input) {
- return format_map->code;
- }
- format_map++;
- }
- return TIMELIB_FORMAT_LITERAL;
- }
- timelib_time *timelib_parse_from_format(const char *format, const char *string, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper)
- {
- return timelib_parse_from_format_with_map(format, string, len, errors, tzdb, tz_get_wrapper, &default_format_config);
- }
- timelib_time *timelib_parse_from_format_with_map(const char *format, const char *string, size_t len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper, const timelib_format_config* format_config)
- {
- const char *fptr = format;
- const char *ptr = string;
- const char *begin;
- timelib_sll tmp;
- Scanner in;
- Scanner *s = ∈
- bool allow_extra = false;
- bool prefix_found = false;
- int iso_year = TIMELIB_UNSET;
- int iso_week_of_year = TIMELIB_UNSET;
- int iso_day_of_week = TIMELIB_UNSET;
- char prefix_char = format_config->prefix_char;
- const timelib_format_specifier *format_map = format_config->format_map;
- memset(&in, 0, sizeof(in));
- in.errors = timelib_malloc(sizeof(timelib_error_container));
- in.errors->warning_count = 0;
- in.errors->warning_messages = NULL;
- in.errors->error_count = 0;
- in.errors->error_messages = NULL;
- in.time = timelib_time_ctor();
- in.time->y = TIMELIB_UNSET;
- in.time->d = TIMELIB_UNSET;
- in.time->m = TIMELIB_UNSET;
- in.time->h = TIMELIB_UNSET;
- in.time->i = TIMELIB_UNSET;
- in.time->s = TIMELIB_UNSET;
- in.time->us = TIMELIB_UNSET;
- in.time->z = TIMELIB_UNSET;
- in.time->dst = TIMELIB_UNSET;
- in.tzdb = tzdb;
- in.time->is_localtime = 0;
- in.time->zone_type = 0;
- /* Loop over the format string */
- while (*fptr && *ptr) {
- begin = ptr;
- if (prefix_char) {
- /* There are 2 cases where the input string and format string
- * should match the next literal:
- *
- * 1. No prefix has been specified yet in the format, so expect 1:1
- * match.
- * 2. Sequential prefix characters indicating that the second
- * prefix is escaped. (e.g. "%%" is expecting literal "%")
- */
- if ((!prefix_found && *fptr != prefix_char) ||
- (prefix_found && *fptr == prefix_char)) {
- if (*fptr != *ptr) {
- add_pbf_error(s, TIMELIB_ERR_FORMAT_LITERAL_MISMATCH, "Format literal not found", string, begin);
- }
- ptr++;
- fptr++;
- prefix_found = false;
- continue;
- }
- if (*fptr == prefix_char) {
- fptr++;
- prefix_found = true;
- continue;
- }
- /* Fall through case is that the prefix has been found and the next
- * character is the format specifier. */
- prefix_found = false;
- }
- switch (timelib_lookup_format(*fptr, format_map)) {
- case TIMELIB_FORMAT_TEXTUAL_DAY_3_LETTER: /* three letter day */
- case TIMELIB_FORMAT_TEXTUAL_DAY_FULL: /* full day */
- {
- const timelib_relunit* tmprel = 0;
- tmprel = timelib_lookup_relunit(&ptr);
- if (!tmprel) {
- add_pbf_error(s, TIMELIB_ERR_NO_TEXTUAL_DAY, "A textual day could not be found", string, begin);
- break;
- } else {
- in.time->have_relative = 1;
- in.time->relative.have_weekday_relative = 1;
- in.time->relative.weekday = tmprel->multiplier;
- in.time->relative.weekday_behavior = 1;
- }
- }
- break;
- case TIMELIB_FORMAT_DAY_TWO_DIGIT: /* two digit day, without leading zero */
- case TIMELIB_FORMAT_DAY_TWO_DIGIT_PADDED: /* two digit day, with leading zero */
- TIMELIB_CHECK_NUMBER;
- if ((s->time->d = timelib_get_nr(&ptr, 2)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_DAY, "A two digit day could not be found", string, begin);
- break;
- }
- s->time->have_date = 1;
- break;
- case TIMELIB_FORMAT_DAY_SUFFIX: /* day suffix, ignored, nor checked */
- timelib_skip_day_suffix(&ptr);
- break;
- case TIMELIB_FORMAT_DAY_OF_YEAR: /* day of year - resets month (0 based) - also initializes everything else to !TIMELIB_UNSET */
- TIMELIB_CHECK_NUMBER;
- if (s->time->y == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_MERIDIAN_BEFORE_HOUR, "A 'day of year' can only come after a year has been found", string, begin);
- }
- if ((tmp = timelib_get_nr(&ptr, 3)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_THREE_DIGIT_DAY_OF_YEAR, "A three digit day-of-year could not be found", string, begin);
- break;
- }
- if (s->time->y != TIMELIB_UNSET) {
- s->time->have_date = 1;
- s->time->m = 1;
- s->time->d = tmp + 1;
- timelib_do_normalize(s->time);
- }
- break;
- case TIMELIB_FORMAT_MONTH_TWO_DIGIT: /* two digit month, without leading zero */
- case TIMELIB_FORMAT_MONTH_TWO_DIGIT_PADDED: /* two digit month, with leading zero */
- TIMELIB_CHECK_NUMBER;
- if ((s->time->m = timelib_get_nr(&ptr, 2)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_MONTH, "A two digit month could not be found", string, begin);
- break;
- }
- s->time->have_date = 1;
- break;
- case TIMELIB_FORMAT_TEXTUAL_MONTH_3_LETTER: /* three letter month */
- case TIMELIB_FORMAT_TEXTUAL_MONTH_FULL: /* full month */
- tmp = timelib_lookup_month(&ptr);
- if (!tmp) {
- add_pbf_error(s, TIMELIB_ERR_NO_TEXTUAL_MONTH, "A textual month could not be found", string, begin);
- break;
- }
- s->time->have_date = 1;
- s->time->m = tmp;
- break;
- case TIMELIB_FORMAT_YEAR_TWO_DIGIT: /* two digit year */
- {
- int length = 0;
- TIMELIB_CHECK_NUMBER;
- if ((s->time->y = timelib_get_nr_ex(&ptr, 2, &length)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_YEAR, "A two digit year could not be found", string, begin);
- break;
- }
-
- s->time->have_date = 1;
- TIMELIB_PROCESS_YEAR(s->time->y, length);
- }
- break;
- case TIMELIB_FORMAT_YEAR_FOUR_DIGIT: /* four digit year */
- TIMELIB_CHECK_NUMBER;
- if ((s->time->y = timelib_get_nr(&ptr, 4)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_FOUR_DIGIT_YEAR, "A four digit year could not be found", string, begin);
- break;
- }
- s->time->have_date = 1;
- break;
- case TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX: /* two digit hour, without leading zero */
- case TIMELIB_FORMAT_HOUR_TWO_DIGIT_12_MAX_PADDED: /* two digit hour, with leading zero */
- TIMELIB_CHECK_NUMBER;
- if ((s->time->h = timelib_get_nr(&ptr, 2)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_HOUR, "A two digit hour could not be found", string, begin);
- break;
- }
- if (s->time->h > 12) {
- add_pbf_error(s, TIMELIB_ERR_HOUR_LARGER_THAN_12, "Hour cannot be higher than 12", string, begin);
- break;
- }
- s->time->have_time = 1;
- break;
- case TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX_PADDED: /* two digit hour, with leading zero */
- case TIMELIB_FORMAT_HOUR_TWO_DIGIT_24_MAX: /* two digit hour, without leading zero */
- TIMELIB_CHECK_NUMBER;
- if ((s->time->h = timelib_get_nr(&ptr, 2)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_HOUR, "A two digit hour could not be found", string, begin);
- break;
- }
- s->time->have_time = 1;
- break;
- case TIMELIB_FORMAT_MERIDIAN: /* am/pm/a.m./p.m. AM/PM/A.M./P.M. */
- if (s->time->h == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_MERIDIAN_BEFORE_HOUR, "Meridian can only come after an hour has been found", string, begin);
- }
- if ((tmp = timelib_meridian_with_check(&ptr, s->time->h)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_MERIDIAN, "A meridian could not be found", string, begin);
- break;
- }
- s->time->have_time = 1;
- if (s->time->h != TIMELIB_UNSET) {
- s->time->h += tmp;
- }
- break;
- case TIMELIB_FORMAT_MINUTE_TWO_DIGIT: /* two digit minute, with leading zero */
- {
- int length;
- timelib_sll min;
- TIMELIB_CHECK_NUMBER;
- min = timelib_get_nr_ex(&ptr, 2, &length);
- if (min == TIMELIB_UNSET || length != 2) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_MINUTE, "A two digit minute could not be found", string, begin);
- break;
- }
- s->time->have_time = 1;
- s->time->i = min;
- }
- break;
- case TIMELIB_FORMAT_SECOND_TWO_DIGIT: /* two digit second, with leading zero */
- {
- int length;
- timelib_sll sec;
- TIMELIB_CHECK_NUMBER;
- sec = timelib_get_nr_ex(&ptr, 2, &length);
- if (sec == TIMELIB_UNSET || length != 2) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_SECOND, "A two digit second could not be found", string, begin);
- break;
- }
- s->time->have_time = 1;
- s->time->s = sec;
- }
- break;
- case TIMELIB_FORMAT_MICROSECOND_SIX_DIGIT: /* up to six digit microsecond */
- {
- double f;
- const char *tptr;
- TIMELIB_CHECK_NUMBER;
- tptr = ptr;
- if ((f = timelib_get_nr(&ptr, 6)) == TIMELIB_UNSET || (ptr - tptr < 1)) {
- add_pbf_error(s, TIMELIB_ERR_NO_SIX_DIGIT_MICROSECOND, "A six digit microsecond could not be found", string, begin);
- break;
- }
- s->time->us = (f * pow(10, 6 - (ptr - tptr)));
- }
- break;
- case TIMELIB_FORMAT_MILLISECOND_THREE_DIGIT: /* up to three digit millisecond */
- {
- double f;
- const char *tptr;
- TIMELIB_CHECK_NUMBER;
- tptr = ptr;
- if ((f = timelib_get_nr(&ptr, 3)) == TIMELIB_UNSET || (ptr - tptr < 1)) {
- add_pbf_error(s, TIMELIB_ERR_NO_THREE_DIGIT_MILLISECOND, "A three digit millisecond could not be found", string, begin);
- break;
- }
-
- s->time->us = (f * pow(10, 3 - (ptr - tptr)) * 1000);
- }
- break;
- case TIMELIB_FORMAT_WHITESPACE: /* any sort of whitespace (' ' and \t) */
- timelib_eat_spaces(&ptr);
- break;
- case TIMELIB_FORMAT_EPOCH_SECONDS: /* epoch seconds */
- TIMELIB_CHECK_SIGNED_NUMBER;
- tmp = timelib_get_signed_nr(s, &ptr, 24);
- s->time->have_zone = 1;
- s->time->sse = tmp;
- s->time->is_localtime = 1;
- s->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
- s->time->z = 0;
- s->time->dst = 0;
- timelib_update_from_sse(s->time);
- break;
- case TIMELIB_FORMAT_ANY_SEPARATOR: /* separation symbol */
- if (timelib_lookup_format(*ptr, format_map) != TIMELIB_FORMAT_SEPARATOR) {
- add_pbf_error(s, TIMELIB_ERR_NO_SEP_SYMBOL, "The separation symbol ([;:/.,-]) could not be found", string, begin);
- break;
- }
-
- ++ptr;
- break;
- case TIMELIB_FORMAT_SEPARATOR:
- if (*ptr != *fptr) {
- add_pbf_error(s, TIMELIB_ERR_NO_SEP_SYMBOL, "The separation symbol could not be found", string, begin);
- break;
- }
- ++ptr;
- break;
- case TIMELIB_FORMAT_RESET_ALL: /* reset all fields to default */
- timelib_time_reset_fields(s->time);
- break; /* break intentionally not missing */
- case TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET: /* reset all fields to default when not set */
- timelib_time_reset_unset_fields(s->time);
- break; /* break intentionally not missing */
- case TIMELIB_FORMAT_RANDOM_CHAR: /* random char */
- ++ptr;
- break;
- case TIMELIB_FORMAT_ESCAPE: /* escaped char */
- if (!fptr[1]) {
- add_pbf_error(s, TIMELIB_ERR_EXPECTED_ESCAPE_CHAR, "Escaped character expected", string, begin);
- break;
- }
- fptr++;
- if (*ptr != *fptr) {
- add_pbf_error(s, TIMELIB_ERR_NO_ESCAPED_CHAR, "The escaped character could not be found", string, begin);
- break;
- }
- ++ptr;
- break;
- case TIMELIB_FORMAT_SKIP_TO_SEPARATOR: /* random chars until a separator or number ([ \t.,:;/-0123456789]) */
- timelib_eat_until_separator(&ptr);
- break;
- case TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS: /* allow extra chars in the format */
- allow_extra = true;
- break;
- case TIMELIB_FORMAT_YEAR_ISO:
- if ((iso_year = timelib_get_nr(&ptr, 4)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_FOUR_DIGIT_YEAR_ISO, "A four digit ISO year could not be found", string, begin);
- break;
- }
- s->time->have_date = 1;
- break;
- case TIMELIB_FORMAT_WEEK_OF_YEAR_ISO:
- if ((iso_week_of_year = timelib_get_nr(&ptr, 2)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_TWO_DIGIT_WEEK, "A two digit ISO week could not be found", string, begin);
- break;
- }
- /* Range is 1 - 53 for ISO week of year */
- if (iso_week_of_year < 1 || iso_week_of_year > 53) {
- add_pbf_error(s, TIMELIB_ERR_INVALID_WEEK, "ISO Week must be between 1 and 53", string, begin);
- break;
- }
- s->time->have_date = 1;
- break;
- case TIMELIB_FORMAT_DAY_OF_WEEK_ISO:
- if ((iso_day_of_week = timelib_get_nr(&ptr, 1)) == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_NO_DAY_OF_WEEK, "A single digit day of week could not be found", string, begin);
- break;
- }
- if (iso_day_of_week < 1 || iso_day_of_week > 7) {
- add_pbf_error(s, TIMELIB_ERR_INVALID_DAY_OF_WEEK, "Day of week must be between 1 and 7", string, begin);
- break;
- }
- s->time->have_date = 1;
- break;
- case TIMELIB_FORMAT_TIMEZONE_OFFSET: /* timezone */
- {
- int tz_not_found;
- s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
- if (tz_not_found) {
- add_pbf_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database", string, begin);
- break;
- }
- s->time->have_zone = 1;
- }
- break;
- case TIMELIB_FORMAT_TIMEZONE_OFFSET_MINUTES: /* timezone format +/-mmm */
- s->time->z = timelib_parse_tz_minutes(&ptr, s->time);
- if (s->time->z == TIMELIB_UNSET) {
- add_pbf_error(s, TIMELIB_ERR_INVALID_TZ_OFFSET, "Invalid timezone offset in minutes", string, begin);
- break;
- }
- s->time->have_zone = 1;
- break;
- case TIMELIB_FORMAT_LITERAL:
- default:
- if (*fptr != *ptr) {
- add_pbf_error(s, TIMELIB_ERR_WRONG_FORMAT_SEP, "The format separator does not match", string, begin);
- }
- ptr++;
- }
- fptr++;
- }
- if (*ptr) {
- if (allow_extra) {
- add_pbf_warning(s, TIMELIB_WARN_TRAILING_DATA, "Trailing data", string, ptr);
- } else {
- add_pbf_error(s, TIMELIB_ERR_TRAILING_DATA, "Trailing data", string, ptr);
- }
- }
- if (*fptr) {
- /* Trailing reset specifiers are valid. */
- int done = 0;
- while (*fptr && !done) {
- switch (timelib_lookup_format(*fptr, format_map)) {
- case TIMELIB_FORMAT_RESET_ALL: /* reset all fields to default */
- timelib_time_reset_fields(s->time);
- break;
- case TIMELIB_FORMAT_RESET_ALL_WHEN_NOT_SET: /* reset all fields to default when not set */
- timelib_time_reset_unset_fields(s->time);
- break;
- case TIMELIB_FORMAT_ALLOW_EXTRA_CHARACTERS:
- break;
- default:
- add_pbf_error(s, TIMELIB_ERR_DATA_MISSING, "Not enough data available to satisfy format", string, ptr);
- done = 1;
- }
- fptr++;
- }
- }
- /* clean up a bit */
- if (s->time->h != TIMELIB_UNSET || s->time->i != TIMELIB_UNSET || s->time->s != TIMELIB_UNSET || s->time->us != TIMELIB_UNSET) {
- if (s->time->h == TIMELIB_UNSET ) {
- s->time->h = 0;
- }
- if (s->time->i == TIMELIB_UNSET ) {
- s->time->i = 0;
- }
- if (s->time->s == TIMELIB_UNSET ) {
- s->time->s = 0;
- }
- if (s->time->us == TIMELIB_UNSET ) {
- s->time->us = 0;
- }
- }
- /* Check for mixing of ISO dates with natural dates. */
- if (s->time->y != TIMELIB_UNSET && (iso_week_of_year != TIMELIB_UNSET || iso_year != TIMELIB_UNSET || iso_day_of_week != TIMELIB_UNSET)) {
- add_pbf_error(s, TIMELIB_ERR_MIX_ISO_WITH_NATURAL, "Mixing of ISO dates with natural dates is not allowed", string, ptr);
- }
- if (iso_year != TIMELIB_UNSET && (s->time->y != TIMELIB_UNSET || s->time->m != TIMELIB_UNSET || s->time->d != TIMELIB_UNSET)) {
- add_pbf_error(s, TIMELIB_ERR_MIX_ISO_WITH_NATURAL, "Mixing of ISO dates with natural dates is not allowed", string, ptr);
- }
- /* Convert ISO values */
- if (iso_year != TIMELIB_UNSET) {
- /* Default week of year and day of week to 1. */
- if (iso_week_of_year == TIMELIB_UNSET) {
- iso_week_of_year = 1;
- }
- if (iso_day_of_week == TIMELIB_UNSET) {
- iso_day_of_week = 1;
- }
- timelib_date_from_isodate(iso_year, iso_week_of_year, iso_day_of_week, &s->time->y, &s->time->m, &s->time->d);
- } else if (iso_week_of_year != TIMELIB_UNSET || iso_day_of_week != TIMELIB_UNSET) {
- add_pbf_warning(s, TIMELIB_WARN_INVALID_DATE, "The parsed date was invalid", string, ptr);
- }
- /* do funky checking whether the parsed time was valid time */
- if (s->time->h != TIMELIB_UNSET && s->time->i != TIMELIB_UNSET &&
- s->time->s != TIMELIB_UNSET &&
- !timelib_valid_time( s->time->h, s->time->i, s->time->s)) {
- add_pbf_warning(s, TIMELIB_WARN_INVALID_TIME, "The parsed time was invalid", string, ptr);
- }
- /* do funky checking whether the parsed date was valid date */
- if (s->time->y != TIMELIB_UNSET && s->time->m != TIMELIB_UNSET &&
- s->time->d != TIMELIB_UNSET &&
- !timelib_valid_date( s->time->y, s->time->m, s->time->d)) {
- add_pbf_warning(s, TIMELIB_WARN_INVALID_DATE, "The parsed date was invalid", string, ptr);
- }
- if (errors) {
- *errors = in.errors;
- } else {
- timelib_error_container_dtor(in.errors);
- }
- return in.time;
- }
- void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
- {
- if (!(options & TIMELIB_OVERRIDE_TIME) && parsed->have_date && !parsed->have_time) {
- parsed->h = 0;
- parsed->i = 0;
- parsed->s = 0;
- parsed->us = 0;
- }
- if (
- parsed->y != TIMELIB_UNSET || parsed->m != TIMELIB_UNSET || parsed->d != TIMELIB_UNSET ||
- parsed->h != TIMELIB_UNSET || parsed->i != TIMELIB_UNSET || parsed->s != TIMELIB_UNSET
- ) {
- if (parsed->us == TIMELIB_UNSET) parsed->us = 0;
- } else {
- if (parsed->us == TIMELIB_UNSET) parsed->us = now->us != TIMELIB_UNSET ? now->us : 0;
- }
- if (parsed->y == TIMELIB_UNSET) parsed->y = now->y != TIMELIB_UNSET ? now->y : 0;
- if (parsed->m == TIMELIB_UNSET) parsed->m = now->m != TIMELIB_UNSET ? now->m : 0;
- if (parsed->d == TIMELIB_UNSET) parsed->d = now->d != TIMELIB_UNSET ? now->d : 0;
- if (parsed->h == TIMELIB_UNSET) parsed->h = now->h != TIMELIB_UNSET ? now->h : 0;
- if (parsed->i == TIMELIB_UNSET) parsed->i = now->i != TIMELIB_UNSET ? now->i : 0;
- if (parsed->s == TIMELIB_UNSET) parsed->s = now->s != TIMELIB_UNSET ? now->s : 0;
- if (!parsed->tz_info) {
- parsed->tz_info = now->tz_info ? (!(options & TIMELIB_NO_CLONE) ? timelib_tzinfo_clone(now->tz_info) : now->tz_info) : NULL;
- if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0;
- if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0;
- if (!parsed->tz_abbr) {
- parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL;
- }
- }
- if (parsed->zone_type == 0 && now->zone_type != 0) {
- parsed->zone_type = now->zone_type;
- /* parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL;
- parsed->tz_info = now->tz_info ? timelib_tzinfo_clone(now->tz_info) : NULL;
- */ parsed->is_localtime = 1;
- }
- /* timelib_dump_date(parsed, 2);
- timelib_dump_date(now, 2);
- */
- }
- const char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst)
- {
- const timelib_tz_lookup_table *tp;
- tp = abbr_search(abbr, gmtoffset, isdst);
- if (tp) {
- return (tp->full_tz_name);
- } else {
- return NULL;
- }
- }
- const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void)
- {
- return timelib_timezone_lookup;
- }
- #ifdef DEBUG_PARSER_STUB
- int main(void)
- {
- timelib_time time = timelib_strtotime("May 12");
- printf ("%04d-%02d-%02d %02d:%02d:%02d.%-5d %+04d %1d",
- time.y, time.m, time.d, time.h, time.i, time.s, time.f, time.z, time.dst);
- if (time.have_relative) {
- printf ("%3dY %3dM %3dD / %3dH %3dM %3dS",
- time.relative.y, time.relative.m, time.relative.d, time.relative.h, time.relative.i, time.relative.s);
- }
- if (time.have_weekday_relative) {
- printf (" / %d", time.relative.weekday);
- }
- if (time.have_weeknr_day) {
- printf(" / %dW%d", time.relative.weeknr_day.weeknr, time.relative.weeknr_day.dayofweek);
- }
- return 0;
- }
- #endif
- /*
- * vim: syntax=c
- */
|