123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <cctype>
- #include <ctime>
- #include <numeric>
- #include <util/datetime/parser.h>
- #include <util/generic/ymath.h>
- %%{
- machine DateTimeParserCommon;
- sp = ' ';
- action clear_int {
- I = 0;
- Dc = 0;
- }
- action update_int {
- I = I * 10 + (fc - '0');
- ++Dc;
- }
- int = (digit+)
- >clear_int
- $update_int;
- int1 = digit
- >clear_int
- $update_int;
- int2 = (digit digit)
- >clear_int
- $update_int;
- int3 = (digit digit digit)
- >clear_int
- $update_int;
- int4 = (digit digit digit digit)
- >clear_int
- $update_int;
- int12 = (digit digit?)
- >clear_int
- $update_int;
- int24 = ( digit digit ( digit digit )? )
- >clear_int
- $update_int;
- # According to both RFC2822 and RFC2616 dates MUST be case-sensitive,
- # but Andrey fomichev@ wants relaxed parser
- month3 =
- 'Jan'i %{ DateTimeFields.Month = 1; }
- | 'Feb'i %{ DateTimeFields.Month = 2; }
- | 'Mar'i %{ DateTimeFields.Month = 3; }
- | 'Apr'i %{ DateTimeFields.Month = 4; }
- | 'May'i %{ DateTimeFields.Month = 5; }
- | 'Jun'i %{ DateTimeFields.Month = 6; }
- | 'Jul'i %{ DateTimeFields.Month = 7; }
- | 'Aug'i %{ DateTimeFields.Month = 8; }
- | 'Sep'i %{ DateTimeFields.Month = 9; }
- | 'Oct'i %{ DateTimeFields.Month = 10; }
- | 'Nov'i %{ DateTimeFields.Month = 11; }
- | 'Dec'i %{ DateTimeFields.Month = 12; };
- wkday = 'Mon'i | 'Tue'i | 'Wed'i | 'Thu'i | 'Fri'i | 'Sat'i | 'Sun'i;
- weekday = 'Monday'i | 'Tuesday'i | 'Wednesday'i | 'Thursday'i
- | 'Friday'i | 'Saturday'i | 'Sunday'i;
- action set_second { DateTimeFields.Second = I; }
- action set_minute { DateTimeFields.Minute = I; }
- action set_hour { DateTimeFields.Hour = I; }
- action set_day { DateTimeFields.Day = I; }
- action set_month { DateTimeFields.Month = I; }
- action set_year { DateTimeFields.SetLooseYear(I); }
- action set_zone_utc { DateTimeFields.ZoneOffsetMinutes = 0; }
- }%%
- %%{
- machine RFC822DateParser;
- ################# RFC 2822 3.3 Full Date ###################
- include DateTimeParserCommon;
- ws1 = (space+);
- ws0 = (space*);
- dow_spec = ( wkday ',' )?;
- day = int12 %set_day;
- year = int24 %set_year;
- # actually it must be from 0 to 23
- hour = int2 %set_hour;
- # actually it must be from 0 to 59
- min = int2 %set_minute;
- # actually it must be from 0 to 59
- sec = int2 %set_second;
- sec_spec = ( ':' . sec )?;
- # so called "military zone offset". I hardly believe someone uses it now, but we MUST respect RFc822
- action set_mil_offset {
- char c = (char)toupper(fc);
- if (c == 'Z')
- DateTimeFields.ZoneOffsetMinutes = 0;
- else {
- if (c <= 'M') {
- // ['A'..'M'] \ 'J'
- if (c < 'J')
- DateTimeFields.ZoneOffsetMinutes = (i32)TDuration::Hours(c - 'A' + 1).Minutes();
- else
- DateTimeFields.ZoneOffsetMinutes = (i32)TDuration::Hours(c - 'A').Minutes();
- } else {
- // ['N'..'Y']
- DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(c - 'N' + 1).Minutes();
- }
- }
- }
- action set_digit_offset {
- DateTimeFields.ZoneOffsetMinutes = Sign * (i32)(TDuration::Hours(I / 100) + TDuration::Minutes(I % 100)).Minutes();
- }
- mil_zone = /[A-IK-Za-ik-z]/ $set_mil_offset;
- # actions % were replaced with @ (when the script was migrated to ragel 5.24)
- # because ragel 5.24 does not call to the % action if it be called at the very end of string.
- # it is a bug in ragel 5 because ragel 6.2 works correctly with % at the end of string.
- # see http://www.complang.org/ragel/ChangeLog.
- zone = 'UT' @{ DateTimeFields.ZoneOffsetMinutes = 0; }
- | 'GMT' @{ DateTimeFields.ZoneOffsetMinutes = 0; }
- | 'EST' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(5).Minutes();}
- | 'EDT' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(4).Minutes(); }
- | 'CST' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(6).Minutes();}
- | 'CDT' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(5).Minutes(); }
- | 'MST' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(7).Minutes();}
- | 'MDT' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(6).Minutes(); }
- | 'PST' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(8).Minutes();}
- | 'PDT' @{ DateTimeFields.ZoneOffsetMinutes = -(i32)TDuration::Hours(7).Minutes(); };
- digit_offset = ('+' | '-') > { Sign = fc == '+' ? 1 : -1; } . int4 @set_digit_offset;
- offset = ( zone | mil_zone | digit_offset );
- rfc822datetime = ws0 . dow_spec . ws0 . day . ws1 . month3 . ws1 . year . ws1 . hour . ':' . min . sec_spec . ws1 . offset . ws0;
- main := rfc822datetime;
- write data noerror;
- }%%
- TRfc822DateTimeParserDeprecated::TRfc822DateTimeParserDeprecated() {
- %% write init;
- }
- bool TRfc822DateTimeParserDeprecated::ParsePart(const char* input, size_t len) {
- const char* p = input;
- const char* pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- TRfc822DateTimeParser::TRfc822DateTimeParser() {
- %% write init;
- }
- bool TRfc822DateTimeParser::ParsePart(const char* input, size_t len) {
- const char* p = input;
- const char* pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- %%{
- machine ISO8601DateTimeParser;
- include DateTimeParserCommon;
- year = int4 @set_year;
- month = int2 @set_month;
- day = int2 @set_day;
- hour = int2 @set_hour;
- minute = int2 @set_minute;
- second = int2 @set_second;
- secondFrac = digit {1,6} >clear_int $update_int @{
- ui32 us = I;
- for (int k = Dc; k < 6; ++k) {
- us *= 10;
- }
- DateTimeFields.MicroSecond = us;
- };
- secondFracTail = (digit*);
- zoneZ = [Zz] @set_zone_utc;
- zoneOffset = space? . ('+' | '-') >{ Sign = fc == '+' ? 1 : -1; } . int2 @{ DateTimeFields.ZoneOffsetMinutes = Sign * (i32)TDuration::Hours(I).Minutes(); } . (':')? . (int2 @{ DateTimeFields.ZoneOffsetMinutes += I * Sign; })?;
- zone = zoneZ | zoneOffset;
- iso8601date = (year . '-' . month . '-' . day) | (year . month . day);
- iso8601time = (hour . ':' . minute . (':' . second ('.' secondFrac secondFracTail)?)?) | (hour . minute . second?);
- iso8601datetime = iso8601date . ([Tt ] . iso8601time . zone?)?;
- main := iso8601datetime;
- write data noerror;
- }%%
- TIso8601DateTimeParserDeprecated::TIso8601DateTimeParserDeprecated() {
- %% write init;
- }
- bool TIso8601DateTimeParserDeprecated::ParsePart(const char* input, size_t len) {
- const char* p = input;
- const char* pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- TIso8601DateTimeParser::TIso8601DateTimeParser() {
- %% write init;
- }
- bool TIso8601DateTimeParser::ParsePart(const char* input, size_t len) {
- const char* p = input;
- const char* pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- %%{
- machine HttpDateTimeParser;
- include DateTimeParserCommon;
- ################# RFC 2616 3.3.1 Full Date #################
- time = int2 %set_hour ':' int2 %set_minute ':' int2 %set_second;
- date1 = int2 %set_day ' ' month3 ' ' int4 %set_year;
- date2 = int2 %set_day '-' month3 '-' int2 %set_year;
- date3 = month3 sp (int2 | sp int1) %set_day;
- rfc1123_date = wkday ',' sp date1 sp time sp 'GMT'i;
- rfc850_date = weekday ',' sp date2 sp time sp 'GMT'i;
- asctime_date = wkday sp date3 sp time sp int4 @set_year;
- http_date = (rfc1123_date | rfc850_date | asctime_date) @set_zone_utc;
- }%%
- %%{
- machine HttpDateTimeParserStandalone;
- include HttpDateTimeParser;
- main := http_date;
- write data noerror;
- }%%
- THttpDateTimeParserDeprecated::THttpDateTimeParserDeprecated() {
- %% write init;
- }
- bool THttpDateTimeParserDeprecated::ParsePart(const char* input, size_t len) {
- const char* p = input;
- const char* pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- THttpDateTimeParser::THttpDateTimeParser() {
- %% write init;
- }
- bool THttpDateTimeParser::ParsePart(const char* input, size_t len) {
- const char* p = input;
- const char* pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- %%{
- machine X509ValidityDateTimeParser;
- include DateTimeParserCommon;
- ################# X.509 certificate validity time (see rfc5280 4.1.2.5.*) #################
- year = int2 @{ DateTimeFields.Year = (I < 50 ? I + 2000 : I + 1900); };
- month = int2 @set_month;
- day = int2 @set_day;
- hour = int2 @set_hour;
- minute = int2 @set_minute;
- second = int2 @set_second;
- zone = 'Z' @set_zone_utc;
- main := year . month . day . hour . minute . second . zone;
- write data noerror;
- }%%
- TX509ValidityDateTimeParserDeprecated::TX509ValidityDateTimeParserDeprecated() {
- %% write init;
- }
- bool TX509ValidityDateTimeParserDeprecated::ParsePart(const char *input, size_t len) {
- const char *p = input;
- const char *pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- TX509ValidityDateTimeParser::TX509ValidityDateTimeParser() {
- %% write init;
- }
- bool TX509ValidityDateTimeParser::ParsePart(const char *input, size_t len) {
- const char *p = input;
- const char *pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- %%{
- machine X509Validity4yDateTimeParser;
- include DateTimeParserCommon;
- year = int4 @{ DateTimeFields.Year = I; };
- month = int2 @set_month;
- day = int2 @set_day;
- hour = int2 @set_hour;
- minute = int2 @set_minute;
- second = int2 @set_second;
- zone = 'Z' @set_zone_utc;
- main := year . month . day . hour . minute . second . zone;
- write data noerror;
- }%%
- TX509Validity4yDateTimeParserDeprecated::TX509Validity4yDateTimeParserDeprecated() {
- %% write init;
- }
- bool TX509Validity4yDateTimeParserDeprecated::ParsePart(const char *input, size_t len) {
- const char *p = input;
- const char *pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- TX509Validity4yDateTimeParser::TX509Validity4yDateTimeParser() {
- %% write init;
- }
- bool TX509Validity4yDateTimeParser::ParsePart(const char *input, size_t len) {
- const char *p = input;
- const char *pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- TInstant TIso8601DateTimeParserDeprecated::GetResult(TInstant defaultValue) const {
- Y_UNUSED(ISO8601DateTimeParser_en_main);
- return TDateTimeParserBaseDeprecated::GetResult(ISO8601DateTimeParser_first_final, defaultValue);
- }
- TInstant TRfc822DateTimeParserDeprecated::GetResult(TInstant defaultValue) const {
- Y_UNUSED(RFC822DateParser_en_main);
- return TDateTimeParserBaseDeprecated::GetResult(RFC822DateParser_first_final, defaultValue);
- }
- TInstant THttpDateTimeParserDeprecated::GetResult(TInstant defaultValue) const {
- Y_UNUSED(HttpDateTimeParserStandalone_en_main);
- return TDateTimeParserBaseDeprecated::GetResult(HttpDateTimeParserStandalone_first_final, defaultValue);
- }
- TInstant TX509ValidityDateTimeParserDeprecated::GetResult(TInstant defaultValue) const {
- Y_UNUSED(X509ValidityDateTimeParser_en_main);
- return TDateTimeParserBaseDeprecated::GetResult(X509ValidityDateTimeParser_first_final, defaultValue);
- }
- TInstant TX509Validity4yDateTimeParserDeprecated::GetResult(TInstant defaultValue) const {
- Y_UNUSED(X509Validity4yDateTimeParser_en_main);
- return TDateTimeParserBaseDeprecated::GetResult(X509Validity4yDateTimeParser_first_final, defaultValue);
- }
- TInstant TIso8601DateTimeParser::GetResult(TInstant defaultValue) const {
- Y_UNUSED(ISO8601DateTimeParser_en_main);
- return TDateTimeParserBase::GetResult(ISO8601DateTimeParser_first_final, defaultValue);
- }
- TInstant TRfc822DateTimeParser::GetResult(TInstant defaultValue) const {
- Y_UNUSED(RFC822DateParser_en_main);
- return TDateTimeParserBase::GetResult(RFC822DateParser_first_final, defaultValue);
- }
- TInstant THttpDateTimeParser::GetResult(TInstant defaultValue) const {
- Y_UNUSED(HttpDateTimeParserStandalone_en_main);
- return TDateTimeParserBase::GetResult(HttpDateTimeParserStandalone_first_final, defaultValue);
- }
- TInstant TX509ValidityDateTimeParser::GetResult(TInstant defaultValue) const {
- Y_UNUSED(X509ValidityDateTimeParser_en_main);
- return TDateTimeParserBase::GetResult(X509ValidityDateTimeParser_first_final, defaultValue);
- }
- TInstant TX509Validity4yDateTimeParser::GetResult(TInstant defaultValue) const {
- Y_UNUSED(X509Validity4yDateTimeParser_en_main);
- return TDateTimeParserBase::GetResult(X509Validity4yDateTimeParser_first_final, defaultValue);
- }
- template<class TParser, class TResult>
- static inline TResult Parse(const char* input, size_t len, TResult defaultValue) {
- TParser parser;
- if (!parser.ParsePart(input, len))
- return defaultValue;
- return parser.GetResult(defaultValue);
- }
- template<class TParser, class TResult, bool ThrowExceptionOnFailure = true>
- static inline TResult ParseUnsafe(const char* input, size_t len) {
- TResult r = Parse<TParser, TResult>(input, len, TResult::Max());
- if (ThrowExceptionOnFailure && r == TResult::Max())
- ythrow TDateTimeParseException() << "error in datetime parsing. Input data: " << TStringBuf(input, len);
- return r;
- }
- TInstant TInstant::ParseIso8601Deprecated(const TStringBuf input) {
- return ParseUnsafe<TIso8601DateTimeParserDeprecated, TInstant>(input.data(), input.size());
- }
- TInstant TInstant::ParseRfc822Deprecated(const TStringBuf input) {
- return ParseUnsafe<TRfc822DateTimeParserDeprecated, TInstant>(input.data(), input.size());
- }
- TInstant TInstant::ParseHttpDeprecated(const TStringBuf input) {
- return ParseUnsafe<THttpDateTimeParserDeprecated, TInstant>(input.data(), input.size());
- }
- TInstant TInstant::ParseX509ValidityDeprecated(const TStringBuf input) {
- switch (input.size()) {
- case 13:
- return ParseUnsafe<TX509ValidityDateTimeParserDeprecated, TInstant>(input.data(), 13);
- case 15:
- return ParseUnsafe<TX509Validity4yDateTimeParserDeprecated, TInstant>(input.data(), 15);
- default:
- ythrow TDateTimeParseException();
- }
- }
- bool TInstant::TryParseIso8601Deprecated(const TStringBuf input, TInstant& instant) {
- const auto parsed = ParseUnsafe<TIso8601DateTimeParserDeprecated, TInstant, false>(input.data(), input.size());
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- bool TInstant::TryParseRfc822Deprecated(const TStringBuf input, TInstant& instant) {
- const auto parsed = ParseUnsafe<TRfc822DateTimeParserDeprecated, TInstant, false>(input.data(), input.size());
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- bool TInstant::TryParseHttpDeprecated(const TStringBuf input, TInstant& instant) {
- const auto parsed = ParseUnsafe<THttpDateTimeParserDeprecated, TInstant, false>(input.data(), input.size());
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- bool TInstant::TryParseX509Deprecated(const TStringBuf input, TInstant& instant) {
- TInstant parsed;
- switch (input.size()) {
- case 13:
- parsed = ParseUnsafe<TX509ValidityDateTimeParserDeprecated, TInstant, false>(input.data(), 13);
- break;
- case 15:
- parsed = ParseUnsafe<TX509Validity4yDateTimeParserDeprecated, TInstant, false>(input.data(), 15);
- break;
- default:
- return false;
- }
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- TInstant TInstant::ParseIso8601(const TStringBuf input) {
- return ParseUnsafe<TIso8601DateTimeParser, TInstant>(input.data(), input.size());
- }
- TInstant TInstant::ParseRfc822(const TStringBuf input) {
- return ParseUnsafe<TRfc822DateTimeParser, TInstant>(input.data(), input.size());
- }
- TInstant TInstant::ParseHttp(const TStringBuf input) {
- return ParseUnsafe<THttpDateTimeParser, TInstant>(input.data(), input.size());
- }
- TInstant TInstant::ParseX509Validity(const TStringBuf input) {
- switch (input.size()) {
- case 13:
- return ParseUnsafe<TX509ValidityDateTimeParser, TInstant>(input.data(), 13);
- case 15:
- return ParseUnsafe<TX509Validity4yDateTimeParser, TInstant>(input.data(), 15);
- default:
- ythrow TDateTimeParseException();
- }
- }
- bool TInstant::TryParseIso8601(const TStringBuf input, TInstant& instant) {
- const auto parsed = ParseUnsafe<TIso8601DateTimeParser, TInstant, false>(input.data(), input.size());
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- bool TInstant::TryParseRfc822(const TStringBuf input, TInstant& instant) {
- const auto parsed = ParseUnsafe<TRfc822DateTimeParser, TInstant, false>(input.data(), input.size());
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- bool TInstant::TryParseHttp(const TStringBuf input, TInstant& instant) {
- const auto parsed = ParseUnsafe<THttpDateTimeParser, TInstant, false>(input.data(), input.size());
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- bool TInstant::TryParseX509(const TStringBuf input, TInstant& instant) {
- TInstant parsed;
- switch (input.size()) {
- case 13:
- parsed = ParseUnsafe<TX509ValidityDateTimeParser, TInstant, false>(input.data(), 13);
- break;
- case 15:
- parsed = ParseUnsafe<TX509Validity4yDateTimeParser, TInstant, false>(input.data(), 15);
- break;
- default:
- return false;
- }
- if (TInstant::Max() == parsed) {
- return false;
- }
- instant = parsed;
- return true;
- }
- bool ParseRFC822DateTimeDeprecated(const char* input, time_t& utcTime) {
- return ParseRFC822DateTimeDeprecated(input, strlen(input), utcTime);
- }
- bool ParseISO8601DateTimeDeprecated(const char* input, time_t& utcTime) {
- return ParseISO8601DateTimeDeprecated(input, strlen(input), utcTime);
- }
- bool ParseHTTPDateTimeDeprecated(const char* input, time_t& utcTime) {
- return ParseHTTPDateTimeDeprecated(input, strlen(input), utcTime);
- }
- bool ParseX509ValidityDateTimeDeprecated(const char* input, time_t& utcTime) {
- return ParseX509ValidityDateTimeDeprecated(input, strlen(input), utcTime);
- }
- bool ParseRFC822DateTimeDeprecated(const char* input, size_t inputLen, time_t& utcTime) {
- try {
- utcTime = ParseUnsafe<TRfc822DateTimeParserDeprecated, TInstant>(input, inputLen).TimeT();
- return true;
- } catch (const TDateTimeParseException&) {
- return false;
- }
- }
- bool ParseISO8601DateTimeDeprecated(const char* input, size_t inputLen, time_t& utcTime) {
- try {
- utcTime = ParseUnsafe<TIso8601DateTimeParserDeprecated, TInstant>(input, inputLen).TimeT();
- return true;
- } catch (const TDateTimeParseException&) {
- return false;
- }
- }
- bool ParseHTTPDateTimeDeprecated(const char* input, size_t inputLen, time_t& utcTime) {
- try {
- utcTime = ParseUnsafe<THttpDateTimeParserDeprecated, TInstant>(input, inputLen).TimeT();
- return true;
- } catch (const TDateTimeParseException&) {
- return false;
- }
- }
- bool ParseX509ValidityDateTimeDeprecated(const char* input, size_t inputLen, time_t& utcTime) {
- TInstant r;
- switch (inputLen) {
- case 13:
- r = Parse<TX509ValidityDateTimeParserDeprecated, TInstant>(input, 13, TInstant::Max());
- break;
- case 15:
- r = Parse<TX509Validity4yDateTimeParserDeprecated, TInstant>(input, 15, TInstant::Max());
- break;
- default:
- return false;
- }
- if (r == TInstant::Max())
- return false;
- utcTime = r.TimeT();
- return true;
- }
- bool ParseRFC822DateTime(const char* input, time_t& utcTime) {
- return ParseRFC822DateTime(input, strlen(input), utcTime);
- }
- bool ParseISO8601DateTime(const char* input, time_t& utcTime) {
- return ParseISO8601DateTime(input, strlen(input), utcTime);
- }
- bool ParseHTTPDateTime(const char* input, time_t& utcTime) {
- return ParseHTTPDateTime(input, strlen(input), utcTime);
- }
- bool ParseX509ValidityDateTime(const char* input, time_t& utcTime) {
- return ParseX509ValidityDateTime(input, strlen(input), utcTime);
- }
- bool ParseRFC822DateTime(const char* input, size_t inputLen, time_t& utcTime) {
- try {
- utcTime = ParseUnsafe<TRfc822DateTimeParser, TInstant>(input, inputLen).TimeT();
- return true;
- } catch (const TDateTimeParseException&) {
- return false;
- }
- }
- bool ParseISO8601DateTime(const char* input, size_t inputLen, time_t& utcTime) {
- try {
- utcTime = ParseUnsafe<TIso8601DateTimeParser, TInstant>(input, inputLen).TimeT();
- return true;
- } catch (const TDateTimeParseException&) {
- return false;
- }
- }
- bool ParseHTTPDateTime(const char* input, size_t inputLen, time_t& utcTime) {
- try {
- utcTime = ParseUnsafe<THttpDateTimeParser, TInstant>(input, inputLen).TimeT();
- return true;
- } catch (const TDateTimeParseException&) {
- return false;
- }
- }
- bool ParseX509ValidityDateTime(const char* input, size_t inputLen, time_t& utcTime) {
- TInstant r;
- switch (inputLen) {
- case 13:
- r = Parse<TX509ValidityDateTimeParser, TInstant>(input, 13, TInstant::Max());
- break;
- case 15:
- r = Parse<TX509Validity4yDateTimeParser, TInstant>(input, 15, TInstant::Max());
- break;
- default:
- return false;
- }
- if (r == TInstant::Max())
- return false;
- utcTime = r.TimeT();
- return true;
- }
- %%{
- machine TDurationParser;
- include DateTimeParserCommon;
- multiplier
- = '' # >{ MultiplierPower = 6; } # work around Ragel bugs
- | 'w' @{ MultiplierPower = 6; Multiplier = 604800; }
- | 'd' @{ MultiplierPower = 6; Multiplier = 86400; }
- | 'h' @{ MultiplierPower = 6; Multiplier = 3600; }
- | 'm' @{ MultiplierPower = 6; Multiplier = 60; }
- | 's' @{ MultiplierPower = 6; Multiplier = 1; }
- | 'ms' @{ MultiplierPower = 3; Multiplier = 1; }
- | 'us' @{ MultiplierPower = 0; Multiplier = 1; }
- | 'ns' @{ MultiplierPower = -3; Multiplier = 1; }
- ;
- integer = int @{ IntegerPart = I; };
- fraction = '.' digit {1,6} >clear_int $update_int @{ FractionPart = I; FractionDigits = Dc; } digit*;
- duration = integer fraction? multiplier;
- main := duration;
- write data noerror;
- }%%
- TDurationParser::TDurationParser()
- : cs(0)
- , I(0)
- , Dc(0)
- , MultiplierPower(6)
- , Multiplier(1)
- , IntegerPart(0)
- , FractionPart(0)
- , FractionDigits(0)
- {
- Y_UNUSED(TDurationParser_en_main);
- %% write init;
- }
- bool TDurationParser::ParsePart(const char* input, size_t len) {
- const char* p = input;
- const char* pe = input + len;
- %% write exec;
- return cs != %%{ write error; }%%;
- }
- static inline ui64 DecPower(ui64 part, i32 power) {
- if (power >= 0)
- return part * Power(10, power);
- return part / Power(10, -power);
- }
- TDuration TDurationParser::GetResult(TDuration defaultValue) const {
- if (cs < TDurationParser_first_final)
- return defaultValue;
- ui64 us = 0;
- us += Multiplier * DecPower(IntegerPart, MultiplierPower);
- us += Multiplier * DecPower(FractionPart, MultiplierPower - FractionDigits);
- return TDuration::MicroSeconds(us);
- }
- bool TDuration::TryParse(const TStringBuf input, TDuration& result) {
- TDuration r = ::Parse<TDurationParser, TDuration>(input.data(), input.size(), TDuration::Max());
- if (r == TDuration::Max())
- return false;
- result = r;
- return true;
- }
- TDuration TDuration::Parse(const TStringBuf input) {
- return ParseUnsafe<TDurationParser, TDuration>(input.data(), input.size());
- }
|