Here is my code:
long treatmentTimeBeginDay;
if ( effectiveBegin.after(businessClosing) ) {
LOGGER.debug("Compute treatment time for beginDay = 0: the effective begin {} is after business closing {}",
config.formatLogDate(effectiveBegin),config.formatLogDate(businessClosing));
treatmentTimeBeginDay = 0;
} else {
LOGGER.debug("Compute treatment time for beginDay between {} and {}",config.formatLogDate(effectiveBegin),config.formatLogDate(businessClosing));
treatmentTimeBeginDay = businessClosing.getTime() - effectiveBegin.getTime();
}
Preconditions.checkState( treatmentTimeBeginDay >= 0 , "Internal bug! treatmentTimeBeginDay="+treatmentTimeBeginDay );
effectiveBegin and businessClosing are not null, also checked by Guava preconditions and you can see it in the logs…
It runs fine in most cases but in production we have these errors:
Caused by: java.lang.IllegalStateException: Internal bug!
treatmentTimeBeginDay=-852
I don’t give you the rest of the stack/code because it should be enough…
The exception is explicitly raised by my Guava checkState call.
I also have the log:
DEBUG [BusinessHoursUtils.java:257] llairie – Compute treatment time
for beginDay between 7/19/12 8:00 PM and 7/19/12 8:00 PM
(I can’t have log with millies for now)
What i’m trying to understand is.
If i get the log i gave you, this means that the test if ( effectiveBegin.after(businessClosing) ) is false, so effectiveBegin should be before or equals to the businessClosing.
In this case effectiveBegin timestamp should be lower than the businessClosing timestamp.
So when i do businessClosing.getTime() - effectiveBegin.getTime(); i would expect to have a positive number.
So please can someone tell me why i have -852 milliseconds in my exception message? How is this possible?
Edit: I was suspecting a tricky case where the after/before method wouldn’t work for milliseconds and it seems that’s the problem since i could reproduce it locally.
The 2 dates at runtime are:
businessClosing = {java.util.Date@503}"Thu Jul 19 20:00:00 CEST 2012"
fastTime = 1342720800000
cdate = null
effectiveBegin = {java.sql.Timestamp@498}"2012-07-19 20:00:00.999"
nanos = 999000000
fastTime = 1342720800000
cdate = {sun.util.calendar.Gregorian$Date@512}"2012-07-19T20:00:00.000+0200"
With these runtime objects, effectiveBegin.after(businessClosing) = false
If i set in DB effectiveBegin = 2012-07-19 20:00:01.000, 1 millisecond later, then the test = true
In both cases i would expect to have effectiveBegin.after(businessClosing) = true
It seems, like ametren suspected, that my dates are different.
So in the end, what’s the problem?
Aren’t we supposed to be able to compare the 2 date instance with a millisecond precision?
Even if they are subclasses of the java.util.Date?
The problem here is that you mix Timestamp and Date.
Timestamp.after(Date)compares only the milliseconds of the Date components, which are both1342720800000in your example.However,
Timestamp.getTime()does also consider the Nanoseconds (999000000ns = 999ms) that are stored within the Timestamp and will return1342720800999. SobusinessClosing.getTime() - effectiveBegin.getTime()will return-999as result.To solve this issue, you could modify the if-statement to
if(effectiveBegin.compareTo(businessClosing) > 0)or you could convert thebusinessClosingDateto aTimestampbefore the if-statement.