Frage

Ich arbeite mit Webservices und füge Datensätze ein, die einen Zeitstempelwert im Typ XMLGregorianCalendar zurückgeben.Ich muss es in einen java.sql.Timestamp-Wert umwandeln, also verwende ich eine Funktion wie diese.

public static java.sql.Timestamp getSqlTimeStamp(XMLGregorianCalendar xgc) {
    if (xgc == null) {
        return null;
    } else {
        return new Timestamp(xgc.toGregorianCalendar().getTime().getTime());
    }
}
Timestamp timestamp=getSqlTimeStamp(ExitInXMLGregor.getTimestamp());

Mein Problem ist, dass auf dem Server der Zeitstempelwert beim Einfügen eines Datensatzes so aussieht:10/03/2012 19:23:22

Aber wenn ich meine Typkonvertierung durchführe, erhalte ich den Zeitstempelwert wie folgt:10/03/2012 17:23:22

Die Zeit auf dem Server (auf dem sich der Webservice befindet) ist 2 Stunden länger als mein Gebietsschema, und aus irgendeinem Grund erhalte ich meine Einfügungszeit für das Gebietsschema, nachdem ich es transformiert habe.Das Problem besteht darin, dass ich unbedingt die Serverzeit ermitteln muss, da in der Datenbank der Zeitstempelwert mit dem des Servers übereinstimmt und ich aufgrund der unterschiedlichen Zeitstempelwerte Probleme beim Aktualisierungsvorgang habe.

Bitte, ich würde mich über jede Art von Hilfe freuen.Danke!

Bearbeiten:Ich finde irgendwie eine Lösung, aber sie ist nicht genau das, was ich brauche.Wenn ich meinen Zeitstempel im java.sql.Timestamp-Format in XMLGregorian konvertiere, stelle ich die Zeitzone des Servers ein (setTimeZone(TimeZone.getTimeZone("GMT+02:00"))).Das funktioniert tatsächlich, ist aber weit von der Ideallösung entfernt (Es könnte passieren, dass sich die Zeitzone oder sogar der Server ändert). Es wäre toll, an dieser Stelle die Zeitzone des Servers dynamisch zu kennen, aber ich weiß nicht wie. .

public static XMLGregorianCalendar getXMLGregorianCalendar(Timestamp timestamp)
        throws BaseException {
    try {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTimeZone(TimeZone.getTimeZone("GMT+02:00"));
        gc.setTimeInMillis(timestamp.getTime());
        return DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
    } catch (DatatypeConfigurationException ex) {
        throw new BaseException(ex);
    }
}
War es hilfreich?

Lösung

Ich vermute, dass der Zeitstempel den richtigen Zeitpunkt anzieht, wird einfach nicht mit der richtigen Zeitzone angezeigt. 2012-10-03t17: 23: 22.342 ist das gleiche wie 2012-10-03t19: 23: 22.342 + 02: 00, vorausgesetzt, dass die (versteckte) Zeitzone des ersteren +00: 00 angenommen wird.

Andere Tipps

tl;dr

  • Beide Zeichenfolgen stellen denselben Moment dar, einfach an eine Zeitzone angepasst, ohne dies zu beachten Offset von UTC.
  • Vermeiden Sie solche Verwirrung, indem Sie in solchen Zeichenfolgen immer die Offset- und Zoneninformationen angeben.
  • Verwenden Sie modern java.time Klassen, die die problematischen Legacy-Klassen ersetzen.(Instant, nicht Timestamp)

Beispielcode.

myPreparedStatement.setObject( 
    … , 
    myXMLGregorianCalendar  // If forced to work with a `javax.xml.datatype.XMLGregorianCalendar` object rather than a modern java.time class…
    .toGregorianCalendar()  // …convert to a `java.util.GregorianCalendar`, and then…
    .toZonedDateTime()      // …convert to modern `java.time.ZonedDateTime` class.
    .toInstant()            // Adjust to UTC by extracting an `Instant` object.
)

Abrufen aus einer Datenbank, ab JDBC 4.2 und höher.

Instant instant = myResultSet.getObject( … , Instant.class ) ;

java.time

Als die richtig akzeptierte Antwort von Robert Tupelo-Schneck sagt, es scheint alles in Ordnung zu sein, da beide Zeichenfolgen denselben Moment darstellen, aber an eine andere Zeitzone mit einem anderen Offset von UTC angepasst sind.Das Problem besteht darin, dass einer dieser beiden Zeichenfolgen ein Indikator für den Offset von UTC fehlt.

Eine solche Unterlassung ist eine schlechte Praxis, da sie zu dieser Verwirrung führt.Geben Sie immer den Offset von UTC an, es sei denn, es ist absolut sicher, dass der Kontext den Offset/die Zone klar macht.

Arbeiten Sie in UTC

Das Arbeiten in UTC vermeidet diese Art von Verwirrung.Im Allgemeinen ist es am besten, Datums-/Uhrzeitwerte in UTC zu bearbeiten, zu speichern und auszutauschen.Passen Sie UTC nur zur Präsentation an den Benutzer oder wenn die Geschäftslogik dies erfordert, an eine Zeitzone an.

Außerdem verwenden Sie schrecklich problematische alte Klassen, die jetzt durch ersetzt werden java.time Klassen.Konvertieren Sie Ihre XMLGregorianCalendar Zu java.time.ZonedDateTime.

ZonedDateTime zdt = myXMLGregorianCalendar.toGregorianCalendar().toZonedDateTime() ;

Passen Sie es an UTC an, indem Sie eine extrahieren Instant Objekt.

Instant instant = zdt.toInstant() ;

Ab JDBC 4.2 und höher können Sie direkt austauschen java.time Objekte mit der Datenbank.Es besteht keine Notwendigkeit, das Erbe jemals zu verwenden java.sql.Timestamp wieder Klasse.

myPreparedStatement.setObject( … , instant ) ;

Abruf:

Instant instant = myResultSet.getObject( … , Instant.class ) ;

Stellen Sie UTC auf eine bestimmte Zeitzone um, wenn Sie denselben Moment mit der von den Menschen in einer bestimmten Region verwendeten Wanduhrzeit sehen möchten.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Konvertieren

Wenn Sie eine Schnittstelle zu einem alten Code benötigen, der eine erfordert java.sql.Timestamp, können Sie mit hin und her konvertieren java.time.Instant.Rufen Sie neue Konvertierungsmethoden auf, die den alten Klassen hinzugefügt wurden.

java.sql.Timestamp ts = java.sql.Timestamp.from( instant ) ;

In die andere Richtung gehen.

Instant instant = ts.toInstant() ;

Siehe auch meine Antwort zu einer ähnlichen Frage.


Um java.time

Der java.time Das Framework ist in Java 8 und höher integriert.Diese Kurse ersetzen die lästigen alten Vermächtnis Datum-Uhrzeit-Klassen wie java.util.Date, Calendar, & SimpleDateFormat.

Der Joda-Zeit Projekt, jetzt in Wartungsmodus, rät zur Migration in die java.time Klassen.

Weitere Informationen finden Sie unter Oracle-Tutorial.Und durchsuchen Sie Stack Overflow nach vielen Beispielen und Erklärungen.Spezifikation ist JSR 310.

Sie können umtauschen java.time Objekte direkt mit Ihrer Datenbank.Benutze einen JDBC-Treiber gemäß JDBC 4.2 oder später.Keine Notwendigkeit für Saiten, keine Notwendigkeit java.sql.* Klassen.

Wo erhält man die java.time-Klassen?

Der ThreeTen-Extra Das Projekt erweitert java.time um zusätzliche Klassen.Dieses Projekt ist ein Testgelände für mögliche zukünftige Ergänzungen zu java.time.Möglicherweise finden Sie hier einige nützliche Klassen, z Interval, YearWeek, YearQuarter, Und mehr.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top