如何使用EclipseLink和Joda-Time将UTC中的日期时间存储到数据库中? [英] How to store date-time in UTC into a database using EclipseLink and Joda-Time?
问题描述
很长时间以来,我一直在使用以下EclipseLink Joda-Time 转换器,将日期时间存储在 UTC 到MySQL数据库中完全没有成功.
I have been fumbling with the following EclipseLink Joda-Time converter for a long time to store date-time in UTC into MySQL database with no success at all.
import java.util.Date;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.converters.Converter;
import org.eclipse.persistence.sessions.Session;
import org.joda.time.DateTime;
public final class JodaDateTimeConverter implements Converter {
private static final long serialVersionUID = 1L;
@Override
public Object convertObjectValueToDataValue(Object objectValue, Session session) {
//Code to convert org.joda.time.DateTime to java.util.Date in UTC.
//Currently dealing with the following line
//that always uses the system local time zone which is incorrect.
//It should be in the UTC zone.
return objectValue instanceof DateTime ? ((DateTime) objectValue).toDate() : null;
}
@Override
public Object convertDataValueToObjectValue(Object dataValue, Session session) {
return dataValue instanceof Date ? new DateTime((Date) dataValue) : null;
}
@Override
public boolean isMutable() {
return true;
}
@Override
public void initialize(DatabaseMapping databaseMapping, Session session) {
databaseMapping.getField().setType(java.util.Date.class);
}
}
convertObjectValueToDataValue()
方法的objectValue
参数是instanceOf
DateTime
,该参数已经根据UTC区域设置.因此,我避免使用.withZone(DateTimeZone.UTC)
.
The objectValue
parameter of the convertObjectValueToDataValue()
method is an instanceOf
DateTime
which is already according to UTC zone. Therefore, I have avoided .withZone(DateTimeZone.UTC)
.
客户端上已经存在一个单独的转换器,该转换器将日期时间的String表示形式转换为UTC中的org.joda.time.DateTime
,然后再将其发送到EJB.)
There is already a separate converter on the client that converts a String representation of date-time to org.joda.time.DateTime
in UTC before sending it to EJBs).
convertObjectValueToDataValue()
方法的return语句中的此((DateTime) objectValue).toDate()
始终采用应位于UTC区域中的系统本地时区.
This ((DateTime) objectValue).toDate()
in the return statement of the convertObjectValueToDataValue()
method always takes the system local time zone that should be in the UTC zone.
应该根据UTC区域将任何日期时间插入MySQL.
Anyway date-time should be inserted into MySQL according to the UTC zone.
最好/理想的解决方案是,如果它处理Joda的日期时间类似于休眠
在模型类中,如下指定类型为org.joda.time.DateTime
的属性.
A property of type org.joda.time.DateTime
as an example is designated in a model class as follows.
@Column(name = "discount_start_date", columnDefinition = "DATETIME")
@Converter(name = "dateTimeConverter", converterClass = JodaDateTimeConverter.class)
@Convert("dateTimeConverter")
private DateTime discountStartDate; //Getter and setter.
推荐答案
我没有得到这个问题,尤其是关于转换为java.util.Date将使用系统时区的声明.以下测试显示了另一种正确的行为:
I don't get the question and especially the statement that conversion to java.util.Date would use the system time zone. Following test shows a different and correct behaviour:
DateTime joda = new DateTime(2014, 3, 14, 0, 0, DateTimeZone.UTC);
Date d = joda.toDate();
System.out.println(joda.getMillis()); // 1394755200000
System.out.println(d.getTime()); // 1394755200000
当然,如果您打印Date变量d,则其toString()方法使用系统时区,但是对象joda
和d
都表示相同的时刻,就像在表示形式中看到的一样.从UNIX时代UTC区域以来的毫秒数.
Of course, if you print the Date-variable d, then its toString()-method uses the system time zone, but the objects joda
and d
both represent the same instant as you can see in the representation of milliseconds since UNIX epoch in UTC-zone.
例如System.out.println(d);
在我的时区生成此字符串:
For example System.out.println(d);
produces this string in my time zone:
2014年3月14日星期五欧洲中部时间
Fri Mar 14 01:00:00 CET 2014
但这不是结果的内部状态,不会存储在数据库中,因此请不要感到困惑或担心.顺便说一句,您将需要根据数据库中的列类型将结果转换为java.sql.Date或java.sql.Timestamp.
But that is not the internal state of the result and will not be stored in database, so don`t be confused or worry about. By the way, you will need to convert the result to either java.sql.Date or java.sql.Timestamp depending on the column type in your database.
要确定UTC,您应该更改其他方法convertDataValueToObjectValue()
并使用类似以下的显式转换:
To be sure about UTC you should change your other method convertDataValueToObjectValue()
and use an explicit conversion like:
new DateTime((Date) dataValue, DateTimeZone.UTC)
否则(假设反向方法如您所说一直在UTC中始终具有DateTime对象),您可能会出现不对称现象(目前我不知道在没有DateTimeZone参数的情况下构造函数中JodaTime在这里做了什么-文献记载不充分?).
Otherwise (assuming that the reverse method has always DateTime-objects in UTC as you said) you might get an asymmetry (I don't know at this moment what JodaTime does here in constructor without DateTimeZone-argument - not so well documented?).
EDIT-2:
测试代码
DateTime reverse = new DateTime(d);
System.out.println(reverse); // 2014-03-14T01:00:00.000+01:00
System.out.println(reverse.getZone()); // Europe/Berlin
清楚地表明,没有第二个DateTimeZone参数的DateTime构造函数隐式使用系统时区(我不喜欢Joda或java.util.*中的此类隐式值).如果往返于UTC-DateTime对象的整个转换不起作用,那么我认为您输入的DateTime对象可能不是真正的UTC.我建议对此进行明确检查.否则,我们没有足够的信息说明为什么您的转换代码不起作用.
clearly shows that the DateTime-constructor without a second DateTimeZone-argument implicitly uses the system time zone (I don't like such implicits equal in Joda or in java.util.*). If the whole conversion forth and back from and to UTC-DateTime-objects does not work then I assume your input of DateTime-objects is maybe not really in UTC. I recommend to check this explicitly. Otherwise we have not enough informations about why your conversion code does not work.
这篇关于如何使用EclipseLink和Joda-Time将UTC中的日期时间存储到数据库中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!