首页 > 数据库 >关于debezium同步mysql字段类型的datetime、date、time、timestamp的格式转换说明

关于debezium同步mysql字段类型的datetime、date、time、timestamp的格式转换说明

时间:2023-12-22 16:33:36浏览次数:43  
标签:12 String timestamp time datetime 2023 mysql date debezium

1.情景展示

使用debezium的插件:debezium-connector-oracle(io.debezium.connector.mysql.MySqlConnector),自动读取mysql日志binlog相关表的数据变更记录,然后将其发布到kafka topic当中。

现在遇到的问题是:

在mysql当中,表示日期类型的数据类型有:datetime、date和timestamp;

表示时间类型的是:time。

当使用io.debezium.connector.mysql.MySqlConnector插件读取mysql数据后,debezium自动对日期类型进行了格式转换。

2.具体分析

先说都转成了什么数据类型,再说怎么解决。

如上图所示,该表当中每个日期类型都有,下面我们进行实战演练。

抓取数据

我使用的REST API的方式来抓取mysql数据。

消费数据

得到其中一条数据如下:

所使用的debezium-connector-oracle插件版本号:2.2.1

id=4的mysql数据展示如下:

由此可以得出以下结论:

mysql datetime类型:使用的转换类是io.debezium.time.Timestamp,最终转成了时间戳(距离1970年01月01日0时0分0秒的毫秒数),形如:1702027934000。

mysql date类型:使用的转换类是io.debezium.time.Date,最终转成了天数(距离1970年01月01日的天数),形如:19699。

mysql timestamp类型:使用的转换类是io.debezium.time.ZonedTimestamp,最终转成了带时钟的时间戳,形如:2023-12-08T15:32:19Z

mysql time类型:使用的转换类是io.debezium.time.MicroTime,最终转成了微妙数(将小时转成了微妙),形如:34341000000。

3.解决方案

在mysql当中,最常用的是datetime类型,当将我们将时间戳转回日期字符串时,发现:所得时间比原来的时间早了8个小时。

这是因为:debezium在将datetime类型转成时间戳时,所用时区为:UTC,而我们在解析时间的时候,用的时区却是:UTC+8,所以最终转换得来的时间会比实际时间早8个小时。

网上搜到的解决办法都是:

无论是设置连接数据库所用时区还是设置数据库服务时间为东八区,统统不管用!

debezium在进行日期格式转换时,默认使用的是UTC,所以你再怎么设置数据库时间都无济于事!

第一种方案:更改debezium源码

源码地址:https://github.com/debezium/debezium

更改源码后,重新打包。

第二种方案:自定义开发Sink Connector

既然我们没有办法通过参数设置,将日期还原成正确时区,那我们完全可以从kafka拿数据自行解析。

先说如何将日期还原成真实日期。

datetime还原

// 年月日(大写M:表示月份,小写m:表示分钟)
public static final String FORMAT_DATE = "yyyy-MM-dd";
// 时分秒(大写H:表示24小时制,小写h:表示12小时制)
public static final String FORMAT_TIME = "HH:mm:ss";
// 年月日时分秒
public static final String FORMAT_DATE_TIME = FORMAT_DATE + " " + FORMAT_TIME;

public static String timestampToString(Long timestamp, String timeZone) {
    if (String.valueOf(timestamp).length() == 16) {// 16:毫秒
        return toDateTimeString(fromTimeMills(timestamp / 1000, timeZone), FORMAT_DATE_TIME);
    } else {// 13:秒
        return toDateTimeString(fromTimeMills(timestamp, timeZone), FORMAT_DATE_TIME);
    }
}

public static LocalDateTime fromTimeMills(long timeMills, String timeZone){
    return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeMills), ZoneId.of(timeZone));
}

/**
 * 日期转字符串(日期+时间)
 * @attention: jdk>=1.8
 * @date: 2020年08月31日 0031 17:04
 * @param: dateTime
 * @param: pattern
 * @return: java.lang.String
 */
public static String toDateTimeString(LocalDateTime dateTime, String pattern) {
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
    return dateTimeFormatter.format(dateTime);
}

调用

timestampToString(1702027934000L,"UTC");// 2023-12-08 09:32:14

date还原

/**
 * 根据天数倒推日期
 * https://www.cnblogs.com/Marydon20170307/p/10672030.html
 * @param days
 * @return
 */
public static String getSomeDay(int days){
    SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DATE);
    Date date;
    try {
        date = sdf.parse("1970-01-01");
    } catch (ParseException e) {
        throw new RuntimeException(e);
    }
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.add(Calendar.DAY_OF_YEAR, days);
    date = calendar.getTime();
    return sdf.format(date);
}

调用

getSomeDay(19699);// 2023-12-08

timestamp还原

/**
 * ISO 8601标准日期转成字符串
 * @param dateTimeStr
 * 2023-12-07T16:00:00Z
 * "2023-12-07T16:00:00Z"是一种ISO 8601标准的日期时间表示方式
 * 这个字符串表示的是一个特定的时间点:2023年12月7日,下午4点(16点),0分钟,0秒。其中“T”是时间标识符,“Z”表示的是协调世界时(UTC)。
 * 这种格式是可以精确到秒的时间戳
 * @return
 */
public static String fromISO8601(String dateTimeStr) {
    return toDateTimeString(toLocalDateTime(dateTimeStr), FORMAT_DATE_TIME);
}

/**
 * 日期字符串按指定格式转LocalDateTime
 * @attention:
 * @date: 2021/7/28 15:05
 * @param: dateTimeStr 日期字符串
 * 2023-12-07T16:00:00Z
 * "2023-12-07T16:00:00Z"是一种ISO 8601标准的日期时间表示方式
 * 这个字符串表示的是一个特定的时间点:2023年12月7日,下午4点(16点),0分钟,0秒。其中“T”是时间标识符,“Z”表示的是协调世界时(UTC)。
 * 这种格式是可以精确到秒的时间戳
 * @return: java.time.LocalDateTime
 */
public static LocalDateTime toLocalDateTime(String dateTimeStr) {
    // UTC时间
    DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
    ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateTimeStr, formatter);
    // TODO
    return zonedDateTime.toLocalDateTime().plusHours(-6);
}

说明:将UTC时间转成本地时间后,需要向前或向后推几个小时,需要自己算一下。

这里的-6,不一定对,我也不知道debezium是怎么进行转换的,竟然比实际时间早了6个小时,而不是8个小时。

调用

fromISO8601("2023-12-08T15:32:19Z");// 2023-12-08 09:32:19

至于自定义开发Sink Connector组件,请看下一篇文章。

写在最后

  哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!

 相关推荐:

标签:12,String,timestamp,time,datetime,2023,mysql,date,debezium
From: https://www.cnblogs.com/Marydon20170307/p/17921900.html

相关文章

  • JavaTimeModule 所在包
    JavaTimeModule是jackson转换java8时间类的需要的typo包,但是jackson-databind包中不存在这个类,JavaTimeModule所在包为jackson-datatype-jsr310,maven坐标如下:<!--https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310--><dependency......
  • 【go】Go (Golang) 语言-Golang 定时器Timer和Ticker、time.AfterFunc、time.NewTicke
    Golang定时器Timer和TickerGolang定时器包括:一次性定时器(Timer)和周期性定时器(Ticker)。编程中经常会通过timer和ticker、AfterFunc定时器NewTicker是设定每隔多长时间触发的,是连续触发,而计时器NewTimer是等待多长时间触发的,只触发一次,两者是不同的。等待时间函数AfterFunc是......
  • time 和 hashlib模块
    【一】time模块【1】时间戳importtimeprint(time.time())#1703122154.8660362【2】时间元组本地时间print(time.localtime(time.time()))#time.struct_time(tm_year=2023,tm_mon=12,tm_mday=21,tm_hour=9,tm_min=30,tm_sec=38,tm_wday=3,tm_yday=355,tm_isdst=......
  • Timestamp
    概述Athinwrapperaround<code>java.util.Date</code>thatallowstheJDBCAPItoidentifythisasanSQL<code>TIMESTAMP</code>value.ItaddstheabilitytoholdtheSQL<code>TIMESTAMP</code>fractionalsecondsvalue,......
  • Oracle12c新增max_idle_time参数的学习与感触
    Oracle12c新增max_idle_time参数的学习与感触TLDR其实任何软件出了新版本.readme是很重要的.尤其是数据库,涉及到底层问题的.比如这次遇到的Oracle的max_idle_time参数,以及前几天遇到的Mysql的新增的parallel关键字.自己之前的积累可能是一盏明灯,也可能是一堵墙.......
  • 初中英语优秀范文100篇-033My Free Time-我的业余时间
    PDF格式公众号回复关键字:SHCZFW033记忆树1Ihavealotofthingstodoinmyfreetime.翻译我有很多空闲时间要做的事情。简化记忆事情句子结构主语(I):表示句子中的主体,即说话者本人。谓语(have):表示主体所进行的动作或状态,这里是“有”的意思。宾语(alotofthing......
  • TimeZone
    概述<code>TimeZone</code>representsatimezoneoffset,andalsofiguresoutdaylightsavings.Typically,yougeta<code>TimeZone</code>using<code>getDefault</code>whichcreatesa<code>TimeZone</code>b......
  • datetime模块
    datetime模块(1)导入模块importdatetime(2)自定义日期并格式化datetime.date()自定义日期并格式化##2.自定义日期并格式化#res=datetime.date(2023,8,18)#print(res)##2023-08-18(3)获取本地时间datetime.date.today()获取年月日##(1)年月日#now_date=datetime.......
  • Derivative norm vector repect to time 《PBM by Pixar》 Appendix D.2 code
    目录1Derivativenormalvectorrepecttotime1.1DerivativevectornormrepecttotimeXRefVectorCalculus1DerivativenormalvectorrepecttotimeLet'sdenotetheunitnormalvectoras:\[\mathbf{n}=\frac{\mathbf{e}_a\times\mathbf{e}_b}{......
  • time模块
    time模块表示时间的三种方式时间戳元组(struct_time)格式化的时间字符串:格式化的时间字符串(FormatString):‘1999-12-06’(1)导入模块importtime(2)时间戳(time)(1)生成时间戳生成时间戳,时间戳是浮点数类型##时间戳##time=time.time()##print(time)......