LocalDateTime,ZonedDateTime和时间戳
我有一个SpringBoot应用程序.使用Spring Initializer,嵌入式Tomcat,Thymeleaf模板引擎以及作为可执行JAR文件的软件包.
I have a SpringBoot app. using Spring Initializer, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR file.
我有一个具有2个属性(initDate,endDate)的域对象.我想创建2个转换器来处理mySQL DB
I have a domain object with 2 properties (initDate, endDate). I want to create 2 converters to deal with mySQL DB
@Convert(converter = LocalDateTimeAttributeConverter.class)
private LocalDateTime initDate;
@Convert(converter = ZonedDateTimeAttributeConverter.class)
private ZonedDateTime endDate;
转换器1(可以)
@Converter
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime localDateTime) {
return (localDateTime == null ? null : Timestamp.valueOf(localDateTime));
}
@Override
public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
}
}
这是我要创建的那个
@Converter
public class ZonedDateTimeAttributeConverter implements AttributeConverter<ZonedDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(ZonedDateTime zoneDateTime) {
return (zoneDateTime == null ? null : Timestamp.valueOf(zoneDateTime));
}
@Override
public ZonedDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return (sqlTimestamp == null ? null : sqlTimestamp.toZonedDateTime());
}
}
但是我不能,因为我有两个错误:
But I can't because I have 2 errors:
The method valueOf(String) in the type Timestamp is not applicable for the arguments (ZonedDateTime)
,并且时间戳记没有方法toZonedDateTime()
and the TimeStamp does not have the method toZonedDateTime()
如果我不为ZonedDate添加任何转换器,JPA将创建一个类型为varbinary(255)
and if I don't add any converter for the ZonedDate, JPA creates a table with the type varbinary(255)
时间戳扩展了Date
以提供纳秒级的精度. Date
和Timestamp
都没有设计为将特定时区称为ZoneDateTime
.
Timestamp extends Date
to provide nanosecond accuracy. Neither Date
nor Timestamp
are designed to refer to a specific timezone as ZoneDateTime
.
如果需要转换ZonedDateTime
-> Timestamp
,则必须放弃时区/偏移量信息.例如
If you need to convert ZonedDateTime
-> Timestamp
you will have to discard the timezone/offset information. E.g.
LocalDateTime withoutTimezone = zoneDateTime.toLocalDateTime();
Timestamp timestamp = Timestamp.valueOf(withoutTimezone));
,要转换Timestamp
-> ZonedDateTime
,您需要指定一个偏移量:
and for converting Timestamp
-> ZonedDateTime
you need to specify an offset:
LocalDateTime withoutTimezone = sqlTimestamp.toLocalDateTime();
ZonedDateTime withTimezone = withoutTimezone.atZone(ZoneId.of("+03:00"));
或时区:
ZonedDateTime withTimezone = withoutTimezone.atZone(ZoneId.of("Europe/Paris"));
如果您打算将ZonedDateTime
变量保存在数据库中并保留在那里指定的各个时区,则建议相应地设计数据库.建议:
If your intention is to save ZonedDateTime
variables in the database and preserve the various timezones specified there, I recommend designing your database accordingly. Suggestions:
- 使用类型为
DATETIME
的列保存LocalDateTime
和VARCHAR
保存时区,如"Europe/Paris"
或SMALLINT
保存以分钟为单位的偏移量. - 将
ZonedDateTime
转换为String
,并保存在VARCHAR
列中,例如"2017-05-16T14:12:48.983682+01:00[Europe/London]"
.然后,当您从数据库中读取数据时,必须对其进行解析.
- Use a column of type
DATETIME
to save aLocalDateTime
and aVARCHAR
saving a timezone like"Europe/Paris"
or aSMALLINT
saving an offset in minutes. - Convert the
ZonedDateTime
to aString
and save in aVARCHAR
column like"2017-05-16T14:12:48.983682+01:00[Europe/London]"
. You'll then have to parse it when reading from the database.