/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.core.clientapi.util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.rhq.core.clientapi.util.units.ScaleConstants;
import org.rhq.core.clientapi.util.units.UnitNumber;
import org.rhq.core.clientapi.util.units.UnitsConstants;
import org.rhq.core.clientapi.util.units.UnitsFormat;
import org.rhq.core.util.StringUtil;
public class TimeUtil {
public static final String DATE_FORMAT = "MM-dd-yy-HH-mm-ss";
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;
public static String toString(long time) {
UnitNumber number = new UnitNumber(time, UnitsConstants.UNIT_DATE, ScaleConstants.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;
int month;
int useIdx;
int 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;
Date 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;
Date res;
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;
SimpleDateFormat 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;
}
}