2016-05-05 20 views
1

Folgendes ist der Code, den ich verwendet habe, um die 00 Stunde des aktuellen Tages (im langen Format) zu erhalten.SimpleDateFormat verhält sich seltsam in Android

Ich führe den folgenden Code in Android.

Die Methode gibt den Wert die meiste Zeit korrekt zurück. Aber ab und zu gibt es den Wert System.currentTimeMillis() zurück.

import java.text.SimpleDateFormat; 
import java.util.Date; 
public static final SimpleDateFormat SD_FORMAT_DAY_MONTH_YEAR = new SimpleDateFormat("dd/MM/yyyy"); 


public static long getLongForCurrent00hr() { 
    Date date = new Date(); 
    String time = SD_FORMAT_DAY_MONTH_YEAR.format(date); 

    long value; 
    try { 
     Date date2 = SD_FORMAT_DAY_MONTH_YEAR .parse(time); 
     value = date2.getTime(); 
    } catch (ParseException e) { 
     value = 0; 
    } 
    return value; 
} 

Warum ist die System.currentTimeMillis Rückkehr()? Wie kann ich das Problem lösen?

Ich bin mehr daran interessiert zu wissen, warum ..

Als ich diesen Code heute wurde ruuning, ich es, indem sie Protokolle geprüft:

Die meiste Zeit kehrt: 1462386600000

Und nur wenige mal System.currentTimeMillis() wie 1462430867302.

+3

Ihr gesendeter Code definiert 'pFormat' oder' pDateString' nicht. –

+0

@ MikeM.fixed, überprüfen Sie die Bearbeitung – OnePunchMan

+1

Kann nicht reproduzieren ... – assylias

Antwort

0

Ihr Beispielcode funktioniert

Ich sehe kein Problem mit Ihrem Code, wie Sie es einrahmen (siehe unten für Kritik).

Fast Ihr genauer Code wird hier gezeigt. Zwei Änderungen:

  • Ich machte Ihr Format konstant eine lokale Variable. (einfach, um diese Demo einfacher zu machen, ein Block von Code, der kopiert werden kann)
  • Ich habe ein paar Anrufe hinzugefügt, um eine Instant, den aktuellen Moment in UTC zu bekommen. Ähnlich wie java.util.Date, aber Instant::toString erstellt eine Zeichenfolge, die UTC anzeigt, anstatt die aktuelle Zeitzone der JVM verwirrend anzuwenden. So können Sie klarer sehen, dass Sie tatsächlich den ersten Moment des Tages der aktuellen Standardzeitzone Ihres JVM erhalten. In meinem Fall, wenn dieser Code ausgeführt wird, ist die aktuelle Standardzeitzone meines JVM , derzeit in Sommerzeit (DST) für offset-from-UTC für -07:00 (sieben Stunden hinter UTC).

Beispielcode.

Date date1 = new Date(); 
SimpleDateFormat SD_FORMAT_DAY_MONTH_YEAR = new SimpleDateFormat ("dd/MM/yyyy"); 
String time = SD_FORMAT_DAY_MONTH_YEAR.format (date1); 

Date date2 = null; 
long value; 
try { 
    date2 = SD_FORMAT_DAY_MONTH_YEAR.parse (time); 
    value = date2.getTime(); 
} catch (ParseException e) { 
    value = 0; 
} 
System.out.println ("date1: " + date1 + " date2: " + date2 + " value: " + value + " | instant 1: " + date1.toInstant() + " | instant 2: " + date2.toInstant()); 

Wenn ausgeführt.

datum1: Do May 05 16:55:40 PDT 2016 date2: Do May 05 00:00:00 PDT 2016 value: 1462431600000 | Instant 1: 2016-05-05T23: 55: 40.907Z | Instant 2: 2016-05-05T07: 00: 00Z

zu hart

Ihre Frage zu arbeiten, ist verwirrend, aber es scheint, dass Sie den ersten Moment des Tages zu erfassen versuchen. Sie gehen falsch herum und arbeiten zu hart.

Zeitzone

Der Code wird mit der java.util.Date Klasse zu arbeiten.Diese Klasse repräsentiert einen Moment auf der Zeitachse in UTC.

Aber Sie erhalten nicht den ersten Moment des Tages in UTC. Wenn Sie diese reine Datumszeichenfolge analysieren, um einen neuen java.util.Date (ein Datum plus Uhrzeitwert trotz des irreführenden Namens) zu generieren, wird die aktuelle Standardzeitzone Ihres JVM implizit angewendet. Sehr verwirrend Zeitzonen unsichtbar in den Prozess zu injizieren.

Stattdessen sollten Sie bewusst Zeitzonen berücksichtigen, und immer die Zeitzone explizite ist Ihre Codierung (siehe unten).

java.time

Die alten java.util.Date/.Calendar Klassen unter Beweis gestellt haben schlecht konzipiert werden, verwirrend und lästig. Sie sind nun veraltet und werden durch das in Java 8 und höher integrierte Framework java.time ersetzt. Ein großer Teil der java.time-Funktionalität ist back-ported to Java 6 & 7 und further adapted for Android.

Verwenden Sie für einen Nur-Datumswert ohne Uhrzeit und ohne Zeitzone LocalDate Klasse. Wenn Sie eine Zeitzone nicht speichern, benötigen Sie für die Festlegung eines Datums wie "Heute" eine Zeitzone. Wenn diese Option nicht angegeben wird, wird die aktuelle Standardzeitzone des JVM angewendet (Vorsicht, dieser Standard kann sich während der Laufzeit jederzeit ändern).

ZoneId zoneId = ZoneId.of("America/Montreal"); 
LocalDate today = LocalDate.now(zoneId); 

Sie scheinen den ersten Moment des Tages wollen. Nehmen Sie nicht an, dass die Uhrzeit 00:00:00.0 ist. In einigen Zeitzonen kann es vorkommen, dass eine Anomalie wie die Sommerzeit in eine andere Zeit wechselt. Lassen Sie java.time die richtige Zeit ermitteln. Der Aufruf von [atStartOfDay][2] erzeugt zum ersten richtigen Zeitpunkt eine ZonedDateTime für die angegebene Zeitzone.

ZonedDateTime zdt = today.atStartOfDay(zoneId); 

Ich empfehle gegen die Verwendung Handhabung Datum Zeitwerte als Count-von- epoch. Das ist so, als würde man ein Array von Ints mit Unicode-Codepunkten verwenden, anstatt die String-bezogenen Klassen für die Textverarbeitung zu verwenden. Aber wenn Sie darauf bestehen, können Sie konvertieren. Aber hüte dich vor Datenverlust, da die java.time-Klassen eine feinere Auflösung von Nanosekunden haben, während du nach Millisekunden fragst (einer von vielen Gründen, die Datums-Zeit nicht als Epochen-Zählung zu behandeln). Zuerst extrahieren Sie einen Instant, einen Moment auf der Timeline in UTC mit einer Auflösung von Nanosekunden.

Instant instant = zdt.toInstant(); 
long millisecondsFromEpoch = instant.toEpochMilli(); // WARNING: Possible data loss (going from nanoseconds to milliseconds). 

UTC

Wenn Sie den ersten Moment des Tages in UTC haben wollen, das zu einfach ist.

Sie könnten UTC als Zeitzone angeben, indem Sie die Konstante ZoneOffset.UTC verwenden. (Das Konstante geschieht in ZoneOffset, eine Unterklasse von ZoneId. Sein)

ZonedDateTime zdt = today.atStartOfDay(ZoneOffset.UTC); 

Aber das ist vielleicht nicht die am besten geeignete Route. Eine Zeitzone ist ein offset-from-UTCplus eine Reihe von Regeln für Anomalien wie Daylight Saving Time (DST). UTC hat per Definition keine solchen Anomalien. So besser geeignet wäre die OffsetDateTime anstatt ZonedDateTime.

OffsetTime ot = OffsetTime.of(0 , 0 , 0 , 0 , ZoneOffset.UTC); 
OffsetDateTime odt = today.atTime(ot); 
Verwandte Themen