2015-01-23 11 views
5

Qualcuno può spiegare perché SimpleDateFormat sottrarre 1 secondo alla mia data analizzata quando si imposta il fuso orario con SimpleTimeZone?Perché il simpleDateFormat di java è sottratto 1 secondo dalla data UTC quando utilizzo SimpleTimeZone

Si tratta di un bug 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 
    } 

} 

risposta

5

Si sta utilizzando il costruttore in modo errato.

Il costruttore di SimpleTimeZone è definito come:

public SimpleTimeZone(int rawOffset, String ID)

Costruisce un SimpleTimeZone con il tempo determinato offset da GMT e fuso ID senza luce risparmio calendario zona di base.

Parametri:

rawOffset - Il tempo di zona compensato in millisecondi a GMT.

ID - Il nome del fuso orario assegnato a questa istanza è .

Quindi il primo parametro del costruttore è quanto il fuso orario che si sta creando differirà da GMT, in millisecondi.

Non c'è motivo di utilizzare nessuna delle costanti STANDARD_TIME, UTC_TIME o WALL_TIME qui. Questo non è il posto per loro da usare. Tuttavia, poiché queste costanti sono di tipo int e il parametro rawOffset è di tipo int, Java non impedisce di passare queste costanti erroneamente al costruttore.

Nel codice sorgente di Java, questa costante è definita come:

public static final int UTC_TIME = 2; 

Allora, cosa si sta effettivamente facendo quando si chiama

new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC") 

sta dicendo "Si prega di creare un fuso orario che è 2 millisecondi di distanza da GMT e chiamarlo "UTC" ". Sono abbastanza sicuro che questo non è quello che stavi cercando di raggiungere. È un fuso orario personalizzato, leggermente diverso da UTC e questa differenza viene arrotondata a un intero secondo nell'output.

3

Il valore di SimpleTimeZone.UTC_TIME è in realtà 2, quindi il SimpleTimeZone è costruito con un offset di due millisecondi:

/** 
* 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()); 
} 

Risultati:

1456335060000 
1456335059998 
Problemi correlati