2012-11-06 3 views
8

Ich versuche tatsächlich, Objekte mit Datumsangaben mit Avro zu serialisieren, und das deserialisierte Datum stimmt nicht mit dem erwarteten Wert überein (getestet mit avro 1.7.2 und 1.7.1). Hier ist die Klasse ich Serialisierung:Wie man ein Datum mit AVRO in Java serialisiert

import java.text.SimpleDateFormat; 
import java.util.Date; 

public class Dummy { 
    private Date date; 
    private SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS"); 

    public Dummy() { 
    } 

    public void setDate(Date date) { 
     this.date = date; 
    } 

    public Date getDate() { 
     return date; 
    } 

    @Override 
    public String toString() { 
     return df.format(date); 
    } 
} 

Der verwendete Code zur Serialisierung/Deserialisierung:

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.util.Date; 

import org.apache.avro.Schema; 
import org.apache.avro.io.DatumReader; 
import org.apache.avro.io.DatumWriter; 
import org.apache.avro.io.Decoder; 
import org.apache.avro.io.DecoderFactory; 
import org.apache.avro.io.Encoder; 
import org.apache.avro.io.EncoderFactory; 
import org.apache.avro.reflect.ReflectData; 
import org.apache.avro.reflect.ReflectDatumReader; 
import org.apache.avro.reflect.ReflectDatumWriter; 

public class AvroSerialization { 

    public static void main(String[] args) { 
     Dummy expected = new Dummy(); 
     expected.setDate(new Date()); 
     System.out.println("EXPECTED: " + expected); 
     Schema schema = ReflectData.get().getSchema(Dummy.class); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     Encoder encoder = EncoderFactory.get().binaryEncoder(baos, null); 
     DatumWriter<Dummy> writer = new ReflectDatumWriter<Dummy>(schema); 
     try { 
      writer.write(expected, encoder); 
      encoder.flush(); 
      Decoder decoder = DecoderFactory.get().binaryDecoder(baos.toByteArray(), null); 
      DatumReader<Dummy> reader = new ReflectDatumReader<Dummy>(schema); 
      Dummy actual = reader.read(null, decoder); 
      System.out.println("ACTUAL: " + actual); 
     } catch (IOException e) { 
      System.err.println("IOException: " + e.getMessage()); 
     } 
    } 
} 

Und die Ausgabe:

EXPECTED: 06/11/2012 05:43:29.188 
ACTUAL: 06/11/2012 05:43:29.387 

es bezieht sich auf einen bekannten Fehler, oder hängt es mit der Art zusammen, in der ich das Objekt serialisiere?

+1

Ich weiß, dass ich Ihre Frage nicht beantworte, aber ich * würde * kein statisches SimpleDateFormat verwenden. Es ist keine threadsichere Klasse und liefert daher unzuverlässige Ergebnisse in einer Umgebung mit Threads –

+0

Vielen Dank für den Kommentar, das ist eigentlich kein Produktionscode, sondern nur eine Testklasse, die ich entwickelt habe, um mein Problem aufzudecken. Wie auch immer, du hast Recht, also habe ich den statischen Modifikator entfernt;) –

Antwort

6

Ich denke, AVRO Serialisierung Datum zu diesem Zeitpunkt nicht. Was ich tun würde ist es in eine andere Klasse zu wickeln und zu speichern, als eine lange (date.gettime()) während avro Völker hinzufügen this feature. Und der Grund, dass Sie unterschiedliche Datumswerte sehen, ist, dass jedes Mal, wenn Sie (und avro) ein Date-Objekt erstellen, es das Datum mit der aktuellen Systemzeit initialisiert.

+0

Danke amas, es sieht aus wie Datum wird eigentlich nicht unterstützt wie in deiner Antwort angegeben, und das Datum ist tatsächlich mit der aktuellen Systemzeit initialisiert. –

7

Avro 1.8 hat jetzt ein Datum "logicalType", das int kennzeichnet. Zum Beispiel:

{ "name": "Datum", "type": "int", "logicalType": "Datum"}

die Spezifikation Zitiert: „Ein Datum logische Art, die einen Avro int annotiert, wobei der Int die Anzahl der Tage ab der Unix-Epoche, 1. Januar 1970 (ISO-Kalender) speichert. "