2013-02-07 8 views
11

Ciò ha causato un bug di tipo Y2K nel mio software, se potete immaginare. La cosa strana è che il calcolo di anno dopo anno si verifica solo per due giorni all'anno, che sono meno sicuro su come risolvere i problemi.Java Il calcolo dell'anno data è disattivato per un anno per due giorni

L'output:

03-Jan-2013 
02-Jan-2013 
01-Jan-2013 
31-Dec-2013 ** strange 
30-Dec-2013 ** strange 
29-Dec-2012 
28-Dec-2012 
27-Dec-2012 
26-Dec-2012 
25-Dec-2012 

io non sono sicuro di quale parte della data utility Java potrebbe causare un errore del genere.

Il codice (dal momento che il test è così piccola ho incluso un programma di lavoro completo):

import java.util.Calendar; 
import java.util.Date; 
import java.text.SimpleDateFormat; 

public class DateT { 

     private static String getFormattedBackscanStartTime(int days) { 

       SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-YYYY"); 
       Calendar workingDate = Calendar.getInstance(); 
       workingDate.add(Calendar.DATE, -1 * days); 

       String formattedStartTime = dateFormat.format(workingDate.getTime()); 
       return formattedStartTime; 
     } 

     public static void main(String args[]) { 

       for(int i = 35; i < 45; i++) { 
         System.out.println(getFormattedBackscanStartTime(i)); 
       } 
     } 
} 
+0

Penso che ne trarrai beneficio. https://forums.oracle.com/forums/thread.jspa?threadID=2096000 – Achrome

+2

Ricorda che le classi 'Calendar' e' SimpleDateFormat' sono ora [legacy] (https://en.wikipedia.org/wiki/ Sistema legacy). Soppiantato dalle classi [java.time] (https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html). Un approccio moderno utilizza invece le classi 'LocalDate',' ZoneId' e 'DateTimeFormatter'. –

risposta

26

Questo è il problema:

"dd-MMM-YYYY" 

YYYY è il week-anno, non il calendario anno. Si desidera invece yyyy.

Gli ultimi due giorni dell'anno solare 2012 si sono verificati nella prima settimana della settimana dell'anno 2013. Di norma, utilizzare l'anno della settimana solo in combinazione con l'identificatore "settimana dell'anno" (w).

2

Il problema si trova nella stringa del formato data - l'anno deve essere yyyy non YYYY.

Se si stampa il valore di workingDate.getTime() in ogni iterazione del ciclo, vedrete che ha i valori attesi:

Thu Jan 03 11:19:33 EST 2013 
Wed Jan 02 11:19:33 EST 2013 
Tue Jan 01 11:19:33 EST 2013 
Mon Dec 31 11:19:33 EST 2012 
Sun Dec 30 11:19:33 EST 2012 
Sat Dec 29 11:19:33 EST 2012 
Fri Dec 28 11:19:33 EST 2012 
Thu Dec 27 11:19:33 EST 2012 
Wed Dec 26 11:19:33 EST 2012 
Tue Dec 25 11:19:33 EST 2012 

Pertanto il problema risiede nell'uso SimpleDateFormat.

+0

+1 per il debug del passo – djechlin

1

È necessario utilizzare la lettera minuscola y per l'anno. Prova questo:

SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy"); 
5

Suppongo che si stia utilizzando java 1.7.

Il frammento di codice di cui sopra non funzionerà con java 1.6 come SimpleDateFormat("dd-MMM-YYYY") solleverà un java.lang.IllegalArgumentException (AAAA non è disponibile in java 1.6)

È necessario utilizzare yyyy invece di YYYY.

Y -> week-year 
y -> year 

here

EDIT

grandi opere con yyyy:

$ java DateT 
03-Jan-2013 
02-Jan-2013 
01-Jan-2013 
31-Dec-2012 
30-Dec-2012 
29-Dec-2012 
28-Dec-2012 
27-Dec-2012 
26-Dec-2012 
25-Dec-2012 
+0

+1 per averne solo 1.7. – djechlin

1

Per ragioni di completezza, ecco la risposta moderna utilizzando LocalDate (come raccomandato da Basil Bourque in un commento).

import java.time.LocalDate; 
import java.time.format.DateTimeFormatter; 
import java.util.Locale; 

public class DateT { 

    private static DateTimeFormatter dateFormatter 
      = DateTimeFormatter.ofPattern("dd-MMM-uuuu", Locale.US); 

    private static String getFormattedBackscanStartTime(int days) { 
     return LocalDate.now(ZoneId.systemDefault()).minusDays(days).format(dateFormatter); 
    } 

    public static void main(String args[]) { 
     for(int i = 155; i < 165; i++) { 
      System.out.println(getFormattedBackscanStartTime(i)); 
     } 
    } 
} 

funzionamento di questo oggi ho avuto

04-Jan-2017 
03-Jan-2017 
02-Jan-2017 
01-Jan-2017 
31-Dec-2016 
30-Dec-2016 
29-Dec-2016 
28-Dec-2016 
27-Dec-2016 
26-Dec-2016 

Un paio di cose da notare:

  • danno un locale esplicito al formattatore per controllare il langauge delle copie. Anche se passi semplicemente a Locale.getDefault(), stai dicendo al lettore che hai pensato al locale e hai preso una decisione.
  • Analogamente, assegnare un fuso orario esplicito a LocalDate.now() per comunicare al lettore che ha preso una decisione (ad esempio ZoneId.of("America/New_York") per un fuso orario specifico, ZoneId.systemDefault() per l'impostazione del fuso orario corrente della JVM).
  • Trovo il codice più semplice e più diretto del codice utilizzando la classe Calendar vecchio stile. Questo è tipico per le classi più recenti.
  • Ho usato uuuu per anno. yyyy (in minuscolo) funziona anche, ci sarà solo una differenza per anni prima dell'era comune (AKA BC).
Problemi correlati