You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TimeUtils.java 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. * Copyright 2011 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit.utils;
  17. import java.text.MessageFormat;
  18. import java.text.SimpleDateFormat;
  19. import java.util.Calendar;
  20. import java.util.Date;
  21. import java.util.ResourceBundle;
  22. /**
  23. * Utility class of time functions.
  24. *
  25. * @author James Moger
  26. *
  27. */
  28. public class TimeUtils {
  29. public static final long MIN = 1000 * 60L;
  30. public static final long HALFHOUR = MIN * 30L;
  31. public static final long ONEHOUR = HALFHOUR * 2;
  32. public static final long ONEDAY = ONEHOUR * 24L;
  33. public static final long ONEYEAR = ONEDAY * 365L;
  34. private final ResourceBundle translation;
  35. public TimeUtils() {
  36. this(null);
  37. }
  38. public TimeUtils(ResourceBundle translation) {
  39. this.translation = translation;
  40. }
  41. /**
  42. * Returns true if date is today.
  43. *
  44. * @param date
  45. * @return true if date is today
  46. */
  47. public static boolean isToday(Date date) {
  48. return (System.currentTimeMillis() - date.getTime()) < ONEDAY;
  49. }
  50. /**
  51. * Returns true if date is yesterday.
  52. *
  53. * @param date
  54. * @return true if date is yesterday
  55. */
  56. public static boolean isYesterday(Date date) {
  57. Calendar cal = Calendar.getInstance();
  58. cal.setTime(new Date());
  59. cal.add(Calendar.DATE, -1);
  60. SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
  61. return df.format(cal.getTime()).equals(df.format(date));
  62. }
  63. /**
  64. * Returns the string representation of the duration as days, months and/or
  65. * years.
  66. *
  67. * @param days
  68. * @return duration as string in days, months, and/or years
  69. */
  70. public String duration(int days) {
  71. if (days <= 60) {
  72. return (days > 1 ? translate(days, "gb.duration.days", "{0} days") : translate("gb.duration.oneDay", "1 day"));
  73. } else if (days < 365) {
  74. int rem = days % 30;
  75. return translate(((days / 30) + (rem >= 15 ? 1 : 0)), "gb.duration.months", "{0} months");
  76. } else {
  77. int years = days / 365;
  78. int rem = days % 365;
  79. String yearsString = (years > 1 ? translate(years, "gb.duration.years", "{0} years") : translate("gb.duration.oneYear", "1 year"));
  80. if (rem < 30) {
  81. if (rem == 0) {
  82. return yearsString;
  83. } else {
  84. return yearsString + (rem >= 15 ? (", " + translate("gb.duration.oneMonth", "1 month")): "");
  85. }
  86. } else {
  87. int months = rem / 30;
  88. int remDays = rem % 30;
  89. if (remDays >= 15) {
  90. months++;
  91. }
  92. String monthsString = yearsString + ", "
  93. + (months > 1 ? translate(months, "gb.duration.months", "{0} months") : translate("gb.duration.oneMonth", "1 month"));
  94. return monthsString;
  95. }
  96. }
  97. }
  98. /**
  99. * Returns the number of minutes ago between the start time and the end
  100. * time.
  101. *
  102. * @param date
  103. * @param endTime
  104. * @param roundup
  105. * @return difference in minutes
  106. */
  107. public static int minutesAgo(Date date, long endTime, boolean roundup) {
  108. long diff = endTime - date.getTime();
  109. int mins = (int) (diff / MIN);
  110. if (roundup && (diff % MIN) >= 30) {
  111. mins++;
  112. }
  113. return mins;
  114. }
  115. /**
  116. * Return the difference in minutes between now and the date.
  117. *
  118. * @param date
  119. * @param roundup
  120. * @return minutes ago
  121. */
  122. public static int minutesAgo(Date date, boolean roundup) {
  123. return minutesAgo(date, System.currentTimeMillis(), roundup);
  124. }
  125. /**
  126. * Return the difference in hours between now and the date.
  127. *
  128. * @param date
  129. * @param roundup
  130. * @return hours ago
  131. */
  132. public static int hoursAgo(Date date, boolean roundup) {
  133. long diff = System.currentTimeMillis() - date.getTime();
  134. int hours = (int) (diff / ONEHOUR);
  135. if (roundup && (diff % ONEHOUR) >= HALFHOUR) {
  136. hours++;
  137. }
  138. return hours;
  139. }
  140. /**
  141. * Return the difference in days between now and the date.
  142. *
  143. * @param date
  144. * @return days ago
  145. */
  146. public static int daysAgo(Date date) {
  147. long today = ONEDAY * (System.currentTimeMillis()/ONEDAY);
  148. long day = ONEDAY * (date.getTime()/ONEDAY);
  149. long diff = today - day;
  150. int days = (int) (diff / ONEDAY);
  151. return days;
  152. }
  153. public String today() {
  154. return translate("gb.time.today", "today");
  155. }
  156. public String yesterday() {
  157. return translate("gb.time.yesterday", "yesterday");
  158. }
  159. /**
  160. * Returns the string representation of the duration between now and the
  161. * date.
  162. *
  163. * @param date
  164. * @return duration as a string
  165. */
  166. public String timeAgo(Date date) {
  167. return timeAgo(date, false);
  168. }
  169. /**
  170. * Returns the CSS class for the date based on its age from Now.
  171. *
  172. * @param date
  173. * @return the css class
  174. */
  175. public String timeAgoCss(Date date) {
  176. return timeAgo(date, true);
  177. }
  178. /**
  179. * Returns the string representation of the duration OR the css class for
  180. * the duration.
  181. *
  182. * @param date
  183. * @param css
  184. * @return the string representation of the duration OR the css class
  185. */
  186. private String timeAgo(Date date, boolean css) {
  187. if (isToday(date) || isYesterday(date)) {
  188. int mins = minutesAgo(date, true);
  189. if (mins >= 120) {
  190. if (css) {
  191. return "age1";
  192. }
  193. int hours = hoursAgo(date, true);
  194. if (hours > 23) {
  195. return yesterday();
  196. } else {
  197. return translate(hours, "gb.time.hoursAgo", "{0} hours ago");
  198. }
  199. }
  200. if (css) {
  201. return "age0";
  202. }
  203. if (mins > 2) {
  204. return translate(mins, "gb.time.minsAgo", "{0} mins ago");
  205. }
  206. return translate("gb.time.justNow", "just now");
  207. } else {
  208. int days = daysAgo(date);
  209. if (css) {
  210. if (days <= 7) {
  211. return "age2";
  212. } if (days <= 30) {
  213. return "age3";
  214. } else {
  215. return "age4";
  216. }
  217. }
  218. if (days < 365) {
  219. if (days <= 30) {
  220. return translate(days, "gb.time.daysAgo", "{0} days ago");
  221. } else if (days <= 90) {
  222. int weeks = days / 7;
  223. if (weeks == 12) {
  224. return translate(3, "gb.time.monthsAgo", "{0} months ago");
  225. } else {
  226. return translate(weeks, "gb.time.weeksAgo", "{0} weeks ago");
  227. }
  228. }
  229. int months = days / 30;
  230. int weeks = (days % 30) / 7;
  231. if (weeks >= 2) {
  232. months++;
  233. }
  234. return translate(months, "gb.time.monthsAgo", "{0} months ago");
  235. } else if (days == 365) {
  236. return translate("gb.time.oneYearAgo", "1 year ago");
  237. } else {
  238. int yr = days / 365;
  239. days = days % 365;
  240. int months = (yr * 12) + (days / 30);
  241. if (months > 23) {
  242. return translate(yr, "gb.time.yearsAgo", "{0} years ago");
  243. } else {
  244. return translate(months, "gb.time.monthsAgo", "{0} months ago");
  245. }
  246. }
  247. }
  248. }
  249. public String inFuture(Date date) {
  250. long diff = date.getTime() - System.currentTimeMillis();
  251. if (diff > ONEDAY) {
  252. double days = ((double) diff)/ONEDAY;
  253. return translate((int) Math.round(days), "gb.time.inDays", "in {0} days");
  254. } else {
  255. double hours = ((double) diff)/ONEHOUR;
  256. if (hours > 2) {
  257. return translate((int) Math.round(hours), "gb.time.inHours", "in {0} hours");
  258. } else {
  259. int mins = (int) (diff/MIN);
  260. return translate(mins, "gb.time.inMinutes", "in {0} minutes");
  261. }
  262. }
  263. }
  264. private String translate(String key, String defaultValue) {
  265. String value = defaultValue;
  266. if (translation != null && translation.containsKey(key)) {
  267. String aValue = translation.getString(key);
  268. if (!StringUtils.isEmpty(aValue)) {
  269. value = aValue;
  270. }
  271. }
  272. return value;
  273. }
  274. private String translate(int val, String key, String defaultPattern) {
  275. String pattern = defaultPattern;
  276. if (translation != null && translation.containsKey(key)) {
  277. String aValue = translation.getString(key);
  278. if (!StringUtils.isEmpty(aValue)) {
  279. pattern = aValue;
  280. }
  281. }
  282. return MessageFormat.format(pattern, val);
  283. }
  284. /**
  285. * Convert a frequency string into minutes.
  286. *
  287. * @param frequency
  288. * @return minutes
  289. */
  290. public static int convertFrequencyToMinutes(String frequency) {
  291. // parse the frequency
  292. frequency = frequency.toLowerCase();
  293. int mins = 60;
  294. if (!StringUtils.isEmpty(frequency)) {
  295. try {
  296. String str = frequency.trim();
  297. if (frequency.indexOf(' ') > -1) {
  298. str = str.substring(0, str.indexOf(' ')).trim();
  299. }
  300. mins = (int) Float.parseFloat(str);
  301. } catch (NumberFormatException e) {
  302. }
  303. if (mins < 5) {
  304. mins = 5;
  305. }
  306. }
  307. if (frequency.indexOf("day") > -1) {
  308. // convert to minutes
  309. mins *= 1440;
  310. } else if (frequency.indexOf("hour") > -1) {
  311. // convert to minutes
  312. mins *= 60;
  313. }
  314. return mins;
  315. }
  316. }