View Javadoc
1   /*
2    * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.util;
11  
12  import java.text.MessageFormat;
13  import java.util.Date;
14  
15  import org.eclipse.jgit.internal.JGitText;
16  
17  /**
18   * Formatter to format timestamps relative to the current time using time units
19   * in the format defined by {@code git log --relative-date}.
20   */
21  public class RelativeDateFormatter {
22  	static final long SECOND_IN_MILLIS = 1000;
23  
24  	static final long MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS;
25  
26  	static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS;
27  
28  	static final long DAY_IN_MILLIS = 24 * HOUR_IN_MILLIS;
29  
30  	static final long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS;
31  
32  	static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;
33  
34  	static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS;
35  
36  	/**
37  	 * Get age of given {@link java.util.Date} compared to now formatted in the
38  	 * same relative format as returned by {@code git log --relative-date}
39  	 *
40  	 * @param when
41  	 *            {@link java.util.Date} to format
42  	 * @return age of given {@link java.util.Date} compared to now formatted in
43  	 *         the same relative format as returned by
44  	 *         {@code git log --relative-date}
45  	 */
46  	@SuppressWarnings("boxing")
47  	public static String format(Date when) {
48  
49  		long ageMillis = SystemReader.getInstance().getCurrentTime()
50  				- when.getTime();
51  
52  		// shouldn't happen in a perfect world
53  		if (ageMillis < 0)
54  			return JGitText.get().inTheFuture;
55  
56  		// seconds
57  		if (ageMillis < upperLimit(MINUTE_IN_MILLIS))
58  			return MessageFormat.format(JGitText.get().secondsAgo,
59  					round(ageMillis, SECOND_IN_MILLIS));
60  
61  		// minutes
62  		if (ageMillis < upperLimit(HOUR_IN_MILLIS))
63  			return MessageFormat.format(JGitText.get().minutesAgo,
64  					round(ageMillis, MINUTE_IN_MILLIS));
65  
66  		// hours
67  		if (ageMillis < upperLimit(DAY_IN_MILLIS))
68  			return MessageFormat.format(JGitText.get().hoursAgo,
69  					round(ageMillis, HOUR_IN_MILLIS));
70  
71  		// up to 14 days use days
72  		if (ageMillis < 14 * DAY_IN_MILLIS)
73  			return MessageFormat.format(JGitText.get().daysAgo,
74  					round(ageMillis, DAY_IN_MILLIS));
75  
76  		// up to 10 weeks use weeks
77  		if (ageMillis < 10 * WEEK_IN_MILLIS)
78  			return MessageFormat.format(JGitText.get().weeksAgo,
79  					round(ageMillis, WEEK_IN_MILLIS));
80  
81  		// months
82  		if (ageMillis < YEAR_IN_MILLIS)
83  			return MessageFormat.format(JGitText.get().monthsAgo,
84  					round(ageMillis, MONTH_IN_MILLIS));
85  
86  		// up to 5 years use "year, months" rounded to months
87  		if (ageMillis < 5 * YEAR_IN_MILLIS) {
88  			long years = round(ageMillis, MONTH_IN_MILLIS) / 12;
89  			String yearLabel = (years > 1) ? JGitText.get().years : //
90  					JGitText.get().year;
91  			long months = round(ageMillis - years * YEAR_IN_MILLIS,
92  					MONTH_IN_MILLIS);
93  			String monthLabel = (months > 1) ? JGitText.get().months : //
94  					(months == 1 ? JGitText.get().month : ""); //$NON-NLS-1$
95  			return MessageFormat.format(
96  					months == 0 ? JGitText.get().years0MonthsAgo : JGitText
97  							.get().yearsMonthsAgo,
98  					new Object[] { years, yearLabel, months, monthLabel });
99  		}
100 
101 		// years
102 		return MessageFormat.format(JGitText.get().yearsAgo,
103 				round(ageMillis, YEAR_IN_MILLIS));
104 	}
105 
106 	private static long upperLimit(long unit) {
107 		long limit = unit + unit / 2;
108 		return limit;
109 	}
110 
111 	private static long round(long n, long unit) {
112 		long rounded = (n + unit / 2) / unit;
113 		return rounded;
114 	}
115 }