6

UTC ゾーンの日付/時刻を (DATETIME 型の列の) MySQL データベースに格納する必要があります。ユーザーが日付を入力すると、最初にorg.joda.time.DateTimeJSF コンバーターによって変換されます。

この日付を MySQL データベースに挿入する前に、再度変換する必要がありますjava.util.Date- EclipseLink のおかげです。

以下は、実際にこのコンバーターを見る必要はありませんが、再度変換org.joda.time.DateTimeするコンバーターです。java.util.Date

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たものは、JSF コンバーターで Joda-Time によって変換された正しい UTC 日付/時刻です。

たとえば、日付を入力した場合 -02-Oct-2013 11:34:26 AMの値はobjectValue- になります2013-10-02T06:04:26.000Z。この日付/時刻をデータベースに挿入する必要があります。

しかし、この値がこの式 - によって変換されると(DateTime) objectValue).withZone(DateTimeZone.UTC).toDate()、再度評価され2013-10-02 11:34:26.0、この値がデータベースに提供されますが、これは正しくありません。

とにかく、UTC ゾーンを に設定する方法は(DateTime) objectValue).withZone(DateTimeZone.UTC).toDate()?


タイプのプロパティはorg.joda.time.DateTime、モデル クラスで次のように指定されます。

@Column(name = "discount_start_date", columnDefinition = "DATETIME")
@Converter(name = "dateTimeConverter", converterClass = JodaDateTimeConverter.class)
@Convert("dateTimeConverter")
private DateTime discountStartDate;

編集: (次の JSF コンバーターは、上記の EclipseLink コンバーターと一緒に期待どおりに動作します。これは、BalusC による唯一の回答から現在までそのままです)

これは私の JSF コンバーターです。

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;
    }
}
4

1 に答える 1

4

DateTime#toDate()への変換中にタイムゾーンを使用しないため、具体的な問題が発生しjava.util.Dateます。これは基本的にnew Date(millis)javadocで記述され、コンストラクターで必要とされるように、インスタンスmillisの内部に保存されたエポック時間を返します。DateTimeDateTimejava.util.Date

つまり、withZone(DateTimeZone.UTC)ここではパーツはまったく影響を与えません。コードは、その部分が存在しない場合とまったく同じように動作します。これは、最初に入力した時間で終わる理由を説明しています。

String技術的には、問題は からに変換するカスタム JSF コンバータにありますDateTime。そのコンバーターは明らかにタイムゾーンを考慮しておらず、入力が既に GMT タイムゾーンにあると想定しています (デフォルトのように)。入力が IST タイムゾーンであることをコンバーターに指示する必要があります。java.util.Date標準 JSFで標準プロパティを使用していた場合、その属性を に<f:convertDateTime>設定することで解決できたはずです。timeZoneIST

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

カスタム JSF コンバーターは、内部でまったく同じことを行う必要があります。提供されStringたものが既に GMT タイムゾーンにあると想定するのではなく、IST タイムゾーンにあることを API に伝えます。カスタム JSF コンバーターをどこにも示していないため、正確な答えを提供することは困難ですが、次のキックオフ例に要約する必要があります。

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インスタンスは、正しい内部エポック時間をミリ秒単位で持つことになります。

于 2013-10-23T12:14:15.470 に答える