You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将CET时区MariaDB的Timestamp转换为Java的UTC LocalDateTime

解决方案

方法1:修正JDBC连接时区配置(优先尝试)

之前时区参数未生效大概率是配置格式不对,MariaDB Connector/J需要结合禁用旧日期处理逻辑的参数,同时明确数据库和应用侧时区:

在Spring Boot配置文件(application.properties)中修改数据源URL:

spring.datasource.url=jdbc:mariadb://<host>:<port>/<db_name>?useLegacyDatetimeCode=false&timeZone=CET&serverTimezone=UTC

或YAML格式:

spring:
  datasource:
    url: jdbc:mariadb://<host>:<port>/<db_name>?useLegacyDatetimeCode=false&timeZone=CET&serverTimezone=UTC
  • timeZone=CET:告知驱动数据库服务器的时区为CET,确保正确解析数据库返回的时间
  • serverTimezone=UTC:指定驱动将数据库时间转换为应用侧的UTC时区
  • useLegacyDatetimeCode=false:必须开启,否则旧日期处理逻辑会忽略时区参数

配置完成后,JPA映射的LocalDateTime字段会自动获取转换后的UTC时间。

方法2:自定义JPA属性转换器(连接参数无效时用)

如果JDBC参数仍不生效,可以通过AttributeConverter手动控制时区转换逻辑:

场景1:数据库字段为TIMESTAMP类型

创建转换器类:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.sql.Timestamp;

@Converter(autoApply = true) // 自动应用到所有LocalDateTime字段,也可单独指定到实体字段
public class CETToUTCLocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {

    private static final ZoneId CET_ZONE = ZoneId.of("CET");
    private static final ZoneId UTC_ZONE = ZoneId.of("UTC");

    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime utcLocalDateTime) {
        // 存储时:UTC时间转CET时区的Timestamp
        ZonedDateTime utcZoned = utcLocalDateTime.atZone(UTC_ZONE);
        ZonedDateTime cetZoned = utcZoned.withZoneSameInstant(CET_ZONE);
        return Timestamp.valueOf(cetZoned.toLocalDateTime());
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp cetTimestamp) {
        // 查询时:CET时区的Timestamp转UTC时间的LocalDateTime
        ZonedDateTime cetZoned = cetTimestamp.toLocalDateTime().atZone(CET_ZONE);
        ZonedDateTime utcZoned = cetZoned.withZoneSameInstant(UTC_ZONE);
        return utcZoned.toLocalDateTime();
    }
}

然后在实体类对应字段上标注:

@Column(name = "your_timestamp_column")
@Convert(converter = CETToUTCLocalDateTimeConverter.class)
private LocalDateTime yourDateTimeField;

场景2:数据库字段为BIGINT(存储Unix时间戳)

如果数据库用整数存储Unix时间戳(10位秒/13位毫秒),转换器可以这样写:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

@Converter(autoApply = true)
public class UnixTimestampToUTCLocalDateTimeConverter implements AttributeConverter<LocalDateTime, Long> {

    private static final ZoneId UTC_ZONE = ZoneId.of("UTC");
    private static final boolean USE_MILLISECONDS = true; // 根据实际存储单位调整

    @Override
    public Long convertToDatabaseColumn(LocalDateTime utcLocalDateTime) {
        Instant instant = utcLocalDateTime.atZone(UTC_ZONE).toInstant();
        return USE_MILLISECONDS ? instant.toEpochMilli() : instant.getEpochSecond();
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Long unixTimestamp) {
        Instant instant = USE_MILLISECONDS ? Instant.ofEpochMilli(unixTimestamp) : Instant.ofEpochSecond(unixTimestamp);
        return LocalDateTime.ofInstant(instant, UTC_ZONE);
    }
}

实体类字段对应标注即可。

方法3:SQL层面直接转换(快速验证用)

在JPA自定义查询中,使用MariaDB的CONVERT_TZ函数直接转换时区:

@Query("SELECT e.id, CONVERT_TZ(e.yourTimestampField, 'CET', 'UTC') as yourUtcDateTime FROM ExampleEntity e WHERE ...")
List<Object[]> findUtcDateTimeList();

若使用Example查询,可替换为自定义查询方法,避开Example自动生成的SQL逻辑。


内容的提问来源于stack exchange,提问作者Jérémy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:17:44