From 118287880982d8eb99eb4f42343cbd7cf75e32cb Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Tue, 9 Feb 2016 15:32:08 +0100 Subject: [PATCH] Resolved issue where the aggregated weeks do not start at the correct point in time. Former-commit-id: 278186f35cef87a3e4ca46ecf816d01338f6b104 --- src/se/hal/util/TimeUtility.java | 33 ++++++++++- test/se/hal/util/TimeUtilityTest.java | 81 ++++++++++++++++++--------- 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/src/se/hal/util/TimeUtility.java b/src/se/hal/util/TimeUtility.java index f7613925..513375bf 100755 --- a/src/se/hal/util/TimeUtility.java +++ b/src/se/hal/util/TimeUtility.java @@ -31,12 +31,23 @@ public class TimeUtility { Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(timestamp); boolean clear = false; + + int weeks = getWeeksFromTimestamp(periodLengthInMs); + if(weeks > 0){ + int currentWeek = cal.get(Calendar.WEEK_OF_YEAR); + cal.set(Calendar.WEEK_OF_YEAR, (currentWeek/weeks)*weeks); + clear = true; + } + int days = getDaysFromTimestamp(periodLengthInMs); - if(days > 0){ + if(days%7 > 0){ int currentDay = cal.get(Calendar.DAY_OF_YEAR); cal.set(Calendar.DAY_OF_YEAR, (currentDay/days)*days); clear = true; + }else if(clear){ + cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); } + int hours = getHourOfDayFromTimestamp(periodLengthInMs); if(hours > 0){ int currentHour = cal.get(Calendar.HOUR_OF_DAY); @@ -45,6 +56,7 @@ public class TimeUtility { }else if(clear){ cal.set(Calendar.HOUR_OF_DAY, 0); } + int minutes = getMinuteOfHourFromTimestamp(periodLengthInMs); if(minutes > 0){ int currentMinute = cal.get(Calendar.MINUTE); @@ -53,6 +65,7 @@ public class TimeUtility { }else if(clear){ cal.set(Calendar.MINUTE, 0); } + int seconds = getSecondOfMinuteFromTimestamp(periodLengthInMs); if(seconds > 0){ int currentSecond = cal.get(Calendar.SECOND); @@ -61,6 +74,7 @@ public class TimeUtility { }else if(clear){ cal.set(Calendar.SECOND, 0); } + int milliseconds = getMillisecondInSecondFromTimestamp(periodLengthInMs); if(milliseconds > 0){ int currentMillisecond = cal.get(Calendar.MILLISECOND); @@ -68,6 +82,7 @@ public class TimeUtility { }else if(clear){ cal.set(Calendar.MILLISECOND, 0); } + return cal.getTimeInMillis(); } @@ -101,12 +116,24 @@ public class TimeUtility { return (int) (ms / DAY_IN_MS); } + public static int getWeeksFromTimestamp(long ms) throws NumberFormatException{ + if(ms < 0) + throw new NumberFormatException("argument must be positive"); + return (int) (ms / WEEK_IN_MS); + } + public static String msToString(long ms) throws NumberFormatException{ if(ms < 0) throw new NumberFormatException("argument must be positive"); String retval = ""; - int days = getDaysFromTimestamp(ms); - retval += days + "days+"; + int weeks = getWeeksFromTimestamp(ms); + if(weeks > 0){ + retval += weeks + "w+"; + } + int days = getDaysFromTimestamp(ms) % 7; + if(days > 0){ + retval += days + "d+"; + } int hours = getHourOfDayFromTimestamp(ms); retval += (hours<10?"0"+hours:hours); int minutes = getMinuteOfHourFromTimestamp(ms); diff --git a/test/se/hal/util/TimeUtilityTest.java b/test/se/hal/util/TimeUtilityTest.java index 13939fa4..64f28f8d 100755 --- a/test/se/hal/util/TimeUtilityTest.java +++ b/test/se/hal/util/TimeUtilityTest.java @@ -6,6 +6,7 @@ import org.junit.Test; import java.util.Calendar; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class TimeUtilityTest { private long currentTime_UTC; @@ -18,6 +19,21 @@ public class TimeUtilityTest { referenceCalendar_LOCAL.setTimeInMillis(currentTime_UTC); } + // Test flooring LOCAL time to the closes day + @Test + public void testWeekStart_LOCAL_ForCurrentTime(){ + long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart_LOCAL(TimeUtility.WEEK_IN_MS, currentTime_UTC); + Calendar testCalendar = Calendar.getInstance(); + testCalendar.setTimeInMillis(thisPeriodStartedAt); + + assertEquals("millisecond is wrong", 0, testCalendar.get(Calendar.MILLISECOND)); + assertEquals("second is wrong", 0, testCalendar.get(Calendar.SECOND)); + assertEquals("minute is wrong", 0, testCalendar.get(Calendar.MINUTE)); + assertEquals("hour is wrong", 0, testCalendar.get(Calendar.HOUR_OF_DAY)); + assertTrue("day is wrong", Math.abs(referenceCalendar_LOCAL.get(Calendar.DAY_OF_YEAR)-testCalendar.get(Calendar.DAY_OF_YEAR)) <= 6); //day cannot differ more than 6 days + assertEquals("week is wrong", referenceCalendar_LOCAL.get(Calendar.WEEK_OF_YEAR), testCalendar.get(Calendar.WEEK_OF_YEAR)); + } + // Test flooring LOCAL time to the closes day @Test public void testDayStart_LOCAL_ForCurrentTime(){ @@ -30,6 +46,7 @@ public class TimeUtilityTest { assertEquals("minute is wrong", 0, testCalendar.get(Calendar.MINUTE)); assertEquals("hour is wrong", 0, testCalendar.get(Calendar.HOUR_OF_DAY)); assertEquals("day is wrong", referenceCalendar_LOCAL.get(Calendar.DAY_OF_YEAR), testCalendar.get(Calendar.DAY_OF_YEAR)); + assertEquals("week is wrong", referenceCalendar_LOCAL.get(Calendar.WEEK_OF_YEAR), testCalendar.get(Calendar.WEEK_OF_YEAR)); } // Test flooring LOCAL time to the closes hour @@ -44,6 +61,7 @@ public class TimeUtilityTest { assertEquals("minute is wrong", 0, testCalendar.get(Calendar.MINUTE)); assertEquals("hour is wrong", referenceCalendar_LOCAL.get(Calendar.HOUR_OF_DAY), testCalendar.get(Calendar.HOUR_OF_DAY)); assertEquals("day is wrong", referenceCalendar_LOCAL.get(Calendar.DAY_OF_YEAR), testCalendar.get(Calendar.DAY_OF_YEAR)); + assertEquals("week is wrong", referenceCalendar_LOCAL.get(Calendar.WEEK_OF_YEAR), testCalendar.get(Calendar.WEEK_OF_YEAR)); } // Test flooring LOCAL time to the closes minute @@ -58,6 +76,7 @@ public class TimeUtilityTest { assertEquals("minute is wrong", referenceCalendar_LOCAL.get(Calendar.MINUTE), testCalendar.get(Calendar.MINUTE)); assertEquals("hour is wrong", referenceCalendar_LOCAL.get(Calendar.HOUR_OF_DAY), testCalendar.get(Calendar.HOUR_OF_DAY)); assertEquals("day is wrong", referenceCalendar_LOCAL.get(Calendar.DAY_OF_YEAR), testCalendar.get(Calendar.DAY_OF_YEAR)); + assertEquals("week is wrong", referenceCalendar_LOCAL.get(Calendar.WEEK_OF_YEAR), testCalendar.get(Calendar.WEEK_OF_YEAR)); } // Test flooring LOCAL time to the closes second @@ -72,8 +91,22 @@ public class TimeUtilityTest { assertEquals("minute is wrong", referenceCalendar_LOCAL.get(Calendar.MINUTE), testCalendar.get(Calendar.MINUTE)); assertEquals("hour is wrong", referenceCalendar_LOCAL.get(Calendar.HOUR_OF_DAY), testCalendar.get(Calendar.HOUR_OF_DAY)); assertEquals("day is wrong", referenceCalendar_LOCAL.get(Calendar.DAY_OF_YEAR), testCalendar.get(Calendar.DAY_OF_YEAR)); + assertEquals("week is wrong", referenceCalendar_LOCAL.get(Calendar.WEEK_OF_YEAR), testCalendar.get(Calendar.WEEK_OF_YEAR)); } + // Test flooring UTC time to the closes week + @Test + public void testWeekStart_UTC_ForCurrentTime(){ + long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart_UTC(TimeUtility.WEEK_IN_MS, currentTime_UTC); + + assertEquals("millisecond is wrong", 0, TimeUtility.getMillisecondInSecondFromTimestamp(thisPeriodStartedAt)); + assertEquals("second is wrong", 0, TimeUtility.getSecondOfMinuteFromTimestamp(thisPeriodStartedAt)); + assertEquals("minute is wrong", 0, TimeUtility.getMinuteOfHourFromTimestamp(thisPeriodStartedAt)); + assertEquals("hour is wrong", 0, TimeUtility.getHourOfDayFromTimestamp(thisPeriodStartedAt)); + assertTrue("day is wrong", Math.abs(TimeUtility.getDaysFromTimestamp(currentTime_UTC)-TimeUtility.getDaysFromTimestamp(thisPeriodStartedAt)) <= 6); //day cannot differ more than 6 days + assertEquals("week is wrong", TimeUtility.getWeeksFromTimestamp(currentTime_UTC), TimeUtility.getWeeksFromTimestamp(thisPeriodStartedAt)); + } + // Test flooring UTC time to the closes day @Test public void testDayStart_UTC_ForCurrentTime(){ @@ -84,79 +117,77 @@ public class TimeUtilityTest { assertEquals("minute is wrong", 0, TimeUtility.getMinuteOfHourFromTimestamp(thisPeriodStartedAt)); assertEquals("hour is wrong", 0, TimeUtility.getHourOfDayFromTimestamp(thisPeriodStartedAt)); assertEquals("day is wrong", TimeUtility.getDaysFromTimestamp(currentTime_UTC), TimeUtility.getDaysFromTimestamp(thisPeriodStartedAt)); + assertEquals("week is wrong", TimeUtility.getWeeksFromTimestamp(currentTime_UTC), TimeUtility.getWeeksFromTimestamp(thisPeriodStartedAt)); } // Test flooring UTC time to the closes hour @Test public void testHourStart_UTC_ForCurrentTime(){ long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart_UTC(TimeUtility.HOUR_IN_MS, currentTime_UTC); - Calendar testCalendar = Calendar.getInstance(); - testCalendar.setTimeInMillis(thisPeriodStartedAt); assertEquals("millisecond is wrong", 0, TimeUtility.getMillisecondInSecondFromTimestamp(thisPeriodStartedAt)); assertEquals("second is wrong", 0, TimeUtility.getSecondOfMinuteFromTimestamp(thisPeriodStartedAt)); assertEquals("minute is wrong", 0, TimeUtility.getMinuteOfHourFromTimestamp(thisPeriodStartedAt)); assertEquals("hour is wrong", TimeUtility.getHourOfDayFromTimestamp(currentTime_UTC), TimeUtility.getHourOfDayFromTimestamp(thisPeriodStartedAt)); assertEquals("day is wrong", TimeUtility.getDaysFromTimestamp(currentTime_UTC), TimeUtility.getDaysFromTimestamp(thisPeriodStartedAt)); + assertEquals("week is wrong", TimeUtility.getWeeksFromTimestamp(currentTime_UTC), TimeUtility.getWeeksFromTimestamp(thisPeriodStartedAt)); } // Test flooring UTC time to the closes minute @Test public void testMinuteStart_UTC_ForCurrentTime(){ long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart_UTC(TimeUtility.MINUTES_IN_MS, currentTime_UTC); - Calendar testCalendar = Calendar.getInstance(); - testCalendar.setTimeInMillis(thisPeriodStartedAt); assertEquals("millisecond is wrong", 0, TimeUtility.getMillisecondInSecondFromTimestamp(thisPeriodStartedAt)); assertEquals("second is wrong", 0, TimeUtility.getSecondOfMinuteFromTimestamp(thisPeriodStartedAt)); assertEquals("minute is wrong", TimeUtility.getMinuteOfHourFromTimestamp(currentTime_UTC), TimeUtility.getMinuteOfHourFromTimestamp(thisPeriodStartedAt)); assertEquals("hour is wrong", TimeUtility.getHourOfDayFromTimestamp(currentTime_UTC), TimeUtility.getHourOfDayFromTimestamp(thisPeriodStartedAt)); assertEquals("day is wrong", TimeUtility.getDaysFromTimestamp(currentTime_UTC), TimeUtility.getDaysFromTimestamp(thisPeriodStartedAt)); + assertEquals("week is wrong", TimeUtility.getWeeksFromTimestamp(currentTime_UTC), TimeUtility.getWeeksFromTimestamp(thisPeriodStartedAt)); } // Test flooring UTC time to the closes second @Test public void testSecondStart_UTC_ForCurrentTime(){ long thisPeriodStartedAt = TimeUtility.getTimestampPeriodStart_UTC(TimeUtility.SECOND_IN_MS, currentTime_UTC); - Calendar testCalendar = Calendar.getInstance(); - testCalendar.setTimeInMillis(thisPeriodStartedAt); assertEquals("millisecond is wrong", 0, TimeUtility.getMillisecondInSecondFromTimestamp(thisPeriodStartedAt)); assertEquals("second is wrong", TimeUtility.getSecondOfMinuteFromTimestamp(currentTime_UTC), TimeUtility.getSecondOfMinuteFromTimestamp(thisPeriodStartedAt)); assertEquals("minute is wrong", TimeUtility.getMinuteOfHourFromTimestamp(currentTime_UTC), TimeUtility.getMinuteOfHourFromTimestamp(thisPeriodStartedAt)); assertEquals("hour is wrong", TimeUtility.getHourOfDayFromTimestamp(currentTime_UTC), TimeUtility.getHourOfDayFromTimestamp(thisPeriodStartedAt)); assertEquals("day is wrong", TimeUtility.getDaysFromTimestamp(currentTime_UTC), TimeUtility.getDaysFromTimestamp(thisPeriodStartedAt)); + assertEquals("week is wrong", TimeUtility.getWeeksFromTimestamp(currentTime_UTC), TimeUtility.getWeeksFromTimestamp(thisPeriodStartedAt)); } // Test printing converting milliseconds to text @Test public void testMsToString(){ //low values - assertEquals("0days+00:00:00.000", TimeUtility.msToString(0)); - assertEquals("0days+00:00:00.001", TimeUtility.msToString(1)); - assertEquals("0days+00:00:01.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS)); - assertEquals("0days+00:01:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS)); - assertEquals("0days+00:05:00.000", TimeUtility.msToString(TimeUtility.FIVE_MINUTES_IN_MS)); - assertEquals("0days+01:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS)); - assertEquals("1days+00:00:00.000", TimeUtility.msToString(TimeUtility.DAY_IN_MS)); - assertEquals("7days+00:00:00.000", TimeUtility.msToString(TimeUtility.WEEK_IN_MS)); + assertEquals("00:00:00.000", TimeUtility.msToString(0)); + assertEquals("00:00:00.001", TimeUtility.msToString(1)); + assertEquals("00:00:01.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS)); + assertEquals("00:01:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS)); + assertEquals("00:05:00.000", TimeUtility.msToString(TimeUtility.FIVE_MINUTES_IN_MS)); + assertEquals("01:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS)); + assertEquals("1d+00:00:00.000", TimeUtility.msToString(TimeUtility.DAY_IN_MS)); + assertEquals("1w+00:00:00.000", TimeUtility.msToString(TimeUtility.WEEK_IN_MS)); //high values - assertEquals("0days+00:00:00.999", TimeUtility.msToString(999)); - assertEquals("0days+00:00:59.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS*59)); - assertEquals("0days+00:59:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS*59)); - assertEquals("0days+23:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS*23)); - assertEquals("369days+00:00:00.000", TimeUtility.msToString(TimeUtility.DAY_IN_MS*369)); + assertEquals("00:00:00.999", TimeUtility.msToString(999)); + assertEquals("00:00:59.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS*59)); + assertEquals("00:59:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS*59)); + assertEquals("23:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS*23)); + assertEquals("52w+5d+00:00:00.000", TimeUtility.msToString(TimeUtility.DAY_IN_MS*369)); //high overflow values - assertEquals("0days+00:00:01.999", TimeUtility.msToString(1999)); - assertEquals("0days+00:02:39.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS*159)); - assertEquals("0days+02:39:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS*159)); - assertEquals("5days+03:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS*123)); + assertEquals("00:00:01.999", TimeUtility.msToString(1999)); + assertEquals("00:02:39.000", TimeUtility.msToString(TimeUtility.SECOND_IN_MS*159)); + assertEquals("02:39:00.000", TimeUtility.msToString(TimeUtility.MINUTES_IN_MS*159)); + assertEquals("5d+03:00:00.000", TimeUtility.msToString(TimeUtility.HOUR_IN_MS*123)); //combinations - long ms = (TimeUtility.DAY_IN_MS*999) + (TimeUtility.HOUR_IN_MS*23) + (TimeUtility.MINUTES_IN_MS*59) + (TimeUtility.SECOND_IN_MS*59) + 999; - assertEquals("999days+23:59:59.999", TimeUtility.msToString(ms)); + assertEquals("142w+5d+23:59:59.999", TimeUtility.msToString((TimeUtility.WEEK_IN_MS*142) + (TimeUtility.DAY_IN_MS*5) + (TimeUtility.HOUR_IN_MS*23) + (TimeUtility.MINUTES_IN_MS*59) + (TimeUtility.SECOND_IN_MS*59) + 999)); + assertEquals("6d+23:59:59.999", TimeUtility.msToString(TimeUtility.WEEK_IN_MS-1)); } // Test printing converting milliseconds to text for a negative time