如何构造一个 OffsetDateTime() now 【可指定时区】 2024-04-21T18:18:35 执行如下代码 OffsetDateTime.now()); // 2024-04-21T18:18:35.161056700+08:00 OffsetDateTime.now(ZoneId.of("Asia/Tokyo"))); // 2024-04-21T19 :18:35.162570500+09:00 OffsetDateTime.now(Clock.systemUTC())); // 2024-04-21T10:18:35.162570500Z OffsetDateTime.parse("2019-07-07T20:18:18+09:00")); //2019-07-07T20:18:18+09:00 OffsetDateTime.parse +09:00 OffsetDateTime offsetDateTime = local_date_time.atOffset(ZoneOffset.ofHours(8));); //2019-07
升级完毕之后,执行所有现存的集成测试,发现有部分OffsetDateTime类型入参的查询方法出现异常,于是进行源码层面的DEBUG找到最终的问题并且解决。 startCreateTime, @Param("endCreateTime") OffsetDateTime endCreateTime MySQL驱动包解析OffsetDateTime类型的参数有版本兼容问题。 前面两种情况混合相互影响导致的,其实这里也可以理解为同一种情况,因为MyBatis归根到底是对MySQL驱动包进行了封装。 当时项目中使用的mysql-connector-java版本为8.0.18,并未升级为当前的最新版本8.0.21,所以当时也有怀疑是低版本MySQL驱动包没有兼容解析OffsetDateTime类型的参数 参数解析异常的根本原因 本文前面提到的解析OffsetDateTime类型异常,实际上执行查询的时候代码会步入OffsetDateTimeTypeHandler,这里对比一下3.4.5和3.5.5版本中
升级完毕之后,执行所有现存的集成测试,发现有部分OffsetDateTime类型入参的查询方法出现异常,于是进行源码层面的DEBUG找到最终的问题并且解决。 ? startCreateTime, @Param("endCreateTime") OffsetDateTime endCreateTime MySQL驱动包解析OffsetDateTime类型的参数有版本兼容问题。 前面两种情况混合相互影响导致的,其实这里也可以理解为同一种情况,因为MyBatis归根到底是对MySQL驱动包进行了封装。 当时项目中使用的mysql-connector-java版本为8.0.18,并未升级为当前的最新版本8.0.21,所以当时也有怀疑是低版本MySQL驱动包没有兼容解析OffsetDateTime类型的参数 参数解析异常的根本原因 本文前面提到的解析OffsetDateTime类型异常,实际上执行查询的时候代码会步入OffsetDateTimeTypeHandler,这里对比一下3.4.5和3.5.5版本中
min = OffsetDateTime.MIN; OffsetDateTime max = OffsetDateTime.MAX; System.out.println("OffsetDateTime OffsetDateTime -> LocalDateTime @Test public void test81() { OffsetDateTime offsetDateTime = OffsetDateTime.of -> ZonedDateTime @Test public void test101() { OffsetDateTime offsetDateTime = OffsetDateTime.of 那么再看这个例子(我把时间改为5月5号,也就是处于夏令营期间): @Test public void test101() { OffsetDateTime offsetDateTime = OffsetDateTime.of OffsetDateTime = LocalDateTime + 偏移量ZoneOffset;ZonedDateTime = LocalDateTime + 时区ZoneId OffsetDateTime
min = OffsetDateTime.MIN; OffsetDateTime max = OffsetDateTime.MAX; System.out.println("OffsetDateTime OffsetDateTime -> LocalDateTime @Test public void test81() { OffsetDateTime offsetDateTime = OffsetDateTime.of -> ZonedDateTime @Test public void test101() { OffsetDateTime offsetDateTime = OffsetDateTime.of 那么再看这个例子(我把时间改为5月5号,也就是处于夏令营期间): @Test public void test101() { OffsetDateTime offsetDateTime = OffsetDateTime.of OffsetDateTime = LocalDateTime + 偏移量ZoneOffset;ZonedDateTime = LocalDateTime + 时区ZoneId OffsetDateTime
Cause: org.postgresql.util.PSQLException: conversion to class java.time.OffsetDateTime from int4 not 具体来说,数据库中的’ id '列的数据类型是int4(整数),但在映射到Java实体类时,使用了java.time.OffsetDateTime(时间日期)类型,导致转换失败。 例如,在你的Java实体类中,将id字段的数据类型改为Long,而不是OffsetDateTime。这样,你就可以正确地映射数据库的id列数据到Java实体类。 这样,你可以在获取数据时,将数据库返回的int值转换为OffsetDateTime类型。这个方法需要编写一些代码,但可以让你在Java实体类中保持OffsetDateTime类型的数据。 假设我们有一个名为 User 的实体类,其中有一个字段名为 createTime,数据类型为 OffsetDateTime。
仿真场景 下面会结合一下仿真场景介绍具体的API选取,由于OffsetDateTime基本能满足大部分场景,因此挑选OffsetDateTime进行举例。 例如: public class Request { private OffsetDateTime createTime; public OffsetDateTime getCreateTime = OffsetDateTime.now(Z); OffsetDateTime start = now.plusDays(-1L).withHour(0).withMinute(0). OffsetDateTime getThisMonthOffsetDateTimeStart() { OffsetDateTime offsetDateTime = getCurrentOffsetDateTime OffsetDateTime offsetDateTime = getCurrentOffsetDateTime(); return offsetDateTime.with(TemporalAdjusters.lastDayOfMonth
) OffsetDateTime的常用静态工厂方法如下: // 基于当前的日期时间、时区ID、时钟创建OffsetDateTime实例 public static OffsetDateTime now( { public static void main(String[] args) throws Exception { OffsetDateTime offsetDateTime = OffsetDateTime.now (); System.out.println(offsetDateTime); offsetDateTime = OffsetDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); System.out.println(offsetDateTime); offsetDateTime = OffsetDateTime.of(LocalDateTime.now (); localDate = offsetDateTime.toLocalDate(); localTime = offsetDateTime.toLocalTime(); offsetDateTime
offsetDateTime = instant.atOffset(ZoneOffset.ofHours(-6)); System.out.println(offsetDateTime); //天数加 offsetDateTime = dateTime.atOffset(ZoneOffset.ofHours(-6)); System.out.println(offsetDateTime); //设置时区为美国时区 (时区变成固定的,不再根据夏令时动态调整) public OffsetDateTime toOffsetDateTime() OffsetDateTime,对应ZoneOffset加LocalDateTime OffsetDateTime of(LocalDateTime dateTime, ZoneOffset offset) public static OffsetDateTime ofInstant offsetDateTime = OffsetDateTime.ofInstant(Instant.now(), ZoneOffset.of("+0")); System.out.println(offsetDateTime
LocalDateTime dateTime = LocalDateTime.now(); ZoneOffset offset = ZoneOffset.of("+05:30"); OffsetDateTime offsetDateTime = OffsetDateTime.of(dateTime, offset); System.out.println(offsetDateTime); // 2020-05-30T12:48:54.655+05:30 System.out.println(OffsetDateTime.now()); //2020-05-30T12:48:54.655
Date.from(ZONED_DATE_TIME.toInstant())); //Sun Jul 07 19:18:18 CST 2019 【当前时区】 // 东9区时间到东8区时间转换会减去一个小时 OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneOffset.ofHours(9)); Date.from( Sun Jul 07 00:00:00 CST 2019 Mon Jul 01 00:00:00 CST 2019 Tue Jan 01 00:00:00 CST 2019 ZonedDateTime/OffsetDateTime [Asia/Shanghai] Date date = Date.from(zonedDateTime.toInstant()); // Fri Dec 27 14:26:28 CST 2024 OffsetDateTime offsetdatetime = OffsetDateTime.now(); // 2024-12-27T14:29:39.153629+08:00 Date date = Date.from(offsetdatetime.toInstant
ZonedDateTime ZONED_DATE_TIME = ZonedDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneId.of("Asia/Tokyo")); OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneOffset.ofHours(9)); LocalDateTime ZonedDateTime ZONED_DATE_TIME = ZonedDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneId.of("Asia/Tokyo")); OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneOffset.ofHours(9)); LocalDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneOffset.ofHours(9)); Date date
问题 问题挺简单的,就是在使用 mybatis 和 ShardingSphere 的时候,有人在 model 类使用了 OffsetDateTime 这个时间类型,发现会报错。 Caused by: java.lang.ClassCastException: class java.sql.Timestamp cannot be cast to class java.time.OffsetDateTime (java.sql.Timestamp is in module java.sql of loader 'platform'; java.time.OffsetDateTime is in module LocalDateTime.class.equals(type) || LocalDate.class.equals(type) || LocalTime.class.equals(type) || OffsetDateTime.class.equals 再去看了下 OffsetDateTimeTypeHandler的实现,其实就是自己就解决了,直接给返回OffsetDateTime ,根本不会走到 ShardingSphere 的逻辑里面去,这也就是他能解决这个问题的原因了
虽然上面的类的of 有一个需要时区参数的初始化函数,但是只用于获取当地时区时间,在初始化完成之后,Local 类中并没有保存时区信息,要显式表示时区,就需要使用下面的 ZonedDateTime 或 OffsetDateTime ` OffsetDateTime 是 LocalDateTime 与 ZonedOffset 组合起来形成的一个类。 //构造一个 +01:00 的时间 LocalDateTime localDateTime = LocalDateTime.now(); OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, ZoneOffset.ofHoursMinutes(1, 0)); // 查看 +02:45 时差处的时间 System.out.println (offsetDateTime.withOffsetSameInstant(ZoneOffset.ofHoursMinutes(2, 45))); API 命名原则 time 包使用了统一的命名规则,这源于它们的共同接口
System.out.println(now); } } 输出 2021-08-14T07:10:30.049Z 默认获取的是UTC时区的时间 跟当前时间不符 //偏移八个时区的时间 OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime); 输出 2021-08
例如:OffsetDateTime 可以寸尺值 “2nd October 2007 at 13:45.30.123456789 +02:00”。 让我们来获得针对 GMT/UTC 2 小时偏移量的 OffsetDateTime :ZoneOffset zoneOffSet= ZoneOffset.of("+02:00");OffsetDateTime date = OffsetDateTime.now(zoneOffSet);OffsetTimeOffsetTime 是不可变的的一个时间。 例如 Java 中使用的 ZonedDateTime, OffsetDateTime, 和 OffsetTime。
ZonedDateTime ZONED_DATE_TIME = ZonedDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneId.of("Asia/Tokyo")); OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2019, 7, 7, 20, 18, 18, 888, ZoneOffset.ofHours(9)); 获取时间 // 年 00 System.out.println(LocalDateTime.MAX); // +999999999-12-31T23:59:59.999999999 System.out.println(OffsetDateTime.MIN ); // -999999999-01-01T00:00+18:00 System.out.println(OffsetDateTime.MAX); // +999999999-12-31T23:59:
(在 ISO-8601 日历系统中,与 UTC/GMT 有偏移的日期时间): // E MMM yyyy HH:mm:ss.SSSZ OffsetDateTime offsetDateTime = OffsetDateTime.now (zoneOffsetFromString); OffsetDateTime offsetDateTime = OffsetDateTime.now(zoneOffsetFromString); 例如,下面的代码从前面的offsetDateTime对象获取区域偏移: // +02:00 ZoneOffset zoneOffsetFromOdt = offsetDateTime.getOffset 2019 public static Date offsetDateTimeToDate( OffsetDateTime offsetDateTime) { return Date.from (offsetDateTime.toLocalDateTime() .toInstant(ZoneOffset.of(offsetDateTime.getOffset().getId())));
Timestamp.valueOf(ZONED_DATE_TIME.toLocalDateTime())); //2019-07-07 20:18:18.000000888 【当前时区】 OffsetDateTime →Timestamp转换 → 【时区切换】 OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2019, 7, 7, 20, 18, 18, 888
可变性 可变(非线程安全) 不可变(线程安全) 设计 过时、易出错 现代、直观、类型安全 精度 毫秒 纳秒 时区支持 需配合 Calendar/TimeZone 需结合 ZonedDateTime 或 OffsetDateTime 明确时区需求: 如果需要时区信息,使用 ZonedDateTime 或 OffsetDateTime。 如果需要时间戳,使用 Instant(替代 Date)。 首选 LocalDateTime:处理本地时间时,使用 LocalDateTime;需要时区时,结合 ZonedDateTime 或 OffsetDateTime。