void parseFromPattern()

in velox/functions/lib/JodaDateTime.cpp [278:367]


void parseFromPattern(
    JodaFormatSpecifier curPattern,
    const std::string& input,
    const char*& cur,
    const char* end,
    JodaDate& jodaDate) {
  // For now, timezone offset is the only non-numeric token supported.
  if (curPattern != JodaFormatSpecifier::TIMEZONE_OFFSET_ID) {
    int64_t number = 0;
    bool negative = false;

    if (cur < end && specAllowsNegative(curPattern) && *cur == '-') {
      negative = true;
      ++cur;
    }

    auto startPos = cur;

    while (cur < end && characterIsDigit(*cur)) {
      number = number * 10 + (*cur - '0');
      ++cur;
    }

    // Need to have read at least one digit.
    if (cur <= startPos) {
      parseFail(input, cur, end);
    }

    if (negative) {
      number *= -1L;
    }

    switch (curPattern) {
      case JodaFormatSpecifier::YEAR:
      case JodaFormatSpecifier::YEAR_OF_ERA:
        jodaDate.isYearOfEra = (curPattern == JodaFormatSpecifier::YEAR_OF_ERA);
        jodaDate.hasYear = true;
        jodaDate.year = number;
        break;

      case JodaFormatSpecifier::MONTH_OF_YEAR:
        jodaDate.month = number;

        // Joda has this weird behavior where it returns 1970 as the year by
        // default (if no year is specified), but if either day or month are
        // specified, it fallsback to 2000.
        if (!jodaDate.hasYear) {
          jodaDate.hasYear = true;
          jodaDate.year = 2000;
        }
        break;

      case JodaFormatSpecifier::DAY_OF_MONTH:
        jodaDate.day = number;
        if (!jodaDate.hasYear) {
          jodaDate.hasYear = true;
          jodaDate.year = 2000;
        }
        break;

      case JodaFormatSpecifier::HOUR_OF_DAY:
        jodaDate.hour = number;
        break;

      case JodaFormatSpecifier::MINUTE_OF_HOUR:
        jodaDate.minute = number;
        break;

      case JodaFormatSpecifier::SECOND_OF_MINUTE:
        jodaDate.second = number;
        break;

      case JodaFormatSpecifier::FRACTION_OF_SECOND:
        jodaDate.microsecond = number * util::kMicrosPerMsec;
        break;

      default:
        VELOX_NYI(
            "Numeric Joda specifier JodaFormatSpecifier::" +
            getSpecifierName(static_cast<int>(curPattern)) +
            " not implemented yet.");
    }
  } else {
    try {
      cur += parseTimezoneOffset(cur, end, jodaDate);
    } catch (...) {
      parseFail(input, cur, end);
    }
  }
}