/** * Copyright 2014 Yahoo! 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. See accompanying * LICENSE file. */ package com.yahoo.sql4d.utils; import com.google.common.collect.ImmutableMap; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; /** * Utils to auto detect time format, auto resolve string time to Joda DateTime etc. * @author srikalyan */ public class TimeUtils { private static final DateTimeFormatter yearOnlyFormat = DateTimeFormat.forPattern("yyyy").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter yearMonthOnlyFormat = DateTimeFormat.forPattern("yyyy-MM").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateOnlyFormat = DateTimeFormat.forPattern("yyyy-MM-dd").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateHourWithSpaceOnlyFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateHourMinWithSpaceOnlyFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeWithSpaceFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeWithSubSecWithSpaceFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSS").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeAndTZWithSpaceFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ssZZ").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeWithSubSecAndTZWithSpaceFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss.SSSZZ").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateHourOnlyFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateHourMinOnlyFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeWithSubSecFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeAndTZFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ").withOffsetParsed().withZoneUTC(); private static final DateTimeFormatter dateTimeWithSubSecAndTZFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZ").withOffsetParsed().withZoneUTC(); private static final ImmutableMap<DateTimeFormatter, String> formatterMap = ImmutableMap.<DateTimeFormatter, String>builder().put( yearOnlyFormat, "yyyy").put( yearMonthOnlyFormat, "yyyy-MM").put( dateOnlyFormat, "yyyy-MM-dd").put( dateHourWithSpaceOnlyFormat,"yyyy-MM-dd HH").put( dateHourMinWithSpaceOnlyFormat, "yyyy-MM-dd HH:mm").put( dateTimeWithSpaceFormat,"yyyy-MM-dd HH:mm:ss").put( dateTimeWithSubSecWithSpaceFormat,"yyyy-MM-dd HH:mm:ss.SSS").put( dateTimeAndTZWithSpaceFormat,"yyyy-MM-dd HH:mm:ssZZ").put( dateTimeWithSubSecAndTZWithSpaceFormat,"yyyy-MM-dd HH:mm:ss.SSSZZ").put( dateHourOnlyFormat,"yyyy-MM-dd'T'HH:mm").put( dateHourMinOnlyFormat,"yyyy-MM-dd'T'HH:mm").put( dateTimeFormat,"yyyy-MM-dd'T'HH:mm:ss").put( dateTimeWithSubSecFormat,"yyyy-MM-dd'T'HH:mm:ss.SSS").put( dateTimeAndTZFormat,"yyyy-MM-dd'T'HH:mm:ssZZ").put( dateTimeWithSubSecAndTZFormat,"yyyy-MM-dd'T'HH:mm:ss.SSSZZ").build(); //TODO: Horrific levels of nesting, do something about this. public static String detectFormat(String strTime) { String format = null; if ((format = tryAndGetFormat(strTime, dateTimeWithSubSecAndTZFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateTimeAndTZFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateTimeWithSubSecFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateTimeFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateHourMinOnlyFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateHourOnlyFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateTimeWithSubSecAndTZWithSpaceFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateTimeAndTZWithSpaceFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateTimeWithSubSecWithSpaceFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateTimeWithSpaceFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateHourMinWithSpaceOnlyFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateHourWithSpaceOnlyFormat)) == null) { if ((format = tryAndGetFormat(strTime, dateOnlyFormat)) == null) { if ((format = tryAndGetFormat(strTime, yearMonthOnlyFormat)) == null) { if ((format = tryAndGetFormat(strTime, yearOnlyFormat)) == null) { return format; } } } } } } } } } } } } } } } return format; } //TODO: Horrific levels of nesting, do something about this. public static DateTime getDateTime(String strTime) { DateTime dateTime = null; if ((dateTime = tryFormat(strTime, dateTimeWithSubSecAndTZFormat)) == null) { if ((dateTime = tryFormat(strTime, dateTimeAndTZFormat)) == null) { if ((dateTime = tryFormat(strTime, dateTimeWithSubSecFormat)) == null) { if ((dateTime = tryFormat(strTime, dateTimeFormat)) == null) { if ((dateTime = tryFormat(strTime, dateHourMinOnlyFormat)) == null) { if ((dateTime = tryFormat(strTime, dateHourOnlyFormat)) == null) { if ((dateTime = tryFormat(strTime, dateTimeWithSubSecAndTZWithSpaceFormat)) == null) { if ((dateTime = tryFormat(strTime, dateTimeAndTZWithSpaceFormat)) == null) { if ((dateTime = tryFormat(strTime, dateTimeWithSubSecWithSpaceFormat)) == null) { if ((dateTime = tryFormat(strTime, dateTimeWithSpaceFormat)) == null) { if ((dateTime = tryFormat(strTime, dateHourMinWithSpaceOnlyFormat)) == null) { if ((dateTime = tryFormat(strTime, dateHourWithSpaceOnlyFormat)) == null) { if ((dateTime = tryFormat(strTime, dateOnlyFormat)) == null) { if ((dateTime = tryFormat(strTime, yearMonthOnlyFormat)) == null) { if ((dateTime = tryFormat(strTime, yearOnlyFormat)) == null) { return dateTime; } } } } } } } } } } } } } } } return dateTime; } public static DateTime tryFormat(String timeStr, DateTimeFormatter formatter) { DateTime result = null; try { result = formatter.parseDateTime(timeStr); } catch (UnsupportedOperationException | IllegalArgumentException e) { //TODO: Log this instead of dumping to console. //System.err.println("Date Format error " + e); } return result; } public static String tryAndGetFormat(String timeStr, DateTimeFormatter formatter) { String result = null; try { formatter.parseDateTime(timeStr); result = formatterMap.get(formatter); } catch (UnsupportedOperationException | IllegalArgumentException e) { //TODO: Log this instead of dumping to console. //System.err.println("Date Format error " + e); } return result; } }