/* * Copyright 2013 David Tinker * * 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 io.qdb.server.databind; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; /** * Date time parser that accepts several formats. Thread safe. */ public class DateTimeParser { private final SimpleDateFormat millis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); private final SimpleDateFormat millisNoTz = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); private final SimpleDateFormat full = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); private final SimpleDateFormat noTz = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); private final SimpleDateFormat noSecs = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm"); private final SimpleDateFormat dateOnly = new SimpleDateFormat("yyyy-MM-dd"); private final SimpleDateFormat secs = new SimpleDateFormat("HH:mm:ss"); private final SimpleDateFormat mins = new SimpleDateFormat("HH:mm"); public static final DateTimeParser INSTANCE = new DateTimeParser(); public Date parse(String s) throws ParseException { Date ans; if (isAllDigits(s)) { try { return new Date(Long.parseLong(s)); } catch (NumberFormatException e) { throw new ParseException(e.getMessage(), 0); } } int n = s.length(); switch (n) { case 5: synchronized (mins) { ans = mins.parse(s); } timeToToday(ans); break; case 8: synchronized (secs) { ans = secs.parse(s); } timeToToday(ans); break; case 10: synchronized (dateOnly) { ans = dateOnly.parse(s); } break; case 16: synchronized (noSecs) { ans = noSecs.parse(s); } break; case 19: synchronized (noTz) { ans = noTz.parse(s); } break; default: if (s.lastIndexOf('.') > 0) { if (n > 23) { synchronized (millis) { ans = millis.parse(s.replace(' ', '+')); } } else synchronized (millisNoTz) { ans = millisNoTz.parse(s); } } else { synchronized (full) { ans = full.parse(s.replace(' ', '+')); } } } return ans; } private boolean isAllDigits(String s) { for (int i = s.length() - 1; i >= 0; i--) { char c = s.charAt(i); if (c < '0' || c > '9') return false; } return true; } @SuppressWarnings("deprecation") private void timeToToday(Date d) { GregorianCalendar gc = new GregorianCalendar(); d.setYear(gc.get(Calendar.YEAR) - 1900); d.setMonth(gc.get(Calendar.MONTH)); d.setDate(gc.get(Calendar.DAY_OF_MONTH)); } /** * Format date with milliseconds and timezone. */ public String formatTimestamp(Date date) { return millis.format(date); } }