From f66e89662c091e082bd1d2feb6ac91513ccff273 Mon Sep 17 00:00:00 2001
From: Rafael Cavazin <rafaelcavazin@gmail.com>
Date: Sun, 21 Jul 2013 09:59:00 -0400
Subject: [PATCH] Merge branch 'master' of https://github.com/gitblit/gitblit

---
 src/main/java/com/gitblit/utils/TimeUtils.java |  353 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 353 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/gitblit/utils/TimeUtils.java b/src/main/java/com/gitblit/utils/TimeUtils.java
new file mode 100644
index 0000000..9b5927c
--- /dev/null
+++ b/src/main/java/com/gitblit/utils/TimeUtils.java
@@ -0,0 +1,353 @@
+/*
+ * 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
+	 * @return minutes
+	 */
+	public static int convertFrequencyToMinutes(String frequency) {
+		// parse the frequency
+		frequency = frequency.toLowerCase();
+		int mins = 60;
+		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 < 5) {
+				mins = 5;
+			}
+		}
+		if (frequency.indexOf("day") > -1) {
+			// convert to minutes
+			mins *= 1440;
+		} else if (frequency.indexOf("hour") > -1) {
+			// convert to minutes
+			mins *= 60;
+		}
+		return mins;
+	}
+}

--
Gitblit v1.9.1