Package org.elasticsearch.common.joda

Source Code of org.elasticsearch.common.joda.DateMathParser

/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.common.joda;

import org.elasticsearch.ElasticsearchParseException;
import org.joda.time.DateTimeZone;
import org.joda.time.MutableDateTime;
import org.joda.time.format.DateTimeFormatter;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
*/
public class DateMathParser {

    private final FormatDateTimeFormatter dateTimeFormatter;

    private final TimeUnit timeUnit;

    public DateMathParser(FormatDateTimeFormatter dateTimeFormatter, TimeUnit timeUnit) {
        this.dateTimeFormatter = dateTimeFormatter;
        this.timeUnit = timeUnit;
    }

    public long parse(String text, long now) {
        return parse(text, now, false, null);
    }

    public long parse(String text, long now, DateTimeZone timeZone) {
        return parse(text, now, false, timeZone);
    }

    public long parseRoundCeil(String text, long now) {
        return parse(text, now, true, null);
    }

    public long parseRoundCeil(String text, long now, DateTimeZone timeZone) {
        return parse(text, now, true, timeZone);
    }

    public long parse(String text, long now, boolean roundCeil) {
        return parse(text, now, roundCeil, null);
    }

    public long parse(String text, long now, boolean roundCeil, DateTimeZone timeZone) {
        long time;
        String mathString;
        if (text.startsWith("now")) {
            time = now;
            mathString = text.substring("now".length());
        } else {
            int index = text.indexOf("||");
            String parseString;
            if (index == -1) {
                parseString = text;
                mathString = ""; // nothing else
            } else {
                parseString = text.substring(0, index);
                mathString = text.substring(index + 2);
            }
            if (roundCeil) {
                time = parseRoundCeilStringValue(parseString, timeZone);
            } else {
                time = parseStringValue(parseString, timeZone);
            }
        }

        if (mathString.isEmpty()) {
            return time;
        }

        return parseMath(mathString, time, roundCeil);
    }

    private long parseMath(String mathString, long time, boolean roundUp) throws ElasticsearchParseException {
        MutableDateTime dateTime = new MutableDateTime(time, DateTimeZone.UTC);
        try {
            for (int i = 0; i < mathString.length(); ) {
                char c = mathString.charAt(i++);
                int type;
                if (c == '/') {
                    type = 0;
                } else if (c == '+') {
                    type = 1;
                } else if (c == '-') {
                    type = 2;
                } else {
                    throw new ElasticsearchParseException("operator not supported for date math [" + mathString + "]");
                }

                int num;
                if (!Character.isDigit(mathString.charAt(i))) {
                    num = 1;
                } else {
                    int numFrom = i;
                    while (Character.isDigit(mathString.charAt(i))) {
                        i++;
                    }
                    num = Integer.parseInt(mathString.substring(numFrom, i));
                }
                if (type == 0) {
                    // rounding is only allowed on whole numbers
                    if (num != 1) {
                        throw new ElasticsearchParseException("rounding `/` can only be used on single unit types [" + mathString + "]");
                    }
                }
                char unit = mathString.charAt(i++);
                switch (unit) {
                    case 'y':
                        if (type == 0) {
                            if (roundUp) {
                                dateTime.yearOfCentury().roundCeiling();
                            } else {
                                dateTime.yearOfCentury().roundFloor();
                            }
                        } else if (type == 1) {
                            dateTime.addYears(num);
                        } else if (type == 2) {
                            dateTime.addYears(-num);
                        }
                        break;
                    case 'M':
                        if (type == 0) {
                            if (roundUp) {
                                dateTime.monthOfYear().roundCeiling();
                            } else {
                                dateTime.monthOfYear().roundFloor();
                            }
                        } else if (type == 1) {
                            dateTime.addMonths(num);
                        } else if (type == 2) {
                            dateTime.addMonths(-num);
                        }
                        break;
                    case 'w':
                        if (type == 0) {
                            if (roundUp) {
                                dateTime.weekOfWeekyear().roundCeiling();
                            } else {
                                dateTime.weekOfWeekyear().roundFloor();
                            }
                        } else if (type == 1) {
                            dateTime.addWeeks(num);
                        } else if (type == 2) {
                            dateTime.addWeeks(-num);
                        }
                        break;
                    case 'd':
                        if (type == 0) {
                            if (roundUp) {
                                dateTime.dayOfMonth().roundCeiling();
                            } else {
                                dateTime.dayOfMonth().roundFloor();
                            }
                        } else if (type == 1) {
                            dateTime.addDays(num);
                        } else if (type == 2) {
                            dateTime.addDays(-num);
                        }
                        break;
                    case 'h':
                    case 'H':
                        if (type == 0) {
                            if (roundUp) {
                                dateTime.hourOfDay().roundCeiling();
                            } else {
                                dateTime.hourOfDay().roundFloor();
                            }
                        } else if (type == 1) {
                            dateTime.addHours(num);
                        } else if (type == 2) {
                            dateTime.addHours(-num);
                        }
                        break;
                    case 'm':
                        if (type == 0) {
                            if (roundUp) {
                                dateTime.minuteOfHour().roundCeiling();
                            } else {
                                dateTime.minuteOfHour().roundFloor();
                            }
                        } else if (type == 1) {
                            dateTime.addMinutes(num);
                        } else if (type == 2) {
                            dateTime.addMinutes(-num);
                        }
                        break;
                    case 's':
                        if (type == 0) {
                            if (roundUp) {
                                dateTime.secondOfMinute().roundCeiling();
                            } else {
                                dateTime.secondOfMinute().roundFloor();
                            }
                        } else if (type == 1) {
                            dateTime.addSeconds(num);
                        } else if (type == 2) {
                            dateTime.addSeconds(-num);
                        }
                        break;
                    default:
                        throw new ElasticsearchParseException("unit [" + unit + "] not supported for date math [" + mathString + "]");
                }
            }
        } catch (Exception e) {
            if (e instanceof ElasticsearchParseException) {
                throw (ElasticsearchParseException) e;
            }
            throw new ElasticsearchParseException("failed to parse date math [" + mathString + "]");
        }
        return dateTime.getMillis();
    }

    /**
     * Get a DateTimeFormatter parser applying timezone if any.
     */
    public static DateTimeFormatter getDateTimeFormatterParser(FormatDateTimeFormatter dateTimeFormatter, DateTimeZone timeZone) {
        if (dateTimeFormatter == null) {
            return null;
        }

        DateTimeFormatter parser = dateTimeFormatter.parser();
        if (timeZone != null) {
            parser = parser.withZone(timeZone);
        }
        return parser;
    }

    private long parseStringValue(String value, DateTimeZone timeZone) {
        try {
            DateTimeFormatter parser = getDateTimeFormatterParser(dateTimeFormatter, timeZone);
            return parser.parseMillis(value);
        } catch (RuntimeException e) {
            try {
                // When date is given as a numeric value, it's a date in ms since epoch
                // By definition, it's a UTC date.
                long time = Long.parseLong(value);
                return timeUnit.toMillis(time);
            } catch (NumberFormatException e1) {
                throw new ElasticsearchParseException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number", e);
            }
        }
    }

    private long parseRoundCeilStringValue(String value, DateTimeZone timeZone) {
        try {
            // we create a date time for inclusive upper range, we "include" by default the day level data
            // so something like 2011-01-01 will include the full first day of 2011.
            // we also use 1970-01-01 as the base for it so we can handle searches like 10:12:55 (just time)
            // since when we index those, the base is 1970-01-01
            MutableDateTime dateTime = new MutableDateTime(1970, 1, 1, 23, 59, 59, 999, DateTimeZone.UTC);
            DateTimeFormatter parser = getDateTimeFormatterParser(dateTimeFormatter, timeZone);
            int location = parser.parseInto(dateTime, value, 0);
            // if we parsed all the string value, we are good
            if (location == value.length()) {
                return dateTime.getMillis();
            }
            // if we did not manage to parse, or the year is really high year which is unreasonable
            // see if its a number
            if (location <= 0 || dateTime.getYear() > 5000) {
                try {
                    long time = Long.parseLong(value);
                    return timeUnit.toMillis(time);
                } catch (NumberFormatException e1) {
                    throw new ElasticsearchParseException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number");
                }
            }
            return dateTime.getMillis();
        } catch (RuntimeException e) {
            try {
                long time = Long.parseLong(value);
                return timeUnit.toMillis(time);
            } catch (NumberFormatException e1) {
                throw new ElasticsearchParseException("failed to parse date field [" + value + "], tried both date format [" + dateTimeFormatter.format() + "], and timestamp number", e);
            }
        }
    }

    public static DateTimeZone parseZone(String text) throws IOException {
        int index = text.indexOf(':');
        if (index != -1) {
            int beginIndex = text.charAt(0) == '+' ? 1 : 0;
            // format like -02:30
            return DateTimeZone.forOffsetHoursMinutes(
                    Integer.parseInt(text.substring(beginIndex, index)),
                    Integer.parseInt(text.substring(index + 1))
            );
        } else {
            // id, listed here: http://joda-time.sourceforge.net/timezones.html
            return DateTimeZone.forID(text);
        }
    }

}
TOP

Related Classes of org.elasticsearch.common.joda.DateMathParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.