2010-10-07 10 views
7

Si prega di Enlight me su questo:Aggiungete anno ad calendario di Java non funziona

Sto semplicemente cercando di aggiungere 10 anni alla data di arrivo quindi sottrarre una data di scadenza da essa per restituire il numero di anni:

public int getMaxYears() { 
    int max = 0; 
    Calendar ten_year_later = Calendar.getInstance(); 
    ten_year_later.setTime(new Date()); 
    ten_year_later.add(Calendar.YEAR, 10); 
    Calendar expiration = Calendar.getInstance(); 
    expiration.setTime(expiration_date); 
    max = (int) (ten_year_later.getTimeInMillis() - expiration.getTimeInMillis())/(365 * 24 * 60 * 60 * 1000); 
    return max; 
} 

Quando eseguo il debug, il calendario rimane sempre nell'anno corrente.

Chiunque?

+0

Quale calendario? dieci_year_later o scadenza? –

+0

@Paul Tomblin: dieci_year_later ... Io modificherò la domanda. – codea

+0

Inoltre: un anno non è 365 giorni, deve tenere conto degli anni bisestili. Per i calcoli approssimativi, 365.25 funziona, ma per i calcoli reali è necessario qualcosa che conosca le regole ... come Calendar. – Anon

risposta

11

Hai un problema con int/lungo conversione: 365 * 24 * 60 * 60 * 1000 che valuta a 31536000000 e quindi supera Questo funziona:

public static void main(String[] args) { 
      Calendar ten_year_later = Calendar.getInstance(); 
      System.out.println(ten_year_later.getTime()); 
      ten_year_later.setTime(new Date()); 
      ten_year_later.add(Calendar.YEAR, 10); 
      System.out.println(ten_year_later.getTime()); 
      Calendar expiration = Calendar.getInstance(); 
      expiration.setTime(expiration.getTime()); 
      long max = (ten_year_later.getTimeInMillis() - expiration.getTimeInMillis())/(365 * 24 * 60 * 60 * 1000L); 
      System.out.println("max " + max); 
     } 
+0

+1: Penso che sia meglio per il caso che l'OP vorrebbe arrotondare per anni invece di arrotondare. L'OP deve tenere presente che un anno non ha necessariamente 365 giorni. – BalusC

+0

Proprio così! Grazie! – codea

1

Il calendario è pigro, quindi potrebbe non ricalcolare tutti gli altri campi finché non li chiedi. Questo mi ha buttato fuori nel debugger prima. Cosa succede se si System.out.println(ten_year_later);?

+0

'getTimeInMillis()' dovrebbe aver già aggiornato i campi -come ogni altro metodo 'get' di' Calendar'. – BalusC

+0

Anche se chiamo ten_year_later.getTimeInMillis()? max è sempre 0 causa il expiration_date after di oggi. – codea

+0

No, stavo parlando di ciò che vedi nel debugger prima di chiamare getTimeInMillis(). –

5

Il calcolo di max è errato. Un int non può contenere un anno in millis.

Piuttosto sostituirlo con

max = ten_year_later.get(Calendar.YEAR) - expiration.get(Calendar.YEAR); 

O meglio, utilizzare JodaTime:

DateTime tenYearsLater = new DateTime().plusYears(10); 
DateTime expiration = new DateTime(expiration_date.getTime()); 
Period period = new Period(expiration, tenYearsLater); 
return period.getYears(); 
+0

Questo non funzionerà! 2020-01-01 - 2010-12-31 = 10. Dovrebbe dare 9 + 1 giorno, quindi 9 anni; – codea

+0

@elblanco: vedere il mio commento sulla risposta dello stacker. – BalusC

+0

+1 Sono pienamente d'accordo che dovrebbe essere calcolato come hai sottolineato. – stacker

3

Ecco un semplice esempio di cosa dovrebbe funzionare.

Calendar cal = new GregorianCalendar(); 
cal.setTime(new Date()); 
cal.add(Calendar.YEAR, yearsToAdd); 
Date retDate = cal.getTime(); 

Basta ricordare di usare un tempo per ottenere il tempo in millisecondi!

+1

Questa è l'unica soluzione funzionante per me di tutte queste risposte. Thx Bryan! – rilar

0

Il numero di millisecondi in un anno è ben al di fuori del range di un int, quindi sia il cast interno di ten_year_later.getTimeInMillis() - expiration.getTimeInMillis() che il calcolo 365 * 24 * 60 * 60 * 1000 valuteranno valori errati.

Il ten_year_later deve essere corretto. Non è necessario invocare computeField come ha scritto R. Bemrose.

1

Ho notato in un commento che si ha un calcolo errato per il numero di millis in un anno (non importa il problema int/long).

Dal momento che si dispone di due calendari, ognuno dei quali può tenere un anno, perché non scrivere il codice come questo (non compilato, quindi potrebbe contenere errori di battitura):

Calendar cal1 = Calendar.newInstance(); // this will use current time 
cal1.add(Calendar.YEAR, 10); 
Calendar cal2 = Calendar.newInstance(); 
cal2.setDate(expiration); 
return cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR); 

Partendo dal presupposto che è quello che veramente voglio ...

Problemi correlati