From b3f35278cead1c4647a10ae615258555618bd087 Mon Sep 17 00:00:00 2001 From: Florian Zschocke Date: Sat, 23 Oct 2021 23:20:47 +0200 Subject: [PATCH] TimeUtils: Increase testability and add tests Add tests for `timeAgo` to analyse issue #1248. The tests are dependent on when they run as they time functions use the current date and time. To make them testable in a reproducible way, we need the ability to pass in what we think is "now". So add overloaded methods that take a `now` parameter so that we can pass in the current time. --- .../java/com/gitblit/utils/TimeUtils.java | 40 ++++- .../java/com/gitblit/tests/TimeUtilsTest.java | 157 ++++++++++++++++++ 2 files changed, 189 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/gitblit/utils/TimeUtils.java b/src/main/java/com/gitblit/utils/TimeUtils.java index c0e98e5d..001e6be6 100644 --- a/src/main/java/com/gitblit/utils/TimeUtils.java +++ b/src/main/java/com/gitblit/utils/TimeUtils.java @@ -59,7 +59,11 @@ public class TimeUtils { * @return true if date is today */ public static boolean isToday(Date date, TimeZone timezone) { - Date now = new Date(); + return isToday(date, timezone, new Date()); + } + + + public static boolean isToday(Date date, TimeZone timezone, Date now) { SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); if (timezone != null) { df.setTimeZone(timezone); @@ -74,8 +78,13 @@ public class TimeUtils { * @return true if date is yesterday */ public static boolean isYesterday(Date date, TimeZone timezone) { + return isYesterday(date, timezone, new Date()); + } + + + public static boolean isYesterday(Date date, TimeZone timezone, Date now) { Calendar cal = Calendar.getInstance(); - cal.setTime(new Date()); + cal.setTime(now); cal.add(Calendar.DATE, -1); SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); if (timezone != null) { @@ -157,7 +166,12 @@ public class TimeUtils { * @return hours ago */ public static int hoursAgo(Date date, boolean roundup) { - long diff = System.currentTimeMillis() - date.getTime(); + return hoursAgo(date, System.currentTimeMillis(), roundup); + } + + + public static int hoursAgo(Date date, long now, boolean roundup) { + long diff = now - date.getTime(); int hours = (int) (diff / ONEHOUR); if (roundup && (diff % ONEHOUR) >= HALFHOUR) { hours++; @@ -172,7 +186,11 @@ public class TimeUtils { * @return days ago */ public static int daysAgo(Date date) { - long today = ONEDAY * (System.currentTimeMillis()/ONEDAY); + return daysAgo(date, System.currentTimeMillis()); + } + + public static int daysAgo(Date date, long now) { + long today = ONEDAY * (now/ONEDAY); long day = ONEDAY * (date.getTime()/ONEDAY); long diff = today - day; int days = (int) (diff / ONEDAY); @@ -217,13 +235,19 @@ public class TimeUtils { * @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); + return timeAgo(date, css, System.currentTimeMillis()); + } + + + public String timeAgo(Date date, boolean css, long now) { + Date dNow = new Date(now); + if (isToday(date, timezone, dNow) || isYesterday(date, timezone, dNow)) { + int mins = minutesAgo(date, now, true); if (mins >= 120) { if (css) { return "age1"; } - int hours = hoursAgo(date, true); + int hours = hoursAgo(date, now, true); if (hours > 23) { return yesterday(); } else { @@ -238,7 +262,7 @@ public class TimeUtils { } return translate("gb.time.justNow", "just now"); } else { - int days = daysAgo(date); + int days = daysAgo(date, now); if (css) { if (days <= 7) { return "age2"; diff --git a/src/test/java/com/gitblit/tests/TimeUtilsTest.java b/src/test/java/com/gitblit/tests/TimeUtilsTest.java index ef506ef4..2dde6d51 100644 --- a/src/test/java/com/gitblit/tests/TimeUtilsTest.java +++ b/src/test/java/com/gitblit/tests/TimeUtilsTest.java @@ -15,7 +15,9 @@ */ package com.gitblit.tests; +import java.util.Calendar; import java.util.Date; +import java.util.TimeZone; import org.junit.Test; @@ -27,6 +29,10 @@ public class TimeUtilsTest extends GitblitUnitTest { return new Date(System.currentTimeMillis() - subtract); } + private Date offset(long now, long subtract) { + return new Date(now - subtract); + } + @Test public void testBasicTimeFunctions() throws Exception { assertEquals(2, TimeUtils.minutesAgo(offset(2 * TimeUtils.MIN), false)); @@ -89,8 +95,12 @@ public class TimeUtilsTest extends GitblitUnitTest { assertEquals("1 year ago", timeUtils.timeAgo(offset(365 * TimeUtils.ONEDAY))); assertEquals("13 months ago", timeUtils.timeAgo(offset(395 * TimeUtils.ONEDAY))); assertEquals("2 years ago", timeUtils.timeAgo(offset((2 * 365 + 30) * TimeUtils.ONEDAY))); + } + @Test + public void testTimeAgoCss() throws Exception { // css class tests + TimeUtils timeUtils = new TimeUtils(); assertEquals("age0", timeUtils.timeAgoCss(offset(1 * TimeUtils.MIN))); assertEquals("age0", timeUtils.timeAgoCss(offset(60 * TimeUtils.MIN))); assertEquals("age1", timeUtils.timeAgoCss(offset(120 * TimeUtils.MIN))); @@ -98,6 +108,74 @@ public class TimeUtilsTest extends GitblitUnitTest { assertEquals("age2", timeUtils.timeAgoCss(offset(2 * TimeUtils.ONEDAY))); } + + @Test + public void testTimeAgoYesterday() throws Exception { + TimeZone myTimezone = TimeZone.getTimeZone("GMT"); + TimeUtils timeUtils = new TimeUtils(null, myTimezone); + + Calendar myCal = Calendar.getInstance(myTimezone); + myCal.set(Calendar.HOUR_OF_DAY, 12); + myCal.set(Calendar.MINUTE, 0); + long now = myCal.getTime().getTime(); + + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,23 * TimeUtils.ONEHOUR), false, now)); + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (29 * TimeUtils.MIN)), false, now)); + + assertEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (31 * TimeUtils.MIN)), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,35 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,36 * TimeUtils.ONEHOUR), false, now)); + + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,37 * TimeUtils.ONEHOUR), false, now)); + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,44 * TimeUtils.ONEHOUR), false, now)); + } + + @Test + public void testTimeAgoYesterdayCET() throws Exception { + TimeZone myTimezone = TimeZone.getTimeZone("CET"); + TimeUtils timeUtils = new TimeUtils(null, myTimezone); + + Calendar myCal = Calendar.getInstance(myTimezone); + myCal.set(Calendar.HOUR_OF_DAY, 22); + myCal.set(Calendar.MINUTE, 0); + long now = myCal.getTime().getTime(); + + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,23 * TimeUtils.ONEHOUR), false, now)); + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (29 * TimeUtils.MIN)), false, now)); + + assertEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (31 * TimeUtils.MIN)), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,36 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,46 * TimeUtils.ONEHOUR), false, now)); + + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,47 * TimeUtils.ONEHOUR), false, now)); + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,56 * TimeUtils.ONEHOUR), false, now)); + } + + + @Test + public void testTimeAgoYesterdayPST() throws Exception { + TimeZone myTimezone = TimeZone.getTimeZone("PST"); + TimeUtils timeUtils = new TimeUtils(null, myTimezone); + + Calendar myCal = Calendar.getInstance(myTimezone); + myCal.set(Calendar.HOUR_OF_DAY, 8); + myCal.set(Calendar.MINUTE, 0); + long now = myCal.getTime().getTime(); + + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,23 * TimeUtils.ONEHOUR), false, now)); + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (29 * TimeUtils.MIN)), false, now)); + + assertEquals("yesterday", timeUtils.timeAgo(offset(now,(23 * TimeUtils.ONEHOUR) + (31 * TimeUtils.MIN)), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,30 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,32 * TimeUtils.ONEHOUR), false, now)); + + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,33 * TimeUtils.ONEHOUR), false, now)); + assertNotEquals("yesterday", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now)); + } + @Test public void testFrequency() { assertEquals(5, TimeUtils.convertFrequencyToMinutes("2 mins", 5)); @@ -105,4 +183,83 @@ public class TimeUtilsTest extends GitblitUnitTest { assertEquals(600, TimeUtils.convertFrequencyToMinutes("10 hours", 5)); assertEquals(14400, TimeUtils.convertFrequencyToMinutes(" 10 days ", 5)); } + + + @Test + public void testTimeAgoDaysAgo() throws Exception { + TimeZone myTimezone = TimeZone.getTimeZone("GMT"); + TimeUtils timeUtils = new TimeUtils(null, myTimezone); + + Calendar myCal = Calendar.getInstance(myTimezone); + myCal.set(Calendar.HOUR_OF_DAY, 12); + myCal.set(Calendar.MINUTE, 0); + long now = myCal.getTime().getTime(); + + assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,36 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,37 * TimeUtils.ONEHOUR), false, now)); + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now)); + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,60 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,61 * TimeUtils.ONEHOUR), false, now)); + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,72 * TimeUtils.ONEHOUR), false, now)); + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,84 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("4 days ago", timeUtils.timeAgo(offset(now,85 * TimeUtils.ONEHOUR), false, now)); + } + + + + @Test + public void testTimeAgoDaysAgoCET() throws Exception { + TimeZone myTimezone = TimeZone.getTimeZone("CET"); + TimeUtils timeUtils = new TimeUtils(null, myTimezone); + + Calendar myCal = Calendar.getInstance(myTimezone); + myCal.set(Calendar.HOUR_OF_DAY, 8); + myCal.set(Calendar.MINUTE, 0); + long now = myCal.getTime().getTime(); + + + assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,32 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,33 * TimeUtils.ONEHOUR), false, now)); + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now)); + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,56 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,57 * TimeUtils.ONEHOUR), false, now)); + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,72 * TimeUtils.ONEHOUR), false, now)); + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,80 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("4 days ago", timeUtils.timeAgo(offset(now,81 * TimeUtils.ONEHOUR), false, now)); + } + + + + @Test + public void testTimeAgoDaysAgoPST() throws Exception { + TimeZone myTimezone = TimeZone.getTimeZone("PST"); + TimeUtils timeUtils = new TimeUtils(null, myTimezone); + + Calendar myCal = Calendar.getInstance(myTimezone); + myCal.set(Calendar.HOUR_OF_DAY, 22); + myCal.set(Calendar.MINUTE, 0); + long now = myCal.getTime().getTime(); + + assertEquals("yesterday", timeUtils.timeAgo(offset(now,24 * TimeUtils.ONEHOUR), false, now)); + assertEquals("yesterday", timeUtils.timeAgo(offset(now,46 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,47 * TimeUtils.ONEHOUR), false, now)); + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,48 * TimeUtils.ONEHOUR), false, now)); + assertEquals("2 days ago", timeUtils.timeAgo(offset(now,70 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,71 * TimeUtils.ONEHOUR), false, now)); + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,72 * TimeUtils.ONEHOUR), false, now)); + assertEquals("3 days ago", timeUtils.timeAgo(offset(now,94 * TimeUtils.ONEHOUR), false, now)); + + assertEquals("4 days ago", timeUtils.timeAgo(offset(now,95 * TimeUtils.ONEHOUR), false, now)); + } + } -- 2.39.5