Showing posts with label jodatime. Show all posts
Showing posts with label jodatime. Show all posts

Wednesday, 21 November 2012

clock changing - Is this a Long, Short or a Normal day

Time is always a thorn in the side of developers.

In my latest project I needed to know the number of hours in a day and I could find no easy method on existing classes to determine if the day was a clock change day. I thought the great Joda date time classes would have helped but I could not find the one I needed so I wrote this.

 public enum ClockChangeInfo {  
  LONG_DAY(90000000, 25), SHORT_DAY(82800000, 23), NORMAL_DAY(86400000, 24), INDETERMINATE(0, 0);  
  private int mMsecs;  
  private int mHrs;  
  private static final Map<Integer, ClockChangeInfo> MSEC = new HashMap<Integer, ClockChangeInfo>();  
  static {  
   for (ClockChangeInfo cci : values()) {  
    MSEC.put(new Integer(cci.mMsecs), cci);  
   }  
  }  
  ClockChangeInfo(int aMsecs, int aHrs) {  
   mMsecs = aMsecs;  
   mHrs = aHrs;  
  }  
  public int getHrs(ClockChangeInfo aCci) {  
   return aCci.mHrs;  
  }  
  public static ClockChangeInfo getDayType(DateMidnight dateToCheck) {  
   DateMidnight nextDay = dateToCheck.plusDays(1);  
   //this is a safe convert as it is only for day(n) - day(n-1)  
   Integer millis = (int)(nextDay.getMillis() - dateToCheck.getMillis());  
   ClockChangeInfo cci = MSEC.get(millis);  
   if (cci == null) {  
    return INDETERMINATE;  
   }  
   return cci;  
  }  
 }  

 public class ClockChangeUtil {  
  public static ClockChangeInfo getDayType(DateMidnight dateToCheck) {  
   return ClockChangeInfo.getDayType((dateToCheck));  
  }  
  public static int getNumHoursInDay(DateMidnight dateToCheck) {  
   ClockChangeInfo dayType = ClockChangeUtil.getDayType(dateToCheck);  
   return dayType.getHrs(dayType);  
  }  
  public static int getNumHalfHoursINMonthSoFar(DateMidnight dateToCheck) {  
   int numHours = 0;  
   int day = dateToCheck.getDayOfMonth();  
   if (day == 1) {  
    return 0;  
   }  
   DateMidnight dm = dateToCheck.minusDays(1);  
   do {  
    numHours += getNumHoursInDay(dm);  
    dm = dm.minusDays(1);  
    day--;  
   } while (day > 1);  
   return numHours * 2;  
  }  
 }  


and some test methods for it. NB these are UK based.


 public class ClockChangeUtilUnitTest  
 {  
  @Test  
  public void test_isLongDay() throws Exception  
  {  
   DateMidnight dm28 = new DateMidnight(2011, 10, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 10, 29);  
   DateMidnight dm30 = new DateMidnight(2011, 10, 30);  
   DateMidnight dm31 = new DateMidnight(2011, 10, 31);   
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm28));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm29));  
   assertEquals(ClockChangeInfo.LONG_DAY, ClockChangeUtil.getDayType(dm30));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm31));  
  }  
  @Test  
  public void test_isShortDay() throws Exception  
  {  
   DateMidnight dm26 = new DateMidnight(2011, 3, 26);  
   DateMidnight dm27 = new DateMidnight(2011, 3, 27);  
   DateMidnight dm28 = new DateMidnight(2011, 3, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 3, 29);  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm26));  
   assertEquals(ClockChangeInfo.SHORT_DAY, ClockChangeUtil.getDayType(dm27));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm28));  
   assertEquals(ClockChangeInfo.NORMAL_DAY, ClockChangeUtil.getDayType(dm29));  
  }  
  @Test  
  public void testClockChange() throws Exception  
  {  
   long millisInANormalDay = 24 * 60 * 60 * 1000;  
   long millisInALongDay = 25 * 60 * 60 * 1000;  
   DateMidnight dm28 = new DateMidnight(2011, 10, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 10, 29);  
   DateMidnight dm30 = new DateMidnight(2011, 10, 30);  
   DateMidnight dm31 = new DateMidnight(2011, 10, 31);  
   assertEquals(millisInANormalDay, dm29.getMillis() - dm28.getMillis());  
   assertEquals(millisInANormalDay, dm30.getMillis() - dm29.getMillis());  
   assertEquals(millisInALongDay, dm31.getMillis() - dm30.getMillis());  
   DateTime dt28 = new DateTime(dm28);  
   DateTime dt29 = new DateTime(dm29);  
   DateTime dt30 = new DateTime(dm30);  
   DateTime dt31 = new DateTime(dm31);  
   assertEquals(millisInANormalDay, dt29.getMillis() - dt28.getMillis());  
   assertEquals(millisInANormalDay, dt30.getMillis() - dt29.getMillis());  
   assertEquals(millisInALongDay, dt31.getMillis() - dt30.getMillis());  
   assertTrue(dt28.getZone().equals(dt29.getZone()));  
   assertTrue(dt28.getZone().equals(dt30.getZone()));  
   assertTrue(dt28.getZone().equals(dt31.getZone()));  
  }  
  @Test  
  public void test_getNumHoursInDay() throws Exception  
  {  
   DateMidnight dm26 = new DateMidnight(2011, 3, 26);  
   DateMidnight dm27 = new DateMidnight(2011, 3, 27);  
   DateMidnight dm28 = new DateMidnight(2011, 3, 28);  
   DateMidnight dm29 = new DateMidnight(2011, 3, 29);  
   assertEquals(24, ClockChangeUtil.getNumHoursInDay(dm26));  
   assertEquals(23, ClockChangeUtil.getNumHoursInDay(dm27));  
   assertEquals(24, ClockChangeUtil.getNumHoursInDay(dm28));  
   assertEquals(24, ClockChangeUtil.getNumHoursInDay(dm29));  
  }  
 }  





Wednesday, 8 July 2009

Testing Times - Freezing Times

I have found many tests that want to set a time in a class and then test that that object has the correct time set.

Often these tests will pass when run locally as unit tests but either fail as integration tests which tend to be slower or fail when run on a heavily loaded build server.

I came across the solution on Mark Needham's Blog making use of a joda-time.

There appears to be may other usefull classes such as LocalDate, a class that just holds the date, yep the bit that says 25/12/2009 with no time representation, ie just a date !!!