/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.util; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import org.hyperic.util.units.UnitsConstants; import org.hyperic.util.units.UnitsFormat; import org.hyperic.util.units.UnitNumber; public class TimeUtil { public static final String DATE_FORMAT = "MM-dd-yy-HH-mm-ss"; public static final String DISPLAY_DATE_FORMAT = "MM/dd/yyyy hh:mm:ss aaa"; public static final long MILLIS_IN_MINUTE = 1000 * 60; public static final long MILLIS_IN_HOUR = MILLIS_IN_MINUTE * 60; public static final long MILLIS_IN_DAY = MILLIS_IN_HOUR * 24; public static final long MILLIS_IN_WEEK = MILLIS_IN_DAY * 7; private TimeUtil() {} public static String toString(long time) { UnitNumber number = new UnitNumber(time, UnitsConstants.UNIT_DATE, UnitsConstants.SCALE_MILLI); return UnitsFormat.format(number).toString(); } /** * Parse times in a 'natural language' fashion. The following * types of times/dates are supported: * * 'now' - Returns the 'basetime' that is passed in * 'now - 1 day' - Returns 1 day prior to the base time * 'yesterday' - Returns basetime - 1 day * 'tomorrow' - Returns basetime + 1 day * 'monday' - Returns the previous monday if futureTime is * set to false, else true * * 'monday + 12 hours' - Depending on futureTime returns different * mondays at noon * 'march + 4 days' - 4 days into March * '3:00' - Parse error -- not enough info * '3:00pm' - Future 3 if futureTime is set * * '12/24/02 9:00pm' - Absolute time * * @param str String to parse * @param baseTime Basetime to use when calculating relative * times (i.e. now - 3 days) * @param futureTime When there is some ambiguity as to the time, * default to the time in the future. I.e * in the case where someone says, "noon" and * the time is currently 1:00, does he mean * the noon that just passed, or the upcoming noon? * * @return milliseconds from the epoch representing the parsed time */ public static long parseComplexTime(String str, long baseTime, boolean futureTime) throws ParseException { Calendar resCal; String[] exp; String dur; int weekday, month, useIdx, offset; exp = (String[])StringUtil.explode(str, " ").toArray(new String[0]); if(exp.length < 1){ throw new ParseException("No time found to parse", 0); } resCal = Calendar.getInstance(); resCal.setTime(new Date(baseTime)); useIdx = 0; // Get the base if(exp[useIdx].equalsIgnoreCase("now")){ // Already set resCal to current time useIdx++; } else if((exp[useIdx].equalsIgnoreCase("yesterday"))){ resCal.add(Calendar.DAY_OF_YEAR, -1); useIdx++; } else if((exp[useIdx].equalsIgnoreCase("tomorrow"))){ resCal.add(Calendar.DAY_OF_YEAR, 1); useIdx++; } else if((weekday = getWeekDay(exp[useIdx])) != -1){ int curDay; curDay = resCal.get(Calendar.DAY_OF_WEEK); if(futureTime){ if(weekday < curDay) weekday += 7; } else { if(weekday > curDay) weekday -= 7; } resCal.add(Calendar.DAY_OF_WEEK, weekday - curDay); useIdx++; } else if((month = getMonth(exp[useIdx])) != -1){ int curMonth; curMonth = resCal.get(Calendar.MONTH); if(futureTime){ if(month < curMonth) month += 7; } else { if(month > curMonth) month -= 7; } resCal.add(Calendar.MONTH, month - curMonth); useIdx++; } else { Date newDate = null, newTime = null; newDate = parseSimpleDate(exp[useIdx]); if(newDate == null){ newTime = parseSimpleTime(exp[useIdx]); if(newTime != null){ useIdx++; } } else { useIdx++; if(useIdx != exp.length){ newTime = parseSimpleTime(exp[useIdx]); if(newTime != null){ useIdx++; } } } if(newDate == null && newTime == null){ throw new ParseException("Invalid date/time specified", 0); } if(newDate != null){ resCal.setTime(newDate); } if(newTime != null){ Calendar tmpCal; long newMillis; long curTimeMillis; tmpCal = Calendar.getInstance(); tmpCal.setTime(newTime); resCal.set(Calendar.SECOND, 0); newMillis = tmpCal.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000 + tmpCal.get(Calendar.MINUTE) * 60 * 1000; curTimeMillis = resCal.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000 + resCal.get(Calendar.MINUTE) * 60 * 1000; // If the user explicitly set a date, the time is absolute // else, it's relative to our current time if(newDate == null){ if(futureTime){ if(curTimeMillis > newMillis) newMillis += 24 * 60 * 60 * 1000; } else { if(curTimeMillis < newMillis) newMillis -= 24 * 60 * 60 * 1000; } resCal.add(Calendar.SECOND, (int)((newMillis - curTimeMillis) / 1000)); } else { resCal.add(Calendar.SECOND, (int)(newMillis / 1000)); } } } // Check for offsets from the base time if(useIdx == exp.length) return resCal.getTime().getTime(); if(useIdx != exp.length - 3 || (exp[useIdx].equals("+") == false && exp[useIdx].equals("-") == false)) { throw new ParseException("Invalid time offset specified, '" + exp[useIdx] + "'", 0); } try { offset = Integer.parseInt(exp[useIdx + 1]); } catch(NumberFormatException exc){ throw new ParseException("Error parsing offset value: " + exp[useIdx + 1] + " is not a number", 0); } if(exp[useIdx].equals("-")) offset = offset * -1; dur = exp[useIdx + 2]; if(dur.regionMatches(true, 0, "seconds", 0, dur.length())) resCal.add(Calendar.SECOND, offset); else if(dur.regionMatches(true, 0, "minutes", 0, dur.length())) resCal.add(Calendar.MINUTE, offset); else if(dur.regionMatches(true, 0, "hours", 0, dur.length())) resCal.add(Calendar.HOUR, offset); else if(dur.regionMatches(true, 0, "days", 0, dur.length())) resCal.add(Calendar.DAY_OF_YEAR, offset); else if(dur.regionMatches(true, 0, "weeks", 0, dur.length())) resCal.add(Calendar.WEEK_OF_YEAR, offset); else if(dur.regionMatches(true, 0, "months", 0, dur.length())) resCal.add(Calendar.MONTH, offset); else if(dur.regionMatches(true, 0, "years", 0, dur.length())) resCal.add(Calendar.YEAR, offset); else throw new ParseException("Invalid offset duration '" + dur + "'", 0); return resCal.getTime().getTime(); } private static Date parseSimpleDate(String str){ DateFormat df; df = DateFormat.getDateInstance(DateFormat.SHORT); df.setLenient(false); try { return df.parse(str); } catch(ParseException exc){ return null; } } private static Date parseSimpleTime(String str){ SimpleDateFormat tf, tf2; tf = new SimpleDateFormat("hh:mma"); tf2 = new SimpleDateFormat("HH:mm"); tf.setLenient(false); tf2.setLenient(false); try { return tf.parse(str); } catch(ParseException exc){ try { return tf2.parse(str); } catch(ParseException iexc){ return null; } } } private static int getWeekDay(String str){ if(str.length() < 3) return -1; if(str.regionMatches(true, 0, "sunday", 0, str.length())) return Calendar.SUNDAY; else if(str.regionMatches(true, 0, "monday", 0, str.length())) return Calendar.MONDAY; else if(str.regionMatches(true, 0, "tuesday", 0, str.length())) return Calendar.TUESDAY; else if(str.regionMatches(true, 0, "wednesday", 0, str.length())) return Calendar.WEDNESDAY; else if(str.regionMatches(true, 0, "thursday", 0, str.length())) return Calendar.THURSDAY; else if(str.regionMatches(true, 0, "friday", 0, str.length())) return Calendar.FRIDAY; else if(str.regionMatches(true, 0, "saturday", 0, str.length())) return Calendar.SATURDAY; else return -1; } private static int getMonth(String str){ if(str.length() < 3) return -1; if(str.regionMatches(true, 0, "january", 0, str.length())) return Calendar.JANUARY; else if(str.regionMatches(true, 0, "february", 0, str.length())) return Calendar.FEBRUARY; else if(str.regionMatches(true, 0, "march", 0, str.length())) return Calendar.MARCH; else if(str.regionMatches(true, 0, "april", 0, str.length())) return Calendar.APRIL; else if(str.regionMatches(true, 0, "may", 0, str.length())) return Calendar.MAY; else if(str.regionMatches(true, 0, "june", 0, str.length())) return Calendar.JUNE; else if(str.regionMatches(true, 0, "july", 0, str.length())) return Calendar.JULY; else if(str.regionMatches(true, 0, "august", 0, str.length())) return Calendar.AUGUST; else if(str.regionMatches(true, 0, "september", 0, str.length())) return Calendar.SEPTEMBER; else if(str.regionMatches(true, 0, "october", 0, str.length())) return Calendar.OCTOBER; else if(str.regionMatches(true, 0, "november", 0, str.length())) return Calendar.NOVEMBER; else if(str.regionMatches(true, 0, "december", 0, str.length())) return Calendar.DECEMBER; else return -1; } public static long getInterval(long begin, long end, int points) { return (end - begin) / points; } }