|
@@ -0,0 +1,60 @@
|
|
|
+package org.dbsyncer.listener.mysql.deserializer;
|
|
|
+
|
|
|
+import com.github.shyiko.mysql.binlog.io.ByteArrayInputStream;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.Serializable;
|
|
|
+import java.sql.Timestamp;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+public class DatetimeV2Deserialize {
|
|
|
+
|
|
|
+ public Serializable deserializeDatetimeV2(int meta, ByteArrayInputStream inputStream) throws IOException {
|
|
|
+ long datetime = bigEndianLong(inputStream.read(5), 0, 5);
|
|
|
+ int yearMonth = bitSlice(datetime, 1, 17, 40);
|
|
|
+ int fsp = deserializeFractionalSeconds(meta, inputStream);
|
|
|
+ LocalDateTime time = LocalDateTime.of(
|
|
|
+ yearMonth / 13,
|
|
|
+ yearMonth % 13,
|
|
|
+ bitSlice(datetime, 18, 5, 40),
|
|
|
+ bitSlice(datetime, 23, 5, 40),
|
|
|
+ bitSlice(datetime, 28, 6, 40),
|
|
|
+ bitSlice(datetime, 34, 6, 40),
|
|
|
+ fsp / 1000
|
|
|
+ );
|
|
|
+ return Timestamp.valueOf(time);
|
|
|
+ }
|
|
|
+
|
|
|
+ private long bigEndianLong(byte[] bytes, int offset, int length) {
|
|
|
+ long result = 0;
|
|
|
+ for (int i = offset; i < (offset + length); i++) {
|
|
|
+ byte b = bytes[i];
|
|
|
+ result = (result << 8) | (b >= 0 ? (int) b : (b + 256));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int deserializeFractionalSeconds(int meta, ByteArrayInputStream inputStream) throws IOException {
|
|
|
+ int length = (meta + 1) / 2;
|
|
|
+ if (length > 0) {
|
|
|
+ int fraction = bigEndianInteger(inputStream.read(length), 0, length);
|
|
|
+ return fraction * (int) Math.pow(100, 3 - length);
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int bigEndianInteger(byte[] bytes, int offset, int length) {
|
|
|
+ int result = 0;
|
|
|
+ for (int i = offset; i < (offset + length); i++) {
|
|
|
+ byte b = bytes[i];
|
|
|
+ result = (result << 8) | (b >= 0 ? (int) b : (b + 256));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private int bitSlice(long value, int bitOffset, int numberOfBits, int payloadSize) {
|
|
|
+ long result = value >> payloadSize - (bitOffset + numberOfBits);
|
|
|
+ return (int) (result & ((1 << numberOfBits) - 1));
|
|
|
+ }
|
|
|
+
|
|
|
+}
|