Class SnowflakeDateParser

java.lang.Object
dev.frostlake.functions.scalar.SnowflakeDateParser

public final class SnowflakeDateParser extends Object
Reads a string against an explicit Snowflake date/time format model — TO_DATE / TO_TIME / TO_TIMESTAMP* with a format argument — the way the account does, and refuses the way it does: Can't parse '<input>' as date|time|timestamp with format '<format>', both echoed verbatim (the input with its own spaces, the format with its quotes). The TRY_ spellings turn that into NULL. Formatting stays with SnowflakeDateFormat; both read the same FormatPieces.

The account's reader is a backtracking scan, not a pattern match (live-verified throughout):

  • a numeric element takes its natural width first and gives digits back when the rest cannot match — '1152020' under MMDDYYYY is November 5th 2020, and so is '2020115' under YYYYMMDD — while a four-digit year also reads three or five digits when a separator follows ('202-01-15' is 0202-01-15, '20201-01-15' is 20201-01-15); a two-digit year is 1970–2069;
  • the elements match case-insensitively ('yyyy-mm-dd' is 'YYYY-MM-DD'), and so do the texts: 'jAN' and 'January' under MON, 'Jan' under MMMM, 'pm';
  • a missing field is 1970-01-01 00:00:00 — TO_DATE('15', 'DD') is 1970-01-15, TO_DATE('', '') is 1970-01-01, TO_TIMESTAMP('10:00:00', 'HH24:MI:SS') is on the epoch day;
  • a value its field cannot hold is a refusal — month 13, February 30th, hour 24, second 60, a 13 under HH12, a signed year;
  • PM adds twelve to an hour below twelve under HH24 and HH12 alike, AM turns a twelve under HH12 into zero and leaves HH24 alone, and HH12 without AM/PM is the hour as written;
  • FF reads any number of fraction digits and keeps the first nine — FF3 is a display width, not a parse width;
  • a day name under DY is read and ignored ('Mon 2020-01-15' is a Wednesday);
  • TZH / TZHTZM / TZH:TZM read a signed offset or Z; TZD reads a standard-time abbreviation;
  • a space in the model is optional in the input except at the very end, where it is required; the input's own leading and trailing spaces are forgiven, inner ones are not;
  • a repeated element keeps the last value.
  • Method Details

    • parse

      public static TemporalAccessor parse(String input, String format, String kind)
      The input read against the model: a LocalDateTime, or an OffsetDateTime when the model read an offset or a zone abbreviation.
      Parameters:
      input - the text as given, echoed verbatim in the refusal
      format - the Snowflake format model, echoed verbatim in the refusal
      kind - the word the refusal uses for the target: date, time or timestamp
      Returns:
      the value the model read
      Throws:
      RuntimeException - when the input does not match the model