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