com.rackspacecloud.blueflood.utils.DateTimeParser.java Source code

Java tutorial

Introduction

Here is the source code for com.rackspacecloud.blueflood.utils.DateTimeParser.java

Source

/*
 * Copyright 2013 Rackspace
 *
 *    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.rackspacecloud.blueflood.utils;

import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DateTimeParser {
    public static DateTime parse(String dateTimeOffsetString) {
        String stringToParse = dateTimeOffsetString.replace(" ", "").replace(",", "").replace("_", "");

        if (StringUtils.isNumeric(stringToParse) && !isLikelyDateTime(stringToParse))
            return dateTimeFromTimestamp(stringToParse);

        DateTime dateTime = tryParseDateTime("HH:mmyyyyMMdd", stringToParse);
        if (dateTime != null)
            return dateTime;

        List<String> splitList = splitDateTimeAndOffset(stringToParse);
        String offset = splitList.get(1);
        String dateTimeString = splitList.get(0);

        DateTimeOffsetParser parser = new DateTimeOffsetParser(dateTimeString, offset);
        return parser.updateDateTime(new DateTime());
    }

    private static class DateTimeOffsetParser {
        private String dateTime = "";
        private String offset = "";

        public DateTimeOffsetParser(String dateTimeString, String offsetString) {
            this.dateTime = dateTimeString;
            this.offset = offsetString;
        }

        public DateTime updateDateTime(DateTime baseDateTime) {
            baseDateTime = extractAndUpdateTime(baseDateTime);
            baseDateTime = extractAndUpdateDate(baseDateTime);
            if (!offset.equals(""))
                baseDateTime = updateDateTimeWithOffset(baseDateTime);
            return baseDateTime;
        }

        private DateTime updateDateTimeWithOffset(DateTime baseDateTime) {
            if (offset.equals(""))
                return baseDateTime;
            Pattern p = Pattern.compile("(-?\\d*)([a-z]*)");
            Matcher m = p.matcher(offset);
            if (!m.matches())
                return baseDateTime;

            int count = Integer.parseInt(m.group(1));
            String unit = m.group(2);

            DateTime dateTimeWithOffset = baseDateTime;
            if (unit.startsWith("s"))
                dateTimeWithOffset = baseDateTime.plusSeconds(count);
            else if (unit.startsWith("min"))
                dateTimeWithOffset = baseDateTime.plusMinutes(count);
            else if (unit.startsWith("h"))
                dateTimeWithOffset = baseDateTime.plusHours(count);
            else if (unit.startsWith("d"))
                dateTimeWithOffset = baseDateTime.plusDays(count);
            else if (unit.startsWith("mon"))
                dateTimeWithOffset = baseDateTime.plusMonths(count);
            else if (unit.startsWith("y"))
                dateTimeWithOffset = baseDateTime.plusYears(count);

            return dateTimeWithOffset;
        }

        private DateTime extractAndUpdateTime(DateTime inputDateTime) {
            DateTime resultDateTime = inputDateTime.withSecondOfMinute(0).withMillisOfSecond(0);

            if (dateTime.equals("") || dateTime.contains("now"))
                return resultDateTime;

            int hour = 0;
            int minute = 0;
            Pattern p = Pattern.compile("(\\d{1,2}):(\\d{2})([a|p]m)?(.*)");
            Matcher m = p.matcher(dateTime);
            if (m.matches()) {
                hour = Integer.parseInt(m.group(1));
                minute = Integer.parseInt(m.group(2));

                String middayModifier = m.group(3);
                if (middayModifier != null && middayModifier.equals("pm"))
                    hour = (hour + 12) % 24;

                dateTime = m.group(4);
            }

            if (dateTime.contains("noon")) {
                hour = 12;
                dateTime = dateTime.replace("noon", "");
            } else if (dateTime.contains("teatime")) {
                hour = 16;
                dateTime = dateTime.replace("teatime", "");
            } else if (dateTime.contains("midnight"))
                dateTime = dateTime.replace("midnight", "");

            return resultDateTime.withHourOfDay(hour).withMinuteOfHour(minute);
        }

        private DateTime extractAndUpdateDate(DateTime resultDateTime) {
            String stringToParse = this.dateTime;

            if (stringToParse.contains("tomorrow")) {
                resultDateTime = resultDateTime.plusDays(1);
                stringToParse = stringToParse.replace("tomorrow", "");
            } else if (stringToParse.contains("yesterday")) {
                resultDateTime = resultDateTime.minusDays(1);
                stringToParse = stringToParse.replace("yesterday", "");
            } else if (stringToParse.contains("today"))
                stringToParse = stringToParse.replace("today", "");

            String[] datePatterns = { "MM/dd/YY", "MM/dd/YYYY", "YYYYMMdd", "MMMMddYYYY" };
            for (String s : datePatterns) {
                DateTime date = tryParseDateTime(s, stringToParse);
                if (date != null) {
                    resultDateTime = resultDateTime.withDate(date.getYear(), date.getMonthOfYear(),
                            date.getDayOfMonth());
                    break;
                }
            }

            // Keep original datetime year
            String monthDayOptionalYearFormat = "MMMMdd";
            DateTime date = tryParseDateTime(monthDayOptionalYearFormat, stringToParse);
            if (date != null)
                resultDateTime = resultDateTime.withDate(resultDateTime.getYear(), date.getMonthOfYear(),
                        date.getDayOfMonth());

            // Keep as much of original datetime as possible
            String dayOfWeekFormat = "EEE";
            date = tryParseDateTime(dayOfWeekFormat, stringToParse);
            if (date != null)
                while (resultDateTime.getDayOfWeek() != date.getDayOfWeek())
                    resultDateTime = resultDateTime.minusDays(1);
            return resultDateTime;
        }
    }

    private static List<String> splitDateTimeAndOffset(String stringToSplit) {
        String offset = "";
        String dateTimeString = stringToSplit;
        if (stringToSplit.contains("+")) {
            String[] offsetSplit = stringToSplit.split("\\+", 2);
            dateTimeString = offsetSplit[0];
            offset = offsetSplit.length > 1 ? offsetSplit[1] : "";
        } else if (stringToSplit.contains("-")) {
            String[] offsetSplit = stringToSplit.split("-", 2);
            dateTimeString = offsetSplit[0];
            offset = offsetSplit.length > 1 ? "-" + offsetSplit[1] : "";
        }

        return Arrays.asList(dateTimeString, offset);
    }

    private static DateTime dateTimeFromTimestamp(String stringToParse) {
        return new DateTime(Long.parseLong(stringToParse) * 1000);
    }

    private static DateTime tryParseDateTime(String format, String dateTime) {
        DateTime resultDateTime;
        try {
            resultDateTime = DateTimeFormat.forPattern(format).parseDateTime(dateTime);
        } catch (IllegalArgumentException e) {
            resultDateTime = null;
        }
        return resultDateTime;
    }

    private static boolean isLikelyDateTime(String stringToParse) {
        return stringToParse.length() == 8 && Integer.parseInt(stringToParse.substring(0, 4)) > 1900
                && Integer.parseInt(stringToParse.substring(4, 6)) < 13
                && Integer.parseInt(stringToParse.substring(6)) < 32;
    }
}