package com.isti.traceview.common;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.apache.log4j.Logger;
import com.isti.traceview.TraceView;
/**
* Class to represent interval of time
*
* @author Max Kokoulin
*/
public class TimeInterval {
/**
* Enumeration for string time representation formats. We use formats with different accuracy
* for convinient date plotting in different situations
*/
public enum DateFormatType {
/**
* format yyyy,DDD,HH:mm:ss.SSS
*/
DATE_FORMAT_NORMAL,
/**
* format yyyy,DDD,HH:mm:ss
*/
DATE_FORMAT_MIDDLE,
/**
* format yyyy,DDD,HH:mm
*/
DATE_FORMAT_LONG
};
private static final Logger logger = Logger.getLogger(TimeInterval.class);
public static SimpleDateFormat df = new SimpleDateFormat("yyyy,DDD,HH:mm:ss.SSS");
public static SimpleDateFormat df_middle = new SimpleDateFormat("yyyy,DDD,HH:mm:ss");
public static SimpleDateFormat df_long = new SimpleDateFormat("yyyy,DDD,HH:mm");
static {
df.setTimeZone(TraceView.timeZone);
df_middle.setTimeZone(TraceView.timeZone);
df_long.setTimeZone(TraceView.timeZone);
}
private long startTime;
private long endTime;
/**
* Default constructor
*/
public TimeInterval() {
startTime = Long.MAX_VALUE;
endTime = Long.MIN_VALUE;
}
/**
* Constructor from Java standard time values
*
* @param startTime
* start time of interval in milliseconds (Java standard time)
* @param endTime
* end time of interval in milliseconds (Java standard time)
*/
public TimeInterval(long startTime, long endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
/**
* Constructor from Java {@link Date} values
*
* @param startTime
* startTime start time of interval
* @param endTime
* end time of interval
*/
public TimeInterval(Date startTime, Date endTime) {
this(startTime.getTime(), endTime.getTime());
}
/**
* Extends time interval
*
* @param date
* new end value
*/
public void setMaxValue(Date date) {
long newVal = date.getTime();
if (newVal > endTime) {
endTime = newVal;
}
}
/**
* Extends time interval
*
* @param date
* new start value
*/
public void setMinValue(Date date) {
long newVal = date.getTime();
if (newVal < startTime) {
startTime = newVal;
}
}
/**
* Getter of startTime
*
* @return start time of interval
*/
public Date getStartTime() {
Date dateStart = new Date(startTime);
return dateStart;
}
/**
* Getter of startTime
*
* @return start time of interval in Java standard time form
*/
public long getStart() {
return startTime;
}
/**
* Getter of endTime
*
* @return end time of interval
*/
public Date getEndTime() {
Date dateEnd = new Date(endTime);
return dateEnd;
}
/**
* Getter of endTime
*
* @return end time of interval in Java standard time form
*/
public long getEnd() {
return endTime;
}
/**
* @return duration of interval in milliseconds
*/
public long getDuration() {
return endTime - startTime;
}
/**
* @param date
* time to test
* @return flag if this interval contains given time
*/
public boolean isContain(Date date) {
return isContain(date.getTime());
}
/**
* @param date
* time to test in Java standard time form
* @return flag if this interval contains given time
*/
public boolean isContain(long date) {
return (startTime <= date && date <= endTime);
}
/**
* @param ti
* time interval to test
* @return flag if this interval contains given one
*/
public boolean isContain(TimeInterval ti) {
return (startTime <= ti.getStart() && endTime >= ti.getEnd());
}
/**
* @param range
* time interval to test
* @return flag if this interval intersects with given one
*/
public boolean isIntersect(TimeInterval range) {
if (range.getStartTime() == null || range.getEndTime() == null || getStartTime() == null || getEndTime() == null) {
return true;
} else {
return !((startTime >= range.getEndTime().getTime() && endTime >= range.getEndTime().getTime()) || (startTime <= range.getStartTime()
.getTime() && endTime <= range.getStartTime().getTime()));
}
}
/**
* String representation of time interval in the debugging purposes
*/
public String toString() {
return "start time: " + formatDate(getStartTime(), DateFormatType.DATE_FORMAT_NORMAL) + ", end time: "
+ formatDate(getEndTime(), DateFormatType.DATE_FORMAT_NORMAL);
}
/**
* String representation of this time interval's duration
*
* @see TimeInterval#getStringDiff
*/
public String convert() {
return TimeInterval.getStringDiff(getDuration());
}
/**
* String representation of this time interval's duration
*
* @see TimeInterval#getStringDiffDDHHMMSS
*/
public String convertDDHHMMSS() {
return TimeInterval.getStringDiffDDHHMMSS(getDuration());
}
/**
* String representation of duration in seconds (if duration less then hour), hours (if duration less then day) or decimal days
*/
public static String getStringDiff(long duration) {
logger.debug("duration = " + duration);
String ret = "";
if (duration < 0) {
duration = -duration;
ret = "-";
} else {
ret = "+";
}
if(duration < 86400000) {
if (duration < 3600000) {
Double sec = new Double(duration) / 1000;
ret = ret + sec.toString() + " s";
} else {
Double h = new Double(duration) / 3600000;
ret = ret + new DecimalFormat("#######.###").format(h) + " h";
}
} else {
Double days = new Double(duration) / 86400000;
ret = ret + new DecimalFormat("#######.###").format(days) + " d";
}
return ret;
}
/**
* String representation of duration in the form +-##days ##hours ##min ##.## s
*/
public static String getStringDiffDDHHMMSS(long duration) {
logger.debug("duration = " + duration);
String ret = "";
if (duration < 0) {
duration = -duration;
ret = "-";
}
long days = duration / 86400000;
if (days > 0) {
ret = ret + days + " days";
}
long rest = duration % 86400000;
long hour = rest / 3600000;
if (hour > 0) {
if (ret.length() > 1) {
ret = ret + ", ";
}
ret = ret + hour + " hours";
}
rest = rest % 3600000;
long min = rest / 60000;
if (min > 0) {
if (ret.length() > 1) {
ret = ret + ", ";
}
ret = ret + min + " min";
}
rest = rest % 60000;
double sec = new Double(rest) / 1000;
if (ret.length() > 1) {
ret = ret + ", ";
}
ret = ret + sec + " s";
return ret;
}
/**
* Intersect two time intervals
*
* @return time interval which is intersection of two given time intervals, or null
*/
public static TimeInterval getIntersect(TimeInterval ti1, TimeInterval ti2) {
if (ti1 == null || ti2 == null)
return null;
long start = Math.max(ti1.getStart(), ti2.getStart());
long end = Math.min(ti1.getEnd(), ti2.getEnd());
if (end > start) {
return new TimeInterval(new Date(start), new Date(end));
} else {
return null;
}
}
/**
* Aggregate two time intervals
*
* @return time interval which aggregate two given time intervals, or null
*/
public static TimeInterval getAggregate(TimeInterval ti1, TimeInterval ti2) {
if (ti1 == null || ti2 == null)
return null;
long start = Math.min(ti1.getStart(), ti2.getStart());
long end = Math.max(ti1.getEnd(), ti2.getEnd());
if (end > start) {
TimeInterval TI = new TimeInterval(new Date(start), new Date(end));
return TI;
} else {
return null;
}
}
/**
* Constructs GregorianCalendar from integer values
*
* @param year the year
* @param jday the julian day
* @param hour_of_day the hour
* @param minute the minute
* @param second the second
* @param millisecond the millisecond
* @return time in GregorianCalendar form
*/
public static long getTime(int year, int jday, int hour_of_day, int minute, int second, int millisecond) {
GregorianCalendar cal = new GregorianCalendar(TraceView.timeZone);
cal.set(Calendar.YEAR, year);
cal.set(Calendar.DAY_OF_YEAR, jday);
cal.set(Calendar.HOUR_OF_DAY, hour_of_day);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
cal.set(Calendar.MILLISECOND, millisecond);
return cal.getTimeInMillis();
}
/**
* Parse string to get date according given date format
*
* @param date
* string representation of date
* @param type
* date format
* @return parsed date
*/
public static Date parseDate(String date, DateFormatType type) {
Date ret = null;
try {
switch (type) {
case DATE_FORMAT_NORMAL:
ret = df.parse(date);
break;
case DATE_FORMAT_MIDDLE:
ret = df_middle.parse(date);
break;
case DATE_FORMAT_LONG:
ret = df_long.parse(date);
break;
default:
logger.error("Wrong date format type: " + type);
}
} catch (ParseException e) {
StringBuilder message = new StringBuilder();
message.append(String.format("Cant parse date from string " + date));
logger.error(message.toString(), e);
}
return ret;
}
/**
* Gets string representation of date according given date format
*
* @param date
* date to process
* @param type
* date format
* @return string representation of date
*/
public static String formatDate(Date date, DateFormatType type) {
switch (type) {
case DATE_FORMAT_NORMAL:
return df.format(date);
case DATE_FORMAT_MIDDLE:
return df_middle.format(date);
case DATE_FORMAT_LONG:
return df_long.format(date);
default:
logger.error("Wrong date format type: " + type);
return null;
}
}
}