11package com .javadiscord .javabot .other ;
22
3+ import java .time .Clock ;
34import java .time .Duration ;
45import java .time .OffsetDateTime ;
56import java .time .format .DateTimeFormatter ;
@@ -17,14 +18,34 @@ public class TimeUtils {
1718 STANDARD_FORMATTER = DateTimeFormatter .ofPattern ("EEE',' dd/MM/yyyy',' HH:mm" , Locale .ENGLISH );
1819 }
1920
21+ private final Clock clock ;
22+
23+ public TimeUtils () {
24+ this (Clock .systemDefaultZone ());
25+ }
26+
27+ public TimeUtils (Clock clock ) {
28+ this .clock = clock ;
29+ }
30+
2031 /**
2132 * Returns the duration between the given time and now, respecting time zone
2233 * information.
2334 * @param time The time to get the duration to.
2435 * @return A duration between the given time and now.
2536 */
26- public static Duration durationToNow (OffsetDateTime time ) {
27- return Duration .between (time , OffsetDateTime .now (time .getOffset ()));
37+ public Duration durationToNow (OffsetDateTime time ) {
38+ return Duration .between (time , this .clock .instant ().atOffset (time .getOffset ()));
39+ }
40+
41+ /**
42+ * Shortcut to get a formatted duration string representing the duration
43+ * from the given time to now.
44+ * @param time The time to use.
45+ * @return A string representing the duration.
46+ */
47+ public String formatDurationToNow (OffsetDateTime time ) {
48+ return formatDuration (durationToNow (time ));
2849 }
2950
3051 /**
@@ -33,28 +54,34 @@ public static Duration durationToNow(OffsetDateTime time) {
3354 * @return A string representing a human-readable duration.
3455 */
3556 public static String formatDuration (Duration duration ) {
36- if (duration .toDays () > 365 ) {
37- return String .format ("%d years, %d days" , duration .toDays () / 365 , duration .toDays () % 365 );
38- } else if (duration .toDays () > 2 ) {
39- return String .format ("%d days" , duration .toDays ());
40- } else if (duration .toHours () > 2 ) {
41- return String .format ("%d hours" , duration .toHours ());
42- } else if (duration .toMinutes () > 2 ){
43- return String .format ("%d minutes" , duration .toMinutes ());
44- } else if (duration .toSeconds () > 2 ) {
45- return String .format ("%d seconds" , duration .toSeconds ());
57+ if (duration .toDays () >= 365 ) {
58+ long years = duration .toDays () / 365 ;
59+ long days = duration .toDays () % 365 ;
60+ StringBuilder sb = new StringBuilder (pluralize ("year" , "years" , years ));
61+ if (days > 0 ) sb .append (", " ).append (pluralize ("day" , "days" , days ));
62+ return sb .toString ();
63+ } else if (duration .toDays () > 0 ) {
64+ return pluralize ("day" , "days" , duration .toDays ());
65+ } else if (duration .toHours () > 0 ) {
66+ return pluralize ("hour" , "hours" , duration .toHours ());
67+ } else if (duration .toMinutes () > 0 ){
68+ return pluralize ("minute" , "minutes" , duration .toMinutes ());
69+ } else if (duration .toSeconds () > 0 ) {
70+ return pluralize ("second" , "seconds" , duration .toSeconds ());
4671 } else {
47- return String . format ( "%d milliseconds" , duration .toMillis ());
72+ return pluralize ( "millisecond" , " milliseconds" , duration .toMillis ());
4873 }
4974 }
5075
5176 /**
52- * Shortcut to get a formatted duration string representing the duration
53- * from the given time to now.
54- * @param time The time to use.
55- * @return A string representing the duration.
77+ * Formats an integer number with a suffix that agrees with the plurality of
78+ * the number. For example, this can produce "1 day" and "2 days".
79+ * @param single The singular form of the suffix.
80+ * @param plural The plural form of the suffix.
81+ * @param count The value to show.
82+ * @return A string representation that respects plurality.
5683 */
57- public static String formatDurationToNow ( OffsetDateTime time ) {
58- return formatDuration ( durationToNow ( time ) );
84+ private static String pluralize ( String single , String plural , long count ) {
85+ return count + " " + ( count == 1 ? single : plural );
5986 }
6087}
0 commit comments