2013-10-14 13 views
5

Ho bisogno di memorizzare data/ora nella zona UTC nel database MySQL (di una colonna di tipo DATETIME). Quando un utente immette una data, viene prima convertito in org.joda.time.DateTime da un convertitore JSF.Come inserire data/ora nella zona UTC in MySQL tramite EclipseLink usando Joda-Time?

Prima di inserire questa data nel database MySQL, deve essere nuovamente convertita in java.util.Date - grazie a EclipseLink.

Quanto segue è il convertitore che convertitori di nuovo da org.joda.time.DateTime a java.util.Date sebbene non sia realmente necessario per vedere questo convertitore.

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

Nel metodo convertObjectValueToDataValue() (il primo), il valore del primo parametro - objectValue ricevuto è la corretta UTC data/ora convertito da Joda-Time in un convertitore JSF.

Ad esempio, se si immette una data - 02-Oct-2013 11:34:26 AM, il valore di objectValue sarà - 2013-10-02T06:04:26.000Z. Questa data/ora dovrebbe essere inserita nel database.

Ma quando questo valore viene convertito da questa espressione - (DateTime) objectValue).withZone(DateTimeZone.UTC).toDate(), viene nuovamente valutata a 2013-10-02 11:34:26.0 e questo valore viene fornito al database che non è corretto.

In ogni caso, come impostare la zona UTC su (DateTime) objectValue).withZone(DateTimeZone.UTC).toDate()?


Una proprietà di tipo org.joda.time.DateTime è designata in una classe modello come segue.

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

EDIT:(Il seguente convertitore JSF funziona come previsto con il convertitore EclipseLink di sopra del quale rimane intatta - dall'unico answer fino ad ora da BalusC)

Questo è il mio Convertitore 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; 
    } 
} 
+0

UTF? forse UTC, il timestamp è di solito già in UTC, quindi il problema è solo durante la conversione da millis a string, per questo controllo http://stackoverflow.com/questions/7670355/convert-date-time-for-given-timezone-java , inoltre, controlla l'impostazione corretta del fuso orario del database –

+0

Scusa è UTC - digitazione insonnia. – Tiny

+0

Non riesco a restituire un oggetto 'Calendar'. Dovrebbe restituire 'java.sql.Timestamp', quando i dati vengono forniti al database. Ecco come funzionano i mapping JPA. – Tiny

risposta

3

vostro problema concreto è causato perché DateTime#toDate() non usa il fuso orario durante la conversione a java.util.Date. In pratica, restituisce new Date(millis) in cui lo millis è l'ora di archiviazione interna dell'istanza DateTime, esattamente come descritto da DateTime javadoc e richiesto dallo java.util.Date constructor.

In altre parole, la parte withZone(DateTimeZone.UTC) non ha alcun effetto qui. Il codice si comporta esattamente come se quella parte fosse assente. Questo spiega perché si finisce con il tempo inserito originariamente.

Tecnicamente, il problema è nel convertitore JSF personalizzato che converte da String a DateTime. A quanto pare, il convertitore non tiene conto del fuso orario e presuppone che l'input sia già nel fuso orario GMT (come predefinito). Il convertitore deve essere informato che l'ingresso è nel fuso orario IST. Se si stesse utilizzando la proprietà standard java.util.Date con JSF standard <f:convertDateTime>, è possibile risolverlo impostando l'attributo timeZone su IST.

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

vostro convertitore JSF personalizzato dovrebbe essere sotto le coperte facendo esattamente la stessa: dire l'API che la dotazione String è nel fuso orario TSI invece di lasciare che si supponga che è già nel fuso orario GMT. Non hai mostrare il convertitore JSF personalizzato da nessuna parte, quindi è difficile per fornire la risposta esatta, ma dovrebbe ridursi al seguente esempio calcio d'inizio:

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); 

La risultante DateTime esempio finirà per avere il diritto dell'epoca interna tempo in millis.

+0

Ho [questo] (http://pastebin.com/xjJtnh8m) convertitore JSF ma sfortunatamente, questo non ha fatto la differenza. Grazie – Tiny

+0

Modificato la domanda per includere il convertitore JSF. – Tiny

+0

Quindi non stai eseguendo il nuovo convertitore o stai interpretando male i risultati o il problema si è spostato altrove, non visibile nelle informazioni fornite finora. Il nuovo convertitore dovrebbe correggere in particolare la parte * "Ma quando questo valore viene convertito da questa espressione (DateTime) objectValue) .withZone (DateTimeZone.UTC) .toDate(), viene nuovamente valutata per 2013-10-02 11:34 : 26.0" *. – BalusC

Problemi correlati