mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
* fix the issue that client-adapter.rdb module loses precision when converting microsencond time * fix the issue that client-adapter.rdb module loses precision when converting to java.sql.Time or java.sql.Timestamp * fix the issue that client-adapter.rdb module loses precision when converting to java.sql.Time or java.sql.Timestamp
This commit is contained in:
@@ -327,4 +327,53 @@ public class Util {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the time string has millisecond or microsecond units
|
||||
* @param timeStr time string
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isAccuracyOverSecond(String timeStr){
|
||||
if (StringUtils.isEmpty(timeStr)) {
|
||||
return false;
|
||||
}
|
||||
String[] times = StringUtils.split(timeStr, ".");
|
||||
return times.length > 1 && !times[times.length - 1].isEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the datetime string has microsecond or nanosecond units
|
||||
* @param datetimeStr datetime string
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isAccuracyOverMillisecond(String datetimeStr){
|
||||
if (StringUtils.isEmpty(datetimeStr)) {
|
||||
return false;
|
||||
}
|
||||
String[] times = StringUtils.split(datetimeStr, ".");
|
||||
return times.length > 1 && times[times.length - 1].length() > 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* MySQL has fractional seconds support for TIME, DATETIME, and TIMESTAMP values, with up to microseconds (6 digits) precision.
|
||||
* ISO-8601 standard format is with up to nanoseconds (9 digits) precision, which is sufficient for storing MySQL time-related data.
|
||||
* @param datetimeStr datetime string
|
||||
* @return LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime parseISOLocalDateTime(String datetimeStr) {
|
||||
if (StringUtils.isEmpty(datetimeStr)) {
|
||||
return null;
|
||||
}
|
||||
datetimeStr = datetimeStr.trim();
|
||||
try {
|
||||
//Replace SPACE in middle with `T` to comply with ISO-8601 standard format
|
||||
return LocalDateTime.parse(datetimeStr.replace(" ", "T"));
|
||||
}catch (Exception e){
|
||||
logger.error("Convert datetime string to ISOLocalDateTime fail:{}", datetimeStr, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -220,12 +221,17 @@ public class SyncUtil {
|
||||
pstmt.setTime(i, new java.sql.Time(((java.util.Date) value).getTime()));
|
||||
} else if (value instanceof String) {
|
||||
String v = (String) value;
|
||||
if(Util.isAccuracyOverSecond(v)) {
|
||||
//the java.sql.time doesn't support for even millisecond, only setObject works here.
|
||||
pstmt.setObject(i, v);
|
||||
}else {
|
||||
java.util.Date date = Util.parseDate(v);
|
||||
if (date != null) {
|
||||
pstmt.setTime(i, new Time(date.getTime()));
|
||||
} else {
|
||||
pstmt.setNull(i, type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pstmt.setNull(i, type);
|
||||
}
|
||||
@@ -238,12 +244,23 @@ public class SyncUtil {
|
||||
} else if (value instanceof String) {
|
||||
String v = (String) value;
|
||||
if (!v.startsWith("0000-00-00")) {
|
||||
if(Util.isAccuracyOverMillisecond(v)){
|
||||
//convert to ISO-8601 standard format, with up to nanoseconds (9 digits) precision
|
||||
LocalDateTime isoDatetime = Util.parseISOLocalDateTime(v);
|
||||
if (isoDatetime != null) {
|
||||
pstmt.setTimestamp(i, Timestamp.valueOf(isoDatetime));
|
||||
} else {
|
||||
//if can't convert, set to null
|
||||
pstmt.setNull(i, type);
|
||||
}
|
||||
}else {
|
||||
java.util.Date date = Util.parseDate(v);
|
||||
if (date != null) {
|
||||
pstmt.setTimestamp(i, new Timestamp(date.getTime()));
|
||||
} else {
|
||||
pstmt.setNull(i, type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pstmt.setObject(i, value);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user