2010-10-07 21 views
7

Por favor EnLight en esto:Agregar a Java año calendario no funciona

Simplemente estoy tratando de añadir 10 años a la fecha actual y luego restar una fecha de caducidad de la misma para devolver el número de años:

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; 
} 

Cuando depuro esto, el calendario siempre permanece en el año actual.

¿Alguien?

+0

¿Qué calendario? ¿diez_year_later o vencimiento? –

+0

@Paul Tomblin: ten_year_later ... Editaré la pregunta. – codea

+0

También: un año no es 365 días, tiene que representar los años bisiestos. Para cálculos aproximados, 365.25 funciona, pero para cálculos reales necesita algo que conozca las reglas ... como Calendar. – Anon

Respuesta

11

Usted tiene un problema con int conversión A/larga: 365 * 24 * 60 * 60 * 1000 que evalúa a 31536000000 y por lo tanto excede Esto funciona:

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: Creo que esto es mejor para el caso que a la OP le gustaría redondear en años en lugar de redondear. El OP solo debe tener en cuenta que un año no necesariamente tiene 365 días. – BalusC

+0

¡Adelante! ¡Gracias! – codea

1

El calendario es flojo, por lo que es posible que no vuelva a calcular todos los demás campos hasta que lo solicite. Eso me ha expulsado en el depurador antes. ¿Qué ocurre si System.out.println(ten_year_later);?

+0

El 'getTimeInMillis()' ya debería haber actualizado los campos, como cualquier otro método 'get' de' Calendar'. – BalusC

+0

Incluso si llamo a ten_year_later.getTimeInMillis()? max siempre es 0 porque expiration_date after than today. – codea

+0

No, estaba hablando de lo que ve en el depurador antes de llamar a getTimeInMillis(). –

5

Su cálculo de max es incorrecto. Un int no puede contener un año en milis.

Más bien sustituirlo por

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

O mejor, utilizar JodaTime:

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

¡Esto no funcionará! 2020-01-01 - 2010-12-31 = 10. Debe dar 9 + 1 día, entonces 9 años; – codea

+0

@elblanco: vea mi comentario sobre la respuesta del apilador. – BalusC

+0

+1 Estoy totalmente de acuerdo en que debe calcularse como usted indicó. – stacker

3

Aquí hay un ejemplo simple de lo que debería funcionar.

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

¡Recuerde utilizar un largo para obtener el tiempo en milisegundos!

+1

Esta es la única solución de trabajo para mí de todas estas respuestas. ¡Thx Bryan! – rilar

0

El número de milisegundos en un año está bien fuera del rango de un int, por lo que tanto el int pitch de ten_year_later.getTimeInMillis() - expiration.getTimeInMillis() como el cálculo 365 * 24 * 60 * 60 * 1000 evaluarán valores incorrectos.

El ten_year_later debería ser correcto. No es necesario invocar computeFields como escribió R. Bemrose.

1

He notado en un comentario que tiene un cálculo incorrecto para el número de millis en un año (sin importar el problema int/long).

Puesto que usted tiene dos calendarios, cada uno de los cuales puede tener un año, ¿por qué no escribir el código como este (no compilado, por lo que puede contener errores tipográficos):

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); 

Suponiendo que es lo que realmente quiere ...