如何将Avro微秒时间戳(long类型)转换为LocalDateTime?
问题描述
我从使用Avro Schema的Kafka中获取到一个时间字段:
long dateTime = 1499070300000L; // 示例值,实际为微秒级时间戳
该字段的逻辑类型为"logical-timestamp-micros"。
我的DTO定义如下:
@JsonFormat(pattern = "dd.MM.yy HH:mm:ss") private LocalDateTime time;
我尝试将dateTime字段转换为符合上述格式的LocalDateTime,代码如下:
long dateTime = 1499070300000L; DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yy HH:mm:ss"); LocalDateTime localDateTime = LocalDateTime.parse(Instant.ofEpochMilli(dateTime) .atZone(ZoneId.systemDefault()) .format(dateTimeFormatter));
但运行时抛出错误:
Exception in thread "main" java.time.format.DateTimeParseException: Text '03.07.17 11:25:00' could not be parsed at index 0
错误原因与解决方案
核心错误点
- 时间戳单位不匹配:Avro的
logical-timestamp-micros是微秒级时间戳,但你调用了Instant.ofEpochMilli()(处理毫秒级时间戳),导致时间被错误放大1000倍,生成的时间字符串逻辑错误,后续解析失败。 - 冗余的格式化再解析:你先将时间对象格式化为字符串,再用同一解析器转回
LocalDateTime,完全没必要,额外的字符串转换反而可能引入格式匹配问题(比如Locale差异)。
正确转换代码
直接将微秒时间戳转换为Instant,再通过时区转成LocalDateTime即可,无需中间字符串转换:
long dateTime = 1499070300000L; // 微秒转毫秒,再生成Instant,最后转LocalDateTime LocalDateTime localDateTime = Instant.ofEpochMilli(dateTime / 1000) .atZone(ZoneId.systemDefault()) .toLocalDateTime();
如果使用Java 9及以上版本,推荐更精准的微秒处理方式:
// 直接处理微秒:秒数=微秒/1_000_000,纳秒=微秒%1_000_000 * 1_000 LocalDateTime localDateTime = Instant.ofEpochSecond(dateTime / 1_000_000, dateTime % 1_000_000 * 1_000) .atZone(ZoneId.systemDefault()) .toLocalDateTime();
补充说明
@JsonFormat注解仅影响JSON的序列化/反序列化格式,不影响Java对象内部的转换逻辑,手动转换时无需依赖该注解的格式。- 若使用Jackson等JSON框架,可直接配置Avro逻辑类型的转换器,避免手动转换的错误。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

