maxwell在处理timestamp默认使用字段类型时utc时间差8小时。尝试修改配置`jdbc_options`和`replication_jdbc_options`,但都解决不了这个问题。参照https://github.com/zendesk/maxwell/issues/903,重编解决这个问题。环境
jdk | java version "12.0.2" 2019-07-16 |
maxwell | 1.33.1 |
涉及的修改com.zendesk.maxwell.schema.columndef.ColumnDef.java
修改前: case "datetime": case "timestamp": return new DateTimeColumnDef(name, type, pos, columnLength); 修改后: case "datetime": return new DateTimeColumnDef(name, type, pos, columnLength); case "timestamp": return new TimeStampColumnDef(name, type, pos, columnLength);
新增
com.zendesk.maxwell.schema.columndef.TimeStampColumnDef.java
package com.zendesk.maxwell.schema.columndef; import com.zendesk.maxwell.producer.MaxwellOutputConfig; import java.sql.Timestamp; public class TimeStampColumnDef extends ColumnDefWithLength { public TimeStampColumnDef(String name, String type, short pos, Long columnLength) { super(name, type, pos, columnLength); } @Override protected String formatValue(Object value, MaxwellOutputConfig config) throws ColumnDefCastException { Timestamp ts = TimeStampFormatter.extractTimestamp(value); String dateString = TimeStampFormatter.formatDateTime(value, ts); if ( dateString == null ) return null; else return appendFractionalSeconds(dateString, ts.getNanos(), columnLength); } }
新增com.zendesk.maxwell.schema.columndef.TimeStampFormatter.java
package com.zendesk.maxwell.schema.columndef; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; public class TimeStampFormatter { private static SimpleDateFormat makeFormatter(String format, boolean utc) { SimpleDateFormat dateFormatter = new SimpleDateFormat(format); dateFormatter.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); return dateFormatter; } private static SimpleDateFormat dateFormatter = makeFormatter("yyyy-MM-dd", false); private static SimpleDateFormat dateUTCFormatter = makeFormatter("yyyy-MM-dd", true); private static SimpleDateFormat dateTimeFormatter = makeFormatter("yyyy-MM-dd HH:mm:ss", false); private static SimpleDateFormat dateTimeUTCFormatter = makeFormatter("yyyy-MM-dd HH:mm:ss", true); public static Timestamp extractTimestamp(Object value) { if (value instanceof Long) { Long micros = (Long) value; long millis = floorDiv(micros, 1000L); Timestamp t = new Timestamp(millis); long microsOnly = floorMod(micros, (long) 1000000); t.setNanos((int) microsOnly * 1000); return t; } else if (value instanceof Timestamp) { return (Timestamp) value; } else if ( value instanceof Date ) { Long time = ((Date) value).getTime(); return new Timestamp(time); } else throw new RuntimeException("couldn't extract date/time out of " value); } private static Timestamp MIN_DATE = Timestamp.valueOf("1000-01-01 00:00:00"); private static String format(SimpleDateFormat formatter, Timestamp ts) { if ( ts.before(MIN_DATE) ) { return null; } else { synchronized(formatter) { return formatter.format(ts); } } } public static String formatDate(Object value) { SimpleDateFormat formatter; if ( value instanceof Long ) formatter = dateUTCFormatter; else formatter = dateFormatter; return format(formatter, extractTimestamp(value)); } public static String formatDateTime(Object value, Timestamp ts) { SimpleDateFormat formatter; if ( value instanceof Long ) formatter = dateTimeUTCFormatter; else formatter = dateTimeFormatter; return format(formatter, ts); } private static long floorDiv(long a, long b) { return ((a < 0)?(a - (b - 1)):a) / b; } private static long floorMod(long x, long y) { return x - floorDiv(x, y) * y; } }
重新编译
mvn clean package -DskipTests