blob: c0e98e5d325223fec567bb9904a46f29808164b4 [file] [log] [blame]
/*
* Copyright 2011 gitblit.com.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gitblit.utils;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.ResourceBundle;
import java.util.TimeZone;
/**
* Utility class of time functions.
*
* @author James Moger
*
*/
public class TimeUtils {
public static final long MIN = 1000 * 60L;
public static final long HALFHOUR = MIN * 30L;
public static final long ONEHOUR = HALFHOUR * 2;
public static final long ONEDAY = ONEHOUR * 24L;
public static final long ONEYEAR = ONEDAY * 365L;
private final ResourceBundle translation;
private final TimeZone timezone;
public TimeUtils() {
this(null, null);
}
public TimeUtils(ResourceBundle translation, TimeZone timezone) {
this.translation = translation;
this.timezone = timezone;
}
/**
* Returns true if date is today.
*
* @param date
* @return true if date is today
*/
public static boolean isToday(Date date, TimeZone timezone) {
Date now = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
if (timezone != null) {
df.setTimeZone(timezone);
}
return df.format(now).equals(df.format(date));
}
/**
* Returns true if date is yesterday.
*
* @param date
* @return true if date is yesterday
*/
public static boolean isYesterday(Date date, TimeZone timezone) {
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.DATE, -1);
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
if (timezone != null) {
df.setTimeZone(timezone);
}
return df.format(cal.getTime()).equals(df.format(date));
}
/**
* Returns the string representation of the duration as days, months and/or
* years.
*
* @param days
* @return duration as string in days, months, and/or years
*/
public String duration(int days) {
if (days <= 60) {
return (days > 1 ? translate(days, "gb.duration.days", "{0} days") : translate("gb.duration.oneDay", "1 day"));
} else if (days < 365) {
int rem = days % 30;
return translate(((days / 30) + (rem >= 15 ? 1 : 0)), "gb.duration.months", "{0} months");
} else {
int years = days / 365;
int rem = days % 365;
String yearsString = (years > 1 ? translate(years, "gb.duration.years", "{0} years") : translate("gb.duration.oneYear", "1 year"));
if (rem < 30) {
if (rem == 0) {
return yearsString;
} else {
return yearsString + (rem >= 15 ? (", " + translate("gb.duration.oneMonth", "1 month")): "");
}
} else {
int months = rem / 30;
int remDays = rem % 30;
if (remDays >= 15) {
months++;
}
String monthsString = yearsString + ", "
+ (months > 1 ? translate(months, "gb.duration.months", "{0} months") : translate("gb.duration.oneMonth", "1 month"));
return monthsString;
}
}
}
/**
* Returns the number of minutes ago between the start time and the end
* time.
*
* @param date
* @param endTime
* @param roundup
* @return difference in minutes
*/
public static int minutesAgo(Date date, long endTime, boolean roundup) {
long diff = endTime - date.getTime();
int mins = (int) (diff / MIN);
if (roundup && (diff % MIN) >= 30) {
mins++;
}
return mins;
}
/**
* Return the difference in minutes between now and the date.
*
* @param date
* @param roundup
* @return minutes ago
*/
public static int minutesAgo(Date date, boolean roundup) {
return minutesAgo(date, System.currentTimeMillis(), roundup);
}
/**
* Return the difference in hours between now and the date.
*
* @param date
* @param roundup
* @return hours ago
*/
public static int hoursAgo(Date date, boolean roundup) {
long diff = System.currentTimeMillis() - date.getTime();
int hours = (int) (diff / ONEHOUR);
if (roundup && (diff % ONEHOUR) >= HALFHOUR) {
hours++;
}
return hours;
}
/**
* Return the difference in days between now and the date.
*
* @param date
* @return days ago
*/
public static int daysAgo(Date date) {
long today = ONEDAY * (System.currentTimeMillis()/ONEDAY);
long day = ONEDAY * (date.getTime()/ONEDAY);
long diff = today - day;
int days = (int) (diff / ONEDAY);
return days;
}
public String today() {
return translate("gb.time.today", "today");
}
public String yesterday() {
return translate("gb.time.yesterday", "yesterday");
}
/**
* Returns the string representation of the duration between now and the
* date.
*
* @param date
* @return duration as a string
*/
public String timeAgo(Date date) {
return timeAgo(date, false);
}
/**
* Returns the CSS class for the date based on its age from Now.
*
* @param date
* @return the css class
*/
public String timeAgoCss(Date date) {
return timeAgo(date, true);
}
/**
* Returns the string representation of the duration OR the css class for
* the duration.
*
* @param date
* @param css
* @return the string representation of the duration OR the css class
*/
private String timeAgo(Date date, boolean css) {
if (isToday(date, timezone) || isYesterday(date, timezone)) {
int mins = minutesAgo(date, true);
if (mins >= 120) {
if (css) {
return "age1";
}
int hours = hoursAgo(date, true);
if (hours > 23) {
return yesterday();
} else {
return translate(hours, "gb.time.hoursAgo", "{0} hours ago");
}
}
if (css) {
return "age0";
}
if (mins > 2) {
return translate(mins, "gb.time.minsAgo", "{0} mins ago");
}
return translate("gb.time.justNow", "just now");
} else {
int days = daysAgo(date);
if (css) {
if (days <= 7) {
return "age2";
} if (days <= 30) {
return "age3";
} else {
return "age4";
}
}
if (days < 365) {
if (days <= 30) {
return translate(days, "gb.time.daysAgo", "{0} days ago");
} else if (days <= 90) {
int weeks = days / 7;
if (weeks == 12) {
return translate(3, "gb.time.monthsAgo", "{0} months ago");
} else {
return translate(weeks, "gb.time.weeksAgo", "{0} weeks ago");
}
}
int months = days / 30;
int weeks = (days % 30) / 7;
if (weeks >= 2) {
months++;
}
return translate(months, "gb.time.monthsAgo", "{0} months ago");
} else if (days == 365) {
return translate("gb.time.oneYearAgo", "1 year ago");
} else {
int yr = days / 365;
days = days % 365;
int months = (yr * 12) + (days / 30);
if (months > 23) {
return translate(yr, "gb.time.yearsAgo", "{0} years ago");
} else {
return translate(months, "gb.time.monthsAgo", "{0} months ago");
}
}
}
}
public String inFuture(Date date) {
long diff = date.getTime() - System.currentTimeMillis();
if (diff > ONEDAY) {
double days = ((double) diff)/ONEDAY;
return translate((int) Math.round(days), "gb.time.inDays", "in {0} days");
} else {
double hours = ((double) diff)/ONEHOUR;
if (hours > 2) {
return translate((int) Math.round(hours), "gb.time.inHours", "in {0} hours");
} else {
int mins = (int) (diff/MIN);
return translate(mins, "gb.time.inMinutes", "in {0} minutes");
}
}
}
private String translate(String key, String defaultValue) {
String value = defaultValue;
if (translation != null && translation.containsKey(key)) {
String aValue = translation.getString(key);
if (!StringUtils.isEmpty(aValue)) {
value = aValue;
}
}
return value;
}
private String translate(int val, String key, String defaultPattern) {
String pattern = defaultPattern;
if (translation != null && translation.containsKey(key)) {
String aValue = translation.getString(key);
if (!StringUtils.isEmpty(aValue)) {
pattern = aValue;
}
}
return MessageFormat.format(pattern, val);
}
/**
* Convert a frequency string into minutes.
*
* @param frequency
* @param minimumMins
* @return minutes
*/
public static int convertFrequencyToMinutes(String frequency, int minimumMins) {
// parse the frequency
frequency = frequency.toLowerCase();
int mins = minimumMins;
if (!StringUtils.isEmpty(frequency)) {
try {
String str = frequency.trim();
if (frequency.indexOf(' ') > -1) {
str = str.substring(0, str.indexOf(' ')).trim();
}
mins = (int) Float.parseFloat(str);
} catch (NumberFormatException e) {
}
if (mins < minimumMins) {
mins = minimumMins;
}
if (frequency.indexOf("day") > -1) {
// convert to minutes
mins *= 1440;
} else if (frequency.indexOf("hour") > -1) {
// convert to minutes
mins *= 60;
}
}
return mins;
}
}