From 5b29c33e0c8643ff3a7b6d315689ccead28b3782 Mon Sep 17 00:00:00 2001 From: Nicolas De Amicis Date: Fri, 16 Aug 2019 15:05:53 +0200 Subject: [PATCH] Update AbstractRowsEventDataDeserializer.java datetime isn't necessarily in UTC (depend on timezone settings). In that case, the datetime deserialization is always wrong for datetime. --- .../AbstractRowsEventDataDeserializer.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/AbstractRowsEventDataDeserializer.java b/src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/AbstractRowsEventDataDeserializer.java index e7cf6d53..35e36982 100644 --- a/src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/AbstractRowsEventDataDeserializer.java +++ b/src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/AbstractRowsEventDataDeserializer.java @@ -417,7 +417,7 @@ protected Long asUnixTime(int year, int month, int day, int hour, int minute, in if (year == 0 || month == 0 || day == 0) { return invalidDateAndTimeRepresentation; } - return UnixTime.from(year, month, day, hour, minute, second, millis); + return convertLocalTimestamp(UnixTime.from(year, month, day, hour, minute, second, millis)); } protected int deserializeFractionalSeconds(int meta, ByteArrayInputStream inputStream) throws IOException { @@ -428,6 +428,33 @@ protected int deserializeFractionalSeconds(int meta, ByteArrayInputStream inputS } return 0; } + + private long convertLocalTimestamp(long millis) { + TimeZone tz = TimeZone.getDefault(); + Calendar c = Calendar.getInstance(tz); + long localMillis = millis; + int offset, time; + + c.set(1970, Calendar.JANUARY, 1, 0, 0, 0); + + // Add milliseconds + while (localMillis > Integer.MAX_VALUE) + { + c.add(Calendar.MILLISECOND, Integer.MAX_VALUE); + localMillis -= Integer.MAX_VALUE; + } + c.add(Calendar.MILLISECOND, (int)localMillis); + + // Stupidly, the Calendar will give us the wrong result if we use getTime() directly. + // Instead, we calculate the offset and do the math ourselves. + time = c.get(Calendar.MILLISECOND); + time += c.get(Calendar.SECOND) * 1000; + time += c.get(Calendar.MINUTE) * 60 * 1000; + time += c.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000; + offset = tz.getOffset(c.get(Calendar.ERA), c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), c.get(Calendar.DAY_OF_WEEK), time); + + return (millis - offset); + } private static int bitSlice(long value, int bitOffset, int numberOfBits, int payloadSize) { long result = value >> payloadSize - (bitOffset + numberOfBits);