com.indeed.imhotep.sql.parser.PeriodParser.java Source code

Java tutorial

Introduction

Here is the source code for com.indeed.imhotep.sql.parser.PeriodParser.java

Source

/*
 * Copyright (C) 2014 Indeed Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.indeed.imhotep.sql.parser;

import com.google.common.base.Strings;
import org.joda.time.Period;

import javax.annotation.Nullable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author vladimir
 */

public class PeriodParser {
    /**
     * Returns a JodaTime Period object representing the provided string period value.
     * Only first symbol of each field tag is mandatory, the rest of the tag is optional. e.g. 1d = 1 day
     * Spacing between the numbers and tags is optional. e.g. 1d = 1 d
     * Having a tag with no number implies quantity of 1. e.g. d = 1d
     * 'ago' suffix is optional.
     * Commas can optionally separate the period parts.
     */
    @Nullable
    public static Period parseString(String value) {
        final String cleanedValue = Strings.nullToEmpty(value).toLowerCase();
        Matcher matcher = relativeDatePattern.matcher(cleanedValue);
        if (!matcher.matches()) {
            return null;
        }
        int years = getValueFromMatch(matcher, 1);
        int months = getValueFromMatch(matcher, 2);
        int weeks = getValueFromMatch(matcher, 3);
        int days = getValueFromMatch(matcher, 4);
        int hours = getValueFromMatch(matcher, 5);
        int minutes = getValueFromMatch(matcher, 6);
        int seconds = getValueFromMatch(matcher, 7);
        return new Period(years, months, weeks, days, hours, minutes, seconds, 0);
    }

    private static final Pattern relativeDatePattern = Pattern.compile("(\\s*(\\d+)?\\s*y(?:ear)?s?\\s*,?\\s*)?"
            + "(\\s*(\\d+)?\\s*mo(?:nth)?s?\\s*,?\\s*)?" + "(\\s*(\\d+)?\\s*w(?:eek)?s?\\s*,?\\s*)?"
            + "(\\s*(\\d+)?\\s*d(?:ay)?s?\\s*,?\\s*)?" + "(\\s*(\\d+)?\\s*h(?:our)?s?\\s*,?\\s*)?"
            + "(\\s*(\\d+)?\\s*m(?:inute)?s?\\s*,?\\s*)?" + "(\\s*(\\d+)?\\s*s(?:econd)?s?\\s*)?" + "(?:ago)?\\s*");

    private static int getValueFromMatch(Matcher matcher, int i) {
        final String fieldMatch = matcher.group((i * 2) - 1);
        if (Strings.isNullOrEmpty(fieldMatch)) {
            return 0;
        }
        String value = matcher.group(i * 2);
        return tryParseInt(value, 1); // if we have a field match then we treat it as 1 by default
    }

    private static int tryParseInt(String val, int def) {
        int retVal;
        try {
            retVal = Integer.parseInt(val);
        } catch (NumberFormatException nfe) {
            retVal = def;
        }
        return retVal;
    }
}