2011-10-26 20 views
39

Estoy tratando de determinar una edad en años a partir de cierta fecha. ¿Alguien sabe una forma limpia de hacer esto en Android? Tengo la aplicación Java disponible obviamente, pero la API de Java es muy débil, y esperaba que Android tuviera algo que me ayudara.¿Cómo puedo encontrar el número de años entre dos fechas?

EDITAR: Las múltiples recomendaciones para usar el tiempo Joda en Android me preocupan un poco debido a Android Java - Joda Date is slow y las preocupaciones relacionadas. Además, tirar de una biblioteca que no se envió con la plataforma por algo de este tamaño probablemente sea excesivo.

+0

Una pregunta similar: http://stackoverflow.com/questions/1116123/how-do-i-calculate-someones-age-in-java – jeha

Respuesta

72
public static int getDiffYears(Date first, Date last) { 
    Calendar a = getCalendar(first); 
    Calendar b = getCalendar(last); 
    int diff = b.get(YEAR) - a.get(YEAR); 
    if (a.get(MONTH) > b.get(MONTH) || 
     (a.get(MONTH) == b.get(MONTH) && a.get(DATE) > b.get(DATE))) { 
     diff--; 
    } 
    return diff; 
} 

public static Calendar getCalendar(Date date) { 
    Calendar cal = Calendar.getInstance(Locale.US); 
    cal.setTime(date); 
    return cal; 
} 
+4

¿Cuáles son las constantes MES, AÑO y FECHA? –

+4

@ChrisSim: son importaciones estáticas de Calendar.MONTH y más. – sinuhepop

+1

Creo que en lugar de DATE debería ser DAY_OF_MONTH. – jiahao

14

Recomendaría utilizar la gran biblioteca Joda-Time para todo lo relacionado con fechas en Java.

Para sus necesidades puede usar el método Years.yearsBetween().

+0

He usado Joda mucho este último proyecto . Realmente se trata de matar en términos de configuración ... – StarWind0

+1

Solo para elaborar: 'public int getYears (org.java.util.Date time) { org.joda.time.DateTime now = org.joda.time. DateTime.now(); org.joda.time.DateTime then = new org.joda.time.DateTime (time.getTime()); return org.joda.time.Years.yearsBetween (ahora, luego) .getYears(); } ' – Nielsvh

0

Si no quiere calcularlo usando el Calendario de Java puede usar Androids Time class Se supone que es más rápido pero no noté mucha diferencia cuando cambié.

No pude encontrar ninguna función predefinida para determinar el tiempo entre 2 fechas para una edad en Android. Hay algunas buenas funciones de ayuda para obtener el formato del tiempo entre las fechas en el DateUtils pero probablemente no sea lo que usted desea.

0

Sé que usted ha pedido una solución limpia, pero aquí hay dos sucia vez:

 static void diffYears1() 
{ 
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy"); 
    Calendar calendar1 = Calendar.getInstance(); // now 
    String toDate = dateFormat.format(calendar1.getTime()); 

    Calendar calendar2 = Calendar.getInstance(); 
    calendar2.add(Calendar.DAY_OF_YEAR, -7000); // some date in the past 
    String fromDate = dateFormat.format(calendar2.getTime()); 

    // just simply add one year at a time to the earlier date until it becomes later then the other one 
    int years = 0; 
    while(true) 
    { 
     calendar2.add(Calendar.YEAR, 1); 
     if(calendar2.getTimeInMillis() < calendar1.getTimeInMillis()) 
      years++; 
     else 
      break; 
    } 

    System.out.println(years + " years between " + fromDate + " and " + toDate); 
} 

static void diffYears2() 
{ 
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy"); 
    Calendar calendar1 = Calendar.getInstance(); // now 
    String toDate = dateFormat.format(calendar1.getTime()); 

    Calendar calendar2 = Calendar.getInstance(); 
    calendar2.add(Calendar.DAY_OF_YEAR, -7000); // some date in the past 
    String fromDate = dateFormat.format(calendar2.getTime()); 

    // first get the years difference from the dates themselves 
    int years = calendar1.get(Calendar.YEAR) - calendar2.get(Calendar.YEAR); 
    // now make the earlier date the same year as the later 
    calendar2.set(Calendar.YEAR, calendar1.get(Calendar.YEAR)); 
    // and see if new date become later, if so then one year was not whole, so subtract 1 
    if(calendar2.getTimeInMillis() > calendar1.getTimeInMillis()) 
     years--; 

    System.out.println(years + " years between " + fromDate + " and " + toDate); 
} 
-1

Prueba esto:

int getYear(Date date1,Date date2){ 
     SimpleDateFormat simpleDateformat=new SimpleDateFormat("yyyy"); 
     Integer.parseInt(simpleDateformat.format(date1)); 

     return Integer.parseInt(simpleDateformat.format(date2))- Integer.parseInt(simpleDateformat.format(date1)); 

    } 
+1

@Johnny Graber se preocupan por explicar por qué votó este ... ehem ... ¿respuesta no óptima? – kleopatra

+0

Downvoted ya que esto no toma los días en cuenta. – leparlon

1

que al parecer no puedo comentar todavía, pero Creo que solo puede usar el DAY_OF_YEAR para entrenar si debe ajustar los años uno abajo (copiado y modificado de la mejor respuesta actual)

public static int getDiffYears(Date first, Date last) { 
    Calendar a = getCalendar(first); 
    Calendar b = getCalendar(last); 
    int diff = b.get(Calendar.YEAR) - a.get(Calendar.YEAR); 
    if (a.get(Calendar.DAY_OF_YEAR) > b.get(Calendar.DAY_OF_YEAR)) { 
     diff--; 
    } 
    return diff; 
} 

public static Calendar getCalendar(Date date) { 
    Calendar cal = Calendar.getInstance(Locale.US); 
    cal.setTime(date); 
    return cal; 
} 

Del mismo modo, es probable que pueda simplemente diferir las representaciones ms de la hora y dividir por el número de ms en un año. Simplemente mantenga todo en longs y eso debería ser lo suficientemente bueno la mayoría de las veces (años bisiestos, ouch) pero depende de su aplicación por la cantidad de años y de cuán eficiente debe ser esa función el clima, valdría la pena ese tipo de pirateo.

+0

El uso de DAY_OF_YEAR también genera errores con los años bisiestos. – sinuhepop

0
// int year =2000; int month =9 ; int day=30; 

    public int getAge (int year, int month, int day) { 

      GregorianCalendar cal = new GregorianCalendar(); 
      int y, m, d, noofyears;   

      y = cal.get(Calendar.YEAR);// current year , 
      m = cal.get(Calendar.MONTH);// current month 
      d = cal.get(Calendar.DAY_OF_MONTH);//current day 
      cal.set(year, month, day);// here ur date 
      noofyears = y - cal.get(Calendar.YEAR); 
      if ((m < cal.get(Calendar.MONTH)) 
          || ((m == cal.get(Calendar.MONTH)) && (d < cal 
              .get(Calendar.DAY_OF_MONTH)))) { 
        --noofyears; 
      } 
      if(noofyears < 0) 
        throw new IllegalArgumentException("age < 0"); 
      System.out.println(noofyears); 
      return noofyears; 
1

Esto es lo que creo que es un método mejor:

public int getYearsBetweenDates(Date first, Date second) { 
    Calendar firstCal = GregorianCalendar.getInstance(); 
    Calendar secondCal = GregorianCalendar.getInstance(); 

    firstCal.setTime(first); 
    secondCal.setTime(second); 

    secondCal.add(Calendar.DAY_OF_YEAR, 1 - firstCal.get(Calendar.DAY_OF_YEAR)); 

    return secondCal.get(Calendar.YEAR) - firstCal.get(Calendar.YEAR); 
} 

EDITAR

Aparte de un error que me fijo, este método no funciona bien con los años bisiestos. Aquí hay un conjunto completo de pruebas. Supongo que será mejor que utilices la respuesta aceptada.

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

class YearsBetweenDates { 
    public static int getYearsBetweenDates(Date first, Date second) { 
     Calendar firstCal = GregorianCalendar.getInstance(); 
     Calendar secondCal = GregorianCalendar.getInstance(); 

     firstCal.setTime(first); 
     secondCal.setTime(second); 

     secondCal.add(Calendar.DAY_OF_YEAR, 1 - firstCal.get(Calendar.DAY_OF_YEAR)); 

     return secondCal.get(Calendar.YEAR) - firstCal.get(Calendar.YEAR); 
    } 

    private static class TestCase { 
     public Calendar date1; 
     public Calendar date2; 
     public int expectedYearDiff; 
     public String comment; 

     public TestCase(Calendar date1, Calendar date2, int expectedYearDiff, String comment) { 
      this.date1 = date1; 
      this.date2 = date2; 
      this.expectedYearDiff = expectedYearDiff; 
      this.comment = comment; 
     } 
    } 

    private static TestCase[] tests = { 
     new TestCase(
       new GregorianCalendar(2014, Calendar.JULY, 15), 
       new GregorianCalendar(2015, Calendar.JULY, 15), 
       1, 
       "exactly one year"), 
     new TestCase(
       new GregorianCalendar(2014, Calendar.JULY, 15), 
       new GregorianCalendar(2017, Calendar.JULY, 14), 
       2, 
       "one day less than 3 years"), 
     new TestCase(
       new GregorianCalendar(2015, Calendar.NOVEMBER, 3), 
       new GregorianCalendar(2017, Calendar.MAY, 3), 
       1, 
       "a year and a half"), 
     new TestCase(
       new GregorianCalendar(2016, Calendar.JULY, 15), 
       new GregorianCalendar(2017, Calendar.JULY, 15), 
       1, 
       "leap years do not compare correctly"), 
    }; 

    public static void main(String[] args) { 
     SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 
     for (TestCase t : tests) { 
      int diff = getYearsBetweenDates(t.date1.getTime(), t.date2.getTime()); 
      String result = diff == t.expectedYearDiff ? "PASS" : "FAIL"; 
      System.out.println(t.comment + ": " + 
        df.format(t.date1.getTime()) + " -> " + 
        df.format(t.date2.getTime()) + " = " + 
        diff + ": " + result); 
     } 
    } 
} 
+0

esto no parece funcionar –

+0

Hubo un error relacionado con días basados ​​en una sola. Pero esto tampoco funciona bien con los años bisiestos. Por favor mira mi edición. – SnakE

4

tl; dr

ChronoUnit.YEARS.between(LocalDate.of(2010 , 1 , 1) , LocalDate.now(ZoneId.of("America/Montreal"))) 

java.time

El viejo fecha-hora clases realmente son malos, tan malos que tanto Sun & Oracle acordó suplantarlos con el java.time clases Si realiza algún trabajo significativo con valores de fecha y hora, vale la pena agregar una biblioteca a su proyecto.La biblioteca Joda-Time fue muy exitosa y recomendada, pero ahora está en modo de mantenimiento. El equipo aconseja la migración a las clases java.time.

Gran parte de la funcionalidad java.time está de vuelta-portado a Java 6 & 7 en ThreeTen-Backport y adaptado además para Android en ThreeTenABP (ver How to use…).

LocalDate start = LocalDate.of(2010 , 1 , 1) ; 
LocalDate stop = LocalDate.now(ZoneId.of("America/Montreal")); 
long years = java.time.temporal.ChronoUnit.YEARS.between(start , stop); 

Volcar a la consola.

System.out.println("start: " + start + " | stop: " + stop + " | years: " + years) ; 

inicio: 2010-01-01 | detener: 2016-09-06 | Años: 6

Cuestiones relacionadas