-
Type:
Bug
-
Status: Closed
-
Resolution: No Longer Reproducible
-
Affects Version/s: 6.1.0 CE GA1, 6.1.1 CE GA2
-
Fix Version/s: 6.2.0 CE M4
-
Component/s: Legacy Components, Legacy Components > API
-
Labels:
-
Environment:Tested on LR 6.1.0 CE GA1/Java6/Tomcat/WinXP (according to the javadoc, GA2 did not change this method).
DateUtil.getDaysBetween(Date, Date, TimeZone) has a one-off-error around midnight during the TimeZone's Daylight Savings timespan.
Reproduction is problematic (it's only noticeable in the FriendsActivities Portlet during daylight savings time either when checking between 23:00 and 23:59 or when looking later at an activity from that timespan – the "today" and "yesterday" headers are in the wrong position).
For testing, I added this code in view.jsp of the FriendsActivities portlet:
<%! public int getDaysCountBetween(Date date1, Date date2, TimeZone timeZone) { // copy of com.liferay.portal.kernel.util.DateUtil.getDaysBetween() // one line was changed (marked by a comment below) if (date1.after(date2)) { Date tempDate = date1; date1 = date2; date2 = tempDate; } Calendar startCal = null; Calendar endCal = null; int offset = 0; if (timeZone == null) { startCal = new GregorianCalendar(); endCal = new GregorianCalendar(); } else { startCal = new GregorianCalendar(timeZone); endCal = new GregorianCalendar(timeZone); offset = timeZone.getOffset(date2.getTime()); // this line is changed compared to trunk } startCal.setTime(date1); startCal.add(Calendar.MILLISECOND, offset); endCal.setTime(date2); endCal.add(Calendar.MILLISECOND, offset); int daysBetween = 0; while (CalendarUtil.beforeByDay(startCal.getTime(), endCal.getTime())) { startCal.add(Calendar.DAY_OF_MONTH, 1); daysBetween++; } return daysBetween; } %> <% Format df = FastDateFormatFactoryUtil.getSimpleDateFormat("dd.MM.yyyy HH:mm z", locale, TimeZone.getTimeZone("Europe/Berlin")); Date date0 = new SimpleDateFormat().parse("07.07.2012 20:30"); //parsing UTC time! Date date1 = new SimpleDateFormat().parse("07.07.2012 21:30"); Date date2 = new SimpleDateFormat().parse("07.07.2012 22:30"); Date date3 = new SimpleDateFormat().parse("07.07.2012 23:30"); Date date4 = new SimpleDateFormat().parse("07.07.2012 24:30"); %> Date0: <%= df.format(date0) %><br/> Date1: <%= df.format(date1) %><br/> Date2: <%= df.format(date2) %><br/> Date3: <%= df.format(date3) %><br/> Date4: <%= df.format(date4) %><br/> getDaysCountBetween(0, 1): <%= getDaysCountBetween(date0, date1, TimeZone.getTimeZone("Europe/Berlin")) %><br/> DateUtil.getDaysBetween(0, 1): <%= DateUtil.getDaysBetween(date0, date1, TimeZone.getTimeZone("Europe/Berlin")) %><br/> getDaysCountBetween(1, 2): <%= getDaysCountBetween(date1, date2, TimeZone.getTimeZone("Europe/Berlin")) %><br/> DateUtil.getDaysBetween(1, 2): <%= DateUtil.getDaysBetween(date1, date2, TimeZone.getTimeZone("Europe/Berlin")) %><br/> getDaysCountBetween(2, 3): <%= getDaysCountBetween(date2, date3, TimeZone.getTimeZone("Europe/Berlin")) %><br/> DateUtil.getDaysBetween(2, 3): <%= DateUtil.getDaysBetween(date2, date3, TimeZone.getTimeZone("Europe/Berlin")) %><br/> getDaysCountBetween(3, 4): <%= getDaysCountBetween(date3, date4, TimeZone.getTimeZone("Europe/Berlin")) %><br/> DateUtil.getDaysBetween(3, 4): <%= DateUtil.getDaysBetween(date3, date4, TimeZone.getTimeZone("Europe/Berlin")) %><br/>
The output of this is as follows (getDaysCountBetween is my patched function, DateUtil.getDaysBetween the trunk method; comments added manually):
Date0: 07.07.2012 22:30 MESZ Date1: 07.07.2012 23:30 MESZ Date2: 08.07.2012 00:30 MESZ Date3: 08.07.2012 01:30 MESZ Date4: 08.07.2012 02:30 MESZ getDaysCountBetween(0, 1): 0 //correct DateUtil.getDaysBetween(0, 1): 0 //correct getDaysCountBetween(1, 2): 1 //correct DateUtil.getDaysBetween(1, 2): 0 //incorrect getDaysCountBetween(2, 3): 0 //correct DateUtil.getDaysBetween(2, 3): 1 //incorrect getDaysCountBetween(3, 4): 0 //correct DateUtil.getDaysBetween(3, 4): 0 //correct
As you see, DateUtil.getDaysBetween() returns the "one day difference" in the wrong case while my corrected version above returns the correct differences. All I did was replacing the line
offset = timeZone.getRawOffset();
with
offset = timeZone.getOffset(date2);
in com.liferay.portal.kernel.util.DateUtil line 153 (method getDaysBetween).
getRawOffset() is the wrong method to use; I cite from it's javadoc: "Because this value is not affected by daylight saving time, it is called raw offset." (see http://docs.oracle.com/javase/6/docs/api/java/util/TimeZone.html#getRawOffset%28%29)