2016-02-03 31 views
6

Avevo una situazione in cui il runtime Java restituiva valori di millisecondo "invertiti" durante la lettura delle date dal database (in java.sql.Date). Il valore del millisecondo era approssimativamente lo stesso numero di giorni, ma contava all'indietro a partire dall'anno 0.Come funziona java.sql.Date con date negative?

Il problema è stato risolto semplicemente riavviando il runtime Java.

Ma: ho scoperto che Java gestisce questi valori "invertiti" quasi correttamente tranne il giorno della settimana.

Quando si esegue il seguente codice:

System.out.println(new java.util.Date(253402214400000l)); 
System.out.println(new java.util.Date(-377648784000000l)); 

Si otterrà il seguente output:

Fri Dec 31 01:00:00 CET 9999 
Tue Dec 31 01:00:00 CET 9999 

Un altro esempio:

System.out.println(new java.util.Date(-294192000000l)); 
System.out.println(new java.util.Date(-123967324800000l)); 

Risultato:

Mon Sep 05 01:00:00 CET 1960 
Mon Sep 05 01:00:00 CET 1960 

Quando si utilizzano convertitori online, il risultato sarà diverso per la seconda riga in particolare. Il risultato sarà una data negativo (l'anno è negativo) vicino al reale, data di positivo:

Example1: 
253402214400000 = Fri Dec 31 9999 01:00:00 
-377648784000000 = Tue Oct 15 -9998 02:00:00 

Example 2: 
-294192000000 = Mon Sep 05 1960 02:00:00 
-123967324800000 = Mon Aug 19 -1959 02:00:00 

non ho trovato alcuna informazione su questo "argomento".

Quindi, qual è il mito dietro date "invertite"? Perché Java li gestisce quasi correttamente? E qual è il senso di un JDBC ResultSet che restituisce valori "invertiti" al millisecondo quando chiama resultSet.getDate(1).getTime()?

+0

Stai parlando di 'java.util.Date' o' java.sql.Date'? Renditi conto che il comportamento di un set di risultati JDBC è specifico del driver, dato che ciascun driver lo implementa per il proprio database specifico. –

+0

È un java.sql.Date (sottoclasse di java.util.Date) – praisezh

+1

Non ho idea di cosa intendi per "invertito". – chrylis

risposta

1

Quando si passa un numero negativo nel costruttore Date, viene considerato come numero di millesecondi prima di 1/1/1970. Il Javadoc dice:

data - millisecondi dal 1 gennaio 1970, 00:00:00 GMT non superare la rappresentazione millisecondi per l'anno 8099. Un numero negativo indica il numero di millisecondi prima del 1 gennaio 1970,

si può vedere il risultato che si ottiene quando si tenta di fornire la Long.MIN_VALUE e Long.MAX_VALUE nel costruttore Data.

DateFormat df = new SimpleDateFormat("d MMM yyyy G, HH:mm:ss.S Z"); 
System.out.println(df.format(new Date(Long.MIN_VALUE))); 
System.out.println(df.format(new Date(Long.MAX_VALUE))); 

Ideone Demo

+0

come risponde a questa domanda? – AdamSkywalker

+0

Grazie, lo so. La domanda non riguardava valori millisecondi negativi prima dell'anno 1970, ma valori millisecondi invertiti prima dell'anno 0. – praisezh

1

ho scoperto che Java gestisce questi valori "invertiti" quasi correttamente ad eccezione del giorno della settimana.

Nel vostro primo esempio, non sono le due date lo stesso - una è aC e l'altra AD (il che spiega il motivo per cui il giorno della settimana è diversa):

Date d1 = new Date(253402214400000l); 
Date d2 = new Date(-377648784000000l); 
DateFormat fmt = new SimpleDateFormat("yyyy G"); 
System.out.println(fmt.format(d1)); //9999 AD 
System.out.println(fmt.format(d2)); //9999 BC 

Quindi la tua osservazione è solo una coincidenza (tuttavia potrebbe esserci una data formattatore da qualche parte che si è scatenata e nega gli anni o gli anni potrebbero effettivamente essere negativi nel database).

La differenza con i convertitori online è probabilmente dovuta a come l'anno 0 viene preso in considerazione e/o alle variazioni nel calendario utilizzato per i calcoli.

+0

Ma un riavvio del runtime Java risolveva il problema :-) quindi nessun valore errato nel database, nessun formato di data speciale in uso. – praisezh

+1

@praisezh Riesci a trovare un modo per riprodurre il problema? – assylias