2015-01-23 27 views
5

Czy ktoś może wyjaśnić, dlaczego SimpleDateFormat odejmuje 1 sekundę od mojej sparsowanej daty podczas ustawiania strefy czasowej za pomocą SimpleTimeZone?Dlaczego SimpleDateFormat java odejmuje 1 sekundę od mojej daty UTC przy użyciu SimpleTimeZone

Czy to błąd jdk?

import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.SimpleTimeZone; 
import java.util.TimeZone; 

public class SimpleDateFormatTest { 

    public static void main(String[] args) throws ParseException { 

     SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 

     format.setTimeZone(TimeZone.getTimeZone("UTC")); 
     System.out.println(format.parse("2016-02-24T17:31:00Z")); 
     // prints Wed Feb 24 17:31:00 UTC 2016 

     format.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")); 
     System.out.println(format.parse("2016-02-24T17:31:00Z")); 
     // Wed Feb 24 17:30:59 UTC 2016 
    } 

} 

Odpowiedz

5

Niepoprawnie używasz konstruktora.

Konstruktor SimpleTimeZone jest zdefiniowany jako:

public SimpleTimeZone(int rawOffset, String ID)

Konstruuje SimpleTimeZone z danej bazy strefy czasowej z GMT i strefa czasowa ID bez światła oszczędności harmonogramu.

Parametry:

rawOffset - strefa czasowa baza przesunięte w milisekundach do GMT.

ID - Nazwa strefy czasowej podana dla tej instancji.

Pierwszym parametrem konstruktora jest to, ile tworzonej strefy czasowej różni się od GMT w milisekundach.

Nie ma powodu, aby używać żadnej z stałych STANDARD_TIME, UTC_TIME lub WALL_TIME tutaj. To nie jest miejsce, w którym mogą być używane. Jednak ponieważ te stałe są typu int, a parametr rawOffset jest typu int, Java nie uniemożliwia ci nieprzemyślanego przekazywania tych wartości do konstruktora.

W kodzie źródłowym Javy, stała ta jest zdefiniowana jako:

public static final int UTC_TIME = 2; 

Więc co się faktycznie robi podczas rozmowy

new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC") 

mówi „Proszę utworzyć strefę czasową, która jest 2 w milisekundach od GMT i nazwij go "UTC". Jestem prawie pewien, że to nie jest to, co próbowaliście osiągnąć. Jest to niestandardowa strefa czasowa, która jest nieco inna niż UTC, a różnica ta jest zaokrąglana do sekundy w wyjściu.

3

Wartość SimpleTimeZone.UTC_TIME jest rzeczywiście 2, więc SimpleTimeZone jest zbudowana z dwóch milisekundy Offset:

/** 
* Constant for a mode of start or end time specified as UTC. European 
* Union rules are specified as UTC time, for example. 
* @since 1.4 
*/ 
public static final int UTC_TIME = 2; 

/** 
* Constructs a SimpleTimeZone with the given base time zone offset from GMT 
* and time zone ID with no daylight saving time schedule. 
* 
* @param rawOffset The base time zone offset in milliseconds to GMT. 
* @param ID   The time zone name that is given to this instance. 
*/ 
public SimpleTimeZone(int rawOffset, String ID) 
{ 
    this.rawOffset = rawOffset; 
    setID (ID); 
    dstSavings = millisPerHour; 
} 

Ideone test:

public static void main(String[] args) throws ParseException { 
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 

    format.setTimeZone(TimeZone.getTimeZone("UTC")); 
    Date date1 = format.parse("2016-02-24T17:31:00Z"); 
    System.out.println(date1.getTime()); 

    format.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC")); 
    Date date2 = format.parse("2016-02-24T17:31:00Z"); 
    System.out.println(date2.getTime()); 
} 

Wyniki:

1456335060000 
1456335059998