I had a bug that caused an integer overflow, resulting in wrong (negative) timestamps being written to the database. The code is fixed already, but I want to fix the wrong data, too.
I thought, I could just take the wrong results and add Integer.MAX_VALUE, but that didn't seem to work, it left me with to high values. I have the offset
value in the code snippet below, but the input values are not stored.
The following code reproduces the bug:
@Test
public void testArexxConversion()
{
// The input values represent seconds since midnight, Jan 1, 2000 UTC
final int sample = 361450072; // A sample input value drawn from production
// I use the offset from the UNIX epoch to convert the vakue to UNIX seconds
final int offset = 946684800; // midnight, Jan 01 2000 UTC in UNIX seconds
// This was the buggy line in my code, the assertion will fail
long result = (sample + offset) * 1000;
// Prints 'Result is negative: -1830153280'
Assert.assertTrue(result > 0, String.format("Result is negative: %d", result));
// This is for comparison
Date dt = new Date(offset * 1000);
Assert.assertEquals(dt.getTime() + sample * 1000, result);
}
To fix the bug in your database you can do the following addition to all the buggy data:
long new_result = old_buggy_result + 1309965025280L;
The constant number was found like this:
result
valueresult
value be?result
value to find the correct `result.But this is only possible if you have saved sample
and offset
in your database or somewhere else.
Otherwise, it depends on the number of wraps that occured during the original calculation:
long size_of_int = (long)Math.pow(2, 32);
int number_of_wraps = 305 // Only correct in your example!
// You can't deduct the number of wraps from
// the wrong value alone, because that information
// is lost in the modulo (the "wrap")
long correct_number = wrong_number + size_of_int * number_of_wraps;
If the numbers in your database are close enough to your sample value, this means, you can do the above, using 305 as the number of wraps.
The operation here:
(sample + offset) * 1000;
is computed using int
and not long
. But the result is "too big" to be saved on an int
variable. That's why you have an overflow.
Change it to:
((long) sample + offset) * 1000L;
So now the +
and *
operations will be done using long
values, and the result will be a long
value which won't overflow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With