/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.util; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.TimeZone; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * * @author Frank Purcell (p u r c e l l f @ t r i m e t . o r g) * @date October 20, 2009 */ public class DateUtils implements DateConstants { private static final Logger LOG = LoggerFactory.getLogger(DateUtils.class); /** * Returns a Date object based on input date & time parameters Defaults to today / now (when * date / time are null) * * @param date * @param time */ static public Date toDate(String date, String time, TimeZone tz) { //LOG.debug("JVM default timezone is {}", TimeZone.getDefault()); LOG.debug("Parsing date {} and time {}", date, time); LOG.debug( "using timezone {}", tz); Date retVal = new Date(); if (date != null) { Date d = parseDate(date, tz); if (d == null) { return null; //unparseable date } Calendar cal = new GregorianCalendar(tz); cal.setTime(d); boolean timed = false; if (time != null) { int[] hms = parseTime (time); if (hms != null) { cal.set(Calendar.HOUR_OF_DAY, hms[0]); cal.set(Calendar.MINUTE, hms[1]); cal.set(Calendar.SECOND, hms[2]); timed = true; } } if (!timed) { //assume t = now Calendar today = new GregorianCalendar(); cal.set(Calendar.HOUR_OF_DAY, today.get(Calendar.HOUR_OF_DAY)); cal.set(Calendar.MINUTE, today.get(Calendar.MINUTE)); cal.set(Calendar.SECOND, today.get(Calendar.SECOND)); } retVal = cal.getTime(); } else if (time != null) { int[] hms = parseTime (time); if (hms != null) { Calendar cal = new GregorianCalendar(tz); cal.set(Calendar.HOUR_OF_DAY, hms[0]); cal.set(Calendar.MINUTE, hms[1]); cal.set(Calendar.SECOND, hms[2]); retVal = cal.getTime(); } } LOG.debug( "resulting date is {}", retVal); return retVal; } /** * Returns H,M,S * @param time * @return */ private static int[] parseTime(String time) { int[] retVal = null; boolean amPm = false; int addHours = 0; int hour = 0, min = 0, sec = 0; try { String[] hms = time.toUpperCase().split(":"); // if we don't have a colon sep string, assume string is int and represents seconds past // midnight if (hms.length < 2) { int secondsPastMidnight = getIntegerFromString(time); retVal = new int[] { secondsPastMidnight / 3600, (secondsPastMidnight % 3600) / 60, secondsPastMidnight % 60 }; } if (hms[1].endsWith("PM") || hms[1].endsWith("AM")) { amPm = true; if (hms[1].contains("PM")) addHours = 12; int suffex = hms[1].lastIndexOf(' '); if (suffex < 1) { suffex = hms[1].lastIndexOf("AM"); if (suffex < 1) { suffex = hms[1].lastIndexOf("PM"); } } hms[1] = hms[1].substring(0, suffex); } int h = Integer.parseInt(trim(hms[0])); if (amPm && h == 12) h = 0; hour = h + addHours; min = Integer.parseInt(trim(hms[1])); if (hms.length > 2) { sec = Integer.parseInt(trim(hms[2])); } retVal = new int[] {hour, min, sec}; } catch (Exception e) { LOG.info(time + " didn't parse", e); retVal = null; } return retVal; } // TODO: could be replaced with Apache's DateFormat.parseDate ??? static public Date parseDate(String input, TimeZone tz) { Date retVal = null; try { String newString = input.trim().replace('_', '.').replace('-', '.').replace(':', '.').replace( '/', '.'); if (newString != null) { List<String> dl = DF_LIST; // if it looks like we have a small date format, ala 11.4.09, then use another set // of compares if (newString.length() <= 8 && !newString.matches(".*20\\d\\d.*")) { dl = SMALL_DF_LIST; } for (String df : dl) { SimpleDateFormat sdf = new SimpleDateFormat(df); sdf.setTimeZone(tz); retVal = DateUtils.parseDate(sdf, newString); if (retVal != null) { Calendar cal = new GregorianCalendar(tz); cal.setTime(retVal); int year = cal.get(Calendar.YEAR); if (year >= 2000) break; } } } } catch (Exception _) { throw new RuntimeException("Could not parse " + input); } return retVal; } public static int getIntegerFromString(String input) { try { return new Integer(input); } catch (Exception e) { return 0; } } /** * Converts time in seconds to a <code>String</code> in the format h:mm. * * @param time * the time in seconds. * @return a <code>String</code> representing the time in the format h:mm */ public static String secondsToString(int time) { return secondsToString(time, false); } public static String secondsToString(int time, boolean withAmPm) { if (time < 0) return null; String minutesStr = secondsToMinutes(time); String hoursStr = secondsToHour(time); String amPmStr = withAmPm ? getAmPm(time) : ""; return hoursStr + ":" + minutesStr + amPmStr; } public static String secondsToHour(int time) { if (time < 0) return null; int hours = (time / 3600) % 12; String hoursStr = hours == 0 ? "12" : hours + ""; return hoursStr; } public static String secondsToMinutes(int time) { if (time < 0) return null; int minutes = (time / 60) % 60; String minutesStr = (minutes < 10 ? "0" : "") + minutes; return minutesStr; } public static String getAmPm(int time) { return getAmPm(time, AM, PM); } public static String getAmPm(int time, String am, String pm) { if (time % 86400 >= 43200) return pm; else return am; } // ///////////////////////////// public static String trim(String str) { String retVal = str; try { retVal = str.trim(); retVal = retVal.replaceAll("%20;", ""); retVal = retVal.replaceAll("%20", ""); } catch (Exception _) { } return retVal; } public static String formatDate(String sdfFormat, Date date, TimeZone tz) { return formatDate(sdfFormat, date, null, tz); } public static String formatDate(String sdfFormat, Date date, String defValue, TimeZone tz) { String retVal = defValue; try { SimpleDateFormat sdf = new SimpleDateFormat(sdfFormat); sdf.setTimeZone(tz); retVal = sdf.format(date); } catch (Exception e) { retVal = defValue; } return retVal; } public static Date parseDate(String sdf, String string) { return parseDate(new SimpleDateFormat(sdf), string); } public synchronized static Date parseDate(SimpleDateFormat sdf, String string) { sdf.setLenient(false); try { return sdf.parse(string); } catch (Exception e) { // log.debug(string + " was not recognized by " + format.toString()); } return null; } public static long absoluteTimeout(double relativeTimeoutSeconds) { if (relativeTimeoutSeconds <= 0) return Long.MAX_VALUE; else return System.currentTimeMillis() + (long)(relativeTimeoutSeconds * 1000.0); } }