2017-04-13 3 views
0

Ich habe zwei Datumsobjekte, Date1 und Date2. Date1 hat eine Zeit und Date2 hat eine Zeit, mit einem Offset zu UTC (nur innerhalb der Zeit, nicht das tatsächliche Datum selbst):Vergleichen der Zeitverschiebung Verwenden von zwei Date-Objekten

Date1: Thu Apr 13 20:41:46 CDT 2017

Date2: Thu Apr 13 15:41:46 CDT 2017

Ich möchte diese beiden Daten nehmen , extrahiere ihre Zeiten, vergleiche sie und stelle dann sicher, dass sie korrekt von meiner Systemzeit und UTC abweichen (dieser Vergleich muss auch die Sommerzeit berücksichtigen).

(Bitte beachten Sie, es gibt keinen Weg, ich kann java.time als Eingabe verwenden. Ich verstehe, es wäre viel einfacher, aber mit unseren Konfigurationen bin ich fest mit java.util.Date als Eingabedatum)

Hier ist mein Code, um diese Datumswerte zu erzeugen, ich brauche nur einen Weg zu überprüfen, dass der Unterschied zwischen den beiden der richtige Offset ist (ohne den Offset zu ändern und ihn bei jeder Änderung der Sommerzeit zu ändern):

public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS"; 
public static final int MILLI_TO_HOUR = 1000 * 60 * 60; 

public static void main(String args[]) throws java.text.ParseException { 
    Date date1 = nowInUTC(); 
    Date date2 = Date.from(Instant.now()); 
    System.out.println("date1: " + date1); 
    System.out.println("date2: " + date2); 

    /* Needs to be modified to contain the logic 
     * I need to verify that the time given in date2 is the offset from date1 
     * in respect to its timezone. You can ignore the CDT in date1*/ 
    if(true){ 
     System.out.println("You have the correct offset!"); 
    } 
    else 
    { 
     System.out.println("you do not have the correct offset!"); 
    } 
} 

private static long toHours(long millis){ 
    return millis/MILLI_TO_HOUR; 
} 

private static Date nowInUTC() { 
    try { 
     Date date = new Date(new SimpleDateFormat(TIMESTAMP_FORMAT).parse(
       nowInUTCAsString()).getTime()); 
     return date; 
    } 
    catch(ParseException pe){ 
     pe.printStackTrace(); 
     return null; 
    } 
} 

private static String nowInUTCAsString() { 
    SimpleDateFormat sdf = new SimpleDateFormat(TIMESTAMP_FORMAT); 
    sdf.setTimeZone(TimeZone.getTimeZone("UTC")); 
    return sdf.format(new Date()); 
} 
+0

Was Sie fragen, macht keinen Sinn (was Ihnen vielleicht helfen kann). Ein 'Date'-Objekt * hat keinen Offset zu UTC *. Es ist ein häufiges Missverständnis, wahrscheinlich sehr geholfen durch die Tatsache, dass seine "toString" -Methode die Zeitzoneneinstellung der JVM aufnimmt und das Datum entsprechend ausdruckt. Wenn also zwei "Date" -Objekte in Ihrem Programm vorhanden sind, kann keiner davon einen Offset enthalten, und beide werden mit demselben Offset gedruckt, nämlich dem der JVM. –

+0

Ich bemerke, dass Sie 'Instant.now()' verwenden, wobei 'Instant' eine Klasse von' java.time' ist (nehme ich an). Wollen Sie sagen, dass Ihre Eingabe notwendigerweise eine 'java.util.Date' ist, damit Sie sie in eine' java.time' Klasse konvertieren und Ihre Verarbeitung mit den neuen Klassen durchführen können? Wenn ja, würde ich das empfehlen. –

+0

Ihre 'nowInUTC()' tut etwas, was ich nicht glauben kann, dass Sie wollen. Central Daylight Time ist -5 Stunden von UTC versetzt. Also, wenn Sie Ihren Code um 15:41:46 CDT ausgeführt haben, war die UTC-Zeit 20:41:46, und 'nowInUTCAsString()' erzeugte korrekt eine Zeichenfolge wie '2017-04-13T20: 41: 46.357' (nur raten bei der Dezimalstellen). Dann analysiert 'nowInUTC()' diese Zeichenkette in * Ihrer lokalen Zeitzone * und erzeugt ein 'Datum' gleich 20:41:46 CDT, das ist das gleiche wie 1:41:46 in der Nacht UTC. Da das Datum immer in der JVM-Zeitzone gedruckt wird, sehen Sie es auf Ihrem Bildschirm als "Do Apr 13 20:41:46 CDT 2017". –

Antwort

1

Danke für Ihren Kommentar mit Klarstellung für Ihre interessante Herausforderung nge. Ich verstehe, dass Sie ein Datum erzeugen müssen, das 5 Stunden vor der Zeit ist, um die Datenbank zu kompensieren, indem Sie die CDT-Zeit nehmen und sie als UTC verstehen. Tatsächlicher Offset abhängig von der Zeitzoneneinstellung Ihres Computers. Ich gehe davon aus, dass Ihre Datenbank lokal ausgeführt wird oder zumindest die gleiche Zeitzoneneinstellung wie Ihre JVM aufweist - eine Annahme, die Sie überprüfen sollten.

Ihr Code ist grundsätzlich korrekt, wenn zwei Daten mit einem Unterschied erzeugt werden, der dem Offset Ihres Computers von UTC entspricht. Sie sollten also nicht wirklich eine Bestätigung dieser Tatsache benötigen. Ich werde dieser Aussage eine oder zwei Nuancen hinzufügen.

Zuerst, wie verifizieren Sie? Nehmen Sie Ihr Wort, das Sie wollen. Hier ist mein Vorschlag:

LocalDateTime date1AsLdt = date1.toInstant() 
      .atZone(ZoneId.systemDefault()) 
      .toLocalDateTime(); 
    LocalDateTime utc = OffsetDateTime.now(ZoneOffset.UTC).toLocalDateTime(); 
    if (date1AsLdt.isEqual(utc)){ 
     System.out.println("You have the correct offset!"); 
    } 
    else 
    { 
     System.out.println("you do not have the correct offset!"); 
    } 

Auch wenn ich behaupten, dass dies eine richtige Art und Weise der Überprüfung ist, wie die richtige Weg date1 produzieren, auf meinem alten Computer druckt es you do not have the correct offset! Dies liegt daran, dass die beiden Zeiten unterscheiden sich um bis zu ein einige hundert Millisekunden. Es ist kein Fehler, es ist eine Ungenauigkeit in Ihrem Code. Es kommt von Ihrem Code, der die Systemuhr zweimal liest, und abhängig von der Zeit, die zwischen den zwei Lesungen verstreicht, können sie übereinstimmen oder nicht. Sie lesen zuerst die Uhr, indem Sie new Date() erstellen, dann erneut unter Instant.now(). Ich empfehle Ihnen, die Uhr nur einmal zu lesen und für beide Daten den gleichen Wert zu verwenden.

Da Sie in Ihrem Code java.time.Instant verwendet haben, habe ich davon ausgegangen, dass Sie java.time intern verwenden können, solange Sie eine java.util.Date produzieren. LocalDateTime in meinem obigen Code ist in java.time auch.

Wenn dies in Ordnung ist, besteht in Ihrem Code keine Notwendigkeit für die Konvertierung in String und zurück. Ich schlage vor:

private static Date nowInUTC() { 
    LocalDateTime utc = OffsetDateTime.now(ZoneOffset.UTC).toLocalDateTime(); 
    return Date.from(utc.atZone(ZoneId.systemDefault()).toInstant()); 
} 

Wie gesagt, es gibt eine Reihe von Annahmen in den oben genannten. Wenn ich irgendwo falsch liege, bitte zurück, und ich werde mich freuen, noch einen Blick darauf zu werfen.

Eine letzte Warnung. Es gibt ein paar Stunden um den Wechsel von DST zu Standardzeit jeden Herbst, wo Uhrzeiten mehrdeutig sind.Selbst wenn Ihr Programm die UTC-Zeit richtig produziert (was niedeutig ist als UTC), muss Ihre Datenbank eine Interpretation der Zeit wählen, die an sie übergeben wurde, und ich kann nicht sehen, dass sie eine Möglichkeit hat, die richtige auszuwählen.