如何使用Joda-Time通过EclipseLink将UTC区域中的日期/时间插入MySQL? [英] How to insert date/time in the UTC zone into MySQL via EclipseLink using Joda-Time?

查看:145
本文介绍了如何使用Joda-Time通过EclipseLink将UTC区域中的日期/时间插入MySQL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将UTC区域中的日期/时间存储到MySQL数据库中(DATETIME类型列).用户输入日期时,JSF转换器首先将其转换为org.joda.time.DateTime.

I need to store date/time in UTC zone into MySQL database (of a DATETIME type column). When a user enters a date, it is first converted to org.joda.time.DateTime by a JSF converter.

在将此日期插入MySQL数据库之前,再次需要将其转换为java.util.Date-感谢EclipseLink.

Before inserting this date into MySQL database, it again needs to be converted to java.util.Date - thanks to EclipseLink.

以下是再次将org.joda.time.DateTime转换为java.util.Date的转换器,尽管实际上并不需要看到它.

The following is the converter that again converters org.joda.time.DateTime to java.util.Date though it is not really needed to see this converter.

package joda.converter;

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;
import org.joda.time.DateTimeZone;

public final class JodaDateTimeConverter implements Converter
{
    private static final long serialVersionUID = 1L;

    @Override
    public Object convertObjectValueToDataValue(Object objectValue, Session session)
    {
        return objectValue instanceof DateTime?((DateTime) objectValue).withZone(DateTimeZone.UTC).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的值是由Joda-Time在JSF转换器中转换的正确UTC日期/时间.

In the convertObjectValueToDataValue() method (the first one), the value of the first parameter - objectValue received is the correct UTC date/time converted by Joda-Time in a JSF converter.

例如,如果我输入一个日期-02-Oct-2013 11:34:26 AM,那么objectValue的值将是-2013-10-02T06:04:26.000Z.此日期/时间应插入数据库中.

For example, if I entered a date - 02-Oct-2013 11:34:26 AM then, the value of objectValue would be - 2013-10-02T06:04:26.000Z. This date/time should be inserted into the database.

但是,当此值由表达式-(DateTime) objectValue).withZone(DateTimeZone.UTC).toDate()转换时,它再次被评估为2013-10-02 11:34:26.0并将该值提供给数据库,这是不正确的.

But when this value is converted by this expression - (DateTime) objectValue).withZone(DateTimeZone.UTC).toDate(), it is again evaluated to 2013-10-02 11:34:26.0 and this value is supplied to the database which is incorrect.

无论如何,如何将UTC区域设置为(DateTime) objectValue).withZone(DateTimeZone.UTC).toDate()?

Anyway, how to set the UTC zone to (DateTime) objectValue).withZone(DateTimeZone.UTC).toDate()?

在模型类中指定类型为org.joda.time.DateTime的属性,如下所示.

A property of type org.joda.time.DateTime 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;


(以下JSF转换器与预期的EclipseLink转换器一起正常工作,该EclipseLink转换器保持不变-来自唯一的


(The following JSF converter works as expected along with the EclipseLink converter above which remains intact - from the only answer until now by BalusC)

这是我的JSF转换器.

This is my JSF converter.

package converter;

import java.util.TimeZone;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import util.Utility;

@ManagedBean
@RequestScoped
public final class DateTimeConverter implements Converter
{
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value)
    {
        DateTime dateTime=null;

        try
        {
            dateTime = DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa").withZone(DateTimeZone.forTimeZone(TimeZone.getTimeZone("IST"))).parseDateTime(value);
        }
        catch (IllegalArgumentException e)
        {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "", Utility.getMessage("datetime.converter.error", DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa").print(DateTime.now().withZone(DateTimeZone.forID("Asia/Kolkata"))))), e);
        }
        catch(UnsupportedOperationException e)
        {
            throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "", Utility.getMessage("datetime.converter.error", DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa").print(DateTime.now().withZone(DateTimeZone.forID("Asia/Kolkata"))))), e);
        }
        return dateTime;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value)
    {
        DateTimeFormatter dateTimeFormatter=DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa").withZone(DateTimeZone.forID("Asia/Kolkata")); //This zone will be tackled/handled later from the database to display.              
        return value instanceof DateTime?dateTimeFormatter.print((DateTime)value):null;
    }
}

推荐答案

您的具体问题是由于

Your concrete problem is caused because DateTime#toDate() doesn't use the time zone during the conversion to java.util.Date. It basically returns new Date(millis) wherein the millis is the internally stored epoch time of DateTime instance, exactly as described by DateTime javadoc and required by the java.util.Date constructor.

换句话说,withZone(DateTimeZone.UTC)部分在这里完全无效.该代码的行为与缺少该部分的行为完全相同.这就解释了为什么您会得到最初输入的时间.

In other words, the withZone(DateTimeZone.UTC) part has totally no effect here. The code behaves exactly the same as if that part was absent. That explains why you end up with the originally entered time.

从技术上讲,问题出在您的自定义JSF转换器中,该转换器将String转换为DateTime.该转换器显然没有考虑时区,并假设输入已经在GMT时区中(默认情况下).必须指示转换器输入为IST时区.如果您将标准java.util.Date属性与标准JSF <f:convertDateTime>一起使用,则可以通过将其timeZone属性设置为IST来解决该问题.

Technically, the problem is in your custom JSF converter which converts from String to DateTime. That converter is apparently not taking the time zone into account and assuming that the input is already in GMT timezone (as by default). The converter must be instructed that the input is in IST timezone. If you were using standard java.util.Date property with standard JSF <f:convertDateTime>, then you could have solved it by setting its timeZone attribute to IST.

<h:inputText value="#{bean.date}">
    <f:convertDateTime pattern="dd-MMM-yyyy hh:mm:ss a" locale="en" timeZone="IST" />
</h:inputText>

您的自定义JSF转换器在幕后应该做的完全一样:告诉API所提供的String在IST时区中,而不是假设它已经在GMT时区中.您没有在任何地方显示自定义JSF转换器,因此很难提供确切的答案,但是应该归结为以下启动示例:

Your custom JSF converter should under the covers be doing exactly the same: tell the API that the supplied String is in IST timezone instead of letting it assume that it's already in GMT timezone. You didn't show the custom JSF converter anywhere, so it's hard to supply the exact answer, but it should boil down to the following kickoff example:

String inputDateString = "02-Oct-2013 11:34:26 AM";
String inputDatePattern = "dd-MMM-yyyy hh:mm:ss a";
TimeZone inputTimeZone = TimeZone.getTimeZone("IST");

DateTime dateTime = DateTimeFormat
    .forPattern(inputDatePattern)
    .withZone(DateTimeZone.forTimeZone(inputTimeZone))
    .parseDateTime(inputDateString);

生成的DateTime实例最终将具有正确的内部纪元时间(以毫秒为单位).

The resulting DateTime instance will end up having the right internal epoch time in millis.

这篇关于如何使用Joda-Time通过EclipseLink将UTC区域中的日期/时间插入MySQL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆