package com.spun.util; import java.util.Calendar; import java.util.Date; import com.spun.util.logger.SimpleLogger; public class DateDifference { public static final String STANDARD_TIME_TEXT[] = {"Year", "Years", "Month", "Months", "Week", "Weeks", "Day", "Days", "Hour", "Hours", "Min", "Mins", "Sec", "Secs", "Milli", "Millis"}; public static final String MILLISECONDS = "milliseconds"; public static final String SECONDS = "seconds"; public static final String MINUTES = "minutes"; public static final String HOURS = "hours"; public static final String DAYS = "days"; public static final String WEEKS = "weeks"; public static final String MONTHS = "months"; public static final String YEARS = "years"; public static String TIME_UNITS[] = {YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS}; // assumes a 30 day month private static int TIME_SCALE[] = {Calendar.YEAR, Calendar.MONTH, Calendar.WEEK_OF_YEAR, Calendar.DATE, Calendar.HOUR, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND}; private static long DIVIDERS[] = {1000 * 60 * 60 * 24 * 365L, 1000 * 60 * 60 * 24 * 30L, 1000 * 60 * 60 * 24 * 7L, 1000 * 60 * 60 * 24L, 1000 * 60 * 60L, 1000 * 60L, 1000L, 1L}; /************************************************************************/ private long milli; /************************************************************************/ public DateDifference(long timeDifference) { this.milli = timeDifference; } /************************************************************************/ public DateDifference(Date date1, Date date2) { milli = date1.getTime() - date2.getTime(); if (milli < 0) { milli = milli * -1; } // My_System.variable("dateDifference = " + milli); } /************************************************************************/ /** * Debugging tool. **/ public static void printDividers() { SimpleLogger.variable("max long = " + Long.MAX_VALUE); for (int i = 0; i < DIVIDERS.length; i++) { SimpleLogger.variable("" + DIVIDERS[i]); } } /************************************************************************/ /** * Gets the amount of [Units]. <BR> * i.e. <BR> * Given a DateDifference of 2 Days 3 Hours 4 Minutes <BR> * getAbsoluteDifference(Calendar.DATE) = 2 * getAbsoluteDifference(Calendar.HOUR) = 51 **/ public long getAbsoluteDifference(int unit) { return getAbsoluteDifference(unit, this.milli); } /************************************************************************/ public long getAbsoluteDifference(String unit) { return getAbsoluteDifference(convertUnitString(unit)); } /************************************************************************/ public long getRoundedDifference(String unit) { return getRoundedDifference(convertUnitString(unit), this.milli); } /************************************************************************/ public long getRoundedDifference(int unit) { return getRoundedDifference(unit, this.milli); } /************************************************************************/ public static long getAbsoluteDifference(int unit, long time) { // My_System.variable("divider = " + DIVIDERS[getIndex(unit)]); return time / DIVIDERS[getTimeScaleIndex(unit)]; } /************************************************************************/ public static long getRoundedDifference(int unit, long time) { return Math.round(((double) time) / DIVIDERS[getTimeScaleIndex(unit)]); } /************************************************************************/ /** * Gets the remaining amount of [Units]. <BR> * i.e. <BR> * Given a DateDifference of 1 Month 2 Weeks 3 Days, * getRemainingDifference(days, months) = 17 days <BR> * getRemainingDifference(days, weeks) = 3 days <BR> **/ public long getRemainingDifference(int wantedUnit, int roundTo) { return getRemainingDifference(wantedUnit, roundTo, this.milli); } /************************************************************************/ /************************************************************************/ public static long getRemainingDifference(int wantedUnit, int roundTo, long time) { int wantedIndex = getTimeScaleIndex(wantedUnit); int roundToIndex = getTimeScaleIndex(roundTo); if (wantedIndex < roundToIndex) { throw new Error( "Can't round with a smaller Unit.[" + TIME_UNITS[wantedIndex] + ", " + TIME_UNITS[roundToIndex] + "]"); } //roundedDifference = (millis % (roundTo in millis)) / (unit in millis) return (time % DIVIDERS[roundToIndex]) / DIVIDERS[wantedIndex]; } /***********************************************************************/ /** * @return the index in TIME_SCALE[] of the largest Unit to be > 0 **/ private int getMaximumTimeUnit() { int i = 0; while ((i < DIVIDERS.length) && (milli < DIVIDERS[i])) { i++; } return i; } /***********************************************************************/ /** * Finds the index for a Calendar.DATE ect. * @return the index in TIME_SCALE[] **/ public static int getTimeScaleIndex(int calendarTime) { int i = 0; while (calendarTime != TIME_SCALE[i]) { i++; } return i; } /***********************************************************************/ public static int convertUnitString(String unit) { int result = 0; if (MILLISECONDS.equalsIgnoreCase(unit)) { result = Calendar.MILLISECOND; } else if (SECONDS.equalsIgnoreCase(unit)) { result = Calendar.SECOND; } else if (MINUTES.equalsIgnoreCase(unit)) { result = Calendar.MINUTE; } else if (HOURS.equalsIgnoreCase(unit)) { result = Calendar.HOUR; } else if (DAYS.equalsIgnoreCase(unit)) { result = Calendar.DATE; } else if (WEEKS.equalsIgnoreCase(unit)) { result = Calendar.WEEK_OF_YEAR; } else if (MONTHS.equalsIgnoreCase(unit)) { result = Calendar.MONTH; } else if (YEARS.equalsIgnoreCase(unit)) { result = Calendar.YEAR; } return result; } /***********************************************************************/ public static long convertUnitStringToMilli(String unit) { int cal = convertUnitString(unit); return DIVIDERS[getTimeScaleIndex(cal)]; } /***********************************************************************/ public boolean isMoreThan(int amount, int unit) { return (getAbsoluteDifference(unit) >= amount); } /***********************************************************************/ public boolean isMoreThan(int amount, String unitString) { return (getAbsoluteDifference(convertUnitString(unitString)) >= amount); } /***********************************************************************/ public long getStandardRoundedTime(int unitIndex, boolean forceAbsolute) { return getStandardRoundedTime(unitIndex, forceAbsolute, this.milli); } /***********************************************************************/ private static long getStandardRoundedTime(int unitIndex, boolean forceAbsolute, long time) { if (unitIndex == 0 || forceAbsolute) { return getAbsoluteDifference(TIME_SCALE[unitIndex], time); } else { return getRemainingDifference(TIME_SCALE[unitIndex], TIME_SCALE[unitIndex - 1], time); } } /***********************************************************************/ public String getStandardTimeText(int amount, String maxUnit, String minUnit, String nowText, String agoText) { return getTimeText(amount, convertUnitString(maxUnit), convertUnitString(minUnit), nowText, agoText, STANDARD_TIME_TEXT); } /***********************************************************************/ public String getTimeText(int amount, int maxUnit, int minUnit, String nowText, String agoText, String units[]) { // My_System.variable("amount = " + amount + ", maxUnit = " + maxUnit + ", minUnit = " + minUnit + ", nowText = " + nowText); if (amount == 0) { throw new Error("getTimeText() requires amount > 0"); } maxUnit = getTimeScaleIndex(maxUnit); minUnit = getTimeScaleIndex(minUnit); int realMax = getMaximumTimeUnit(); String timeText = nowText; if (realMax < maxUnit) { realMax = maxUnit; } if (realMax <= minUnit) { timeText = ""; long remainingTime = this.milli; for (int i = realMax; i < (realMax + amount) && (i <= minUnit); i++) { long time = getStandardRoundedTime(i, i == realMax, remainingTime); remainingTime -= time * DIVIDERS[i]; timeText += time + " " + units[(time == 1) ? i * 2 : i * 2 + 1] + ", "; //My_System.variable("timeText = " + timeText); } timeText = timeText.substring(0, timeText.length() - 2); if ((agoText != null) && (agoText.length() > 0)) { timeText += " " + agoText; } } return timeText; } /***********************************************************************/ public String getClockTimeText() { int maxUnit = getTimeScaleIndex(Calendar.HOUR); int minUnit = getTimeScaleIndex(Calendar.MILLISECOND); int realMax = getMaximumTimeUnit(); realMax = (realMax < maxUnit) ? maxUnit : realMax; String timeText = ""; if (realMax <= minUnit) { for (int i = realMax; i <= minUnit; i++) { int padding = (i == getTimeScaleIndex(Calendar.MILLISECOND)) ? 3 : 2; long time = getStandardRoundedTime(i, i == realMax); if (i == realMax) { timeText += time + ":"; } else { timeText += StringUtils.padNumber(time, padding) + ":"; } } timeText = timeText.substring(0, timeText.length() - 1); } return timeText; } /***********************************************************************/ public String getStandardTimeText(int amountShown) { return getTimeText(amountShown, Calendar.YEAR, Calendar.MILLISECOND, "now", "", STANDARD_TIME_TEXT); } /************************************************************************/ /************************************************************************/ }