2011-10-26 43 views
39

Tôi đang cố gắng xác định độ tuổi theo năm từ một ngày nhất định. Có ai biết một cách sạch sẽ để làm điều này trong Android? Tôi có Java api có sẵn rõ ràng, nhưng api thẳng lên java là khá yếu, và tôi đã hy vọng rằng Android có một cái gì đó để giúp tôi ra ngoài.Tôi có thể tìm số năm giữa hai ngày bằng cách nào?

EDIT: Nhiều đề xuất sử dụng thời gian Joda trong Android khiến tôi lo lắng một chút do Android Java - Joda Date is slow và các mối quan tâm có liên quan. Ngoài ra, kéo trong một thư viện không được vận chuyển với nền tảng cho một cái gì đó kích thước này có lẽ là quá mức cần thiết.

+0

Câu hỏi tương tự: http://stackoverflow.com/questions/1116123/how-do-i-calculate-someones-age-in-java – jeha

Trả lời

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

Hằng số MONTH, YEAR và DATE là gì ?? –

+4

@ChrisSim: Chúng là hàng nhập tĩnh của Lịch.MONTH và cứ tiếp tục như vậy. – sinuhepop

+1

Tôi nghĩ thay vì NGÀY thì phải là DAY_OF_MONTH. – jiahao

14

Tôi khuyên bạn nên sử dụng thư viện Joda-Time tuyệt vời cho mọi ngày liên quan đến Java.

Đối với nhu cầu của bạn, bạn có thể sử dụng phương thức Years.yearsBetween().

+0

Tôi đã sử dụng Joda rất nhiều dự án cuối cùng này . Nó thực sự là trên giết trong điều khoản của thiết lập ... – StarWind0

+1

Chỉ cần để xây dựng: 'public int getYears (org.java.util.Định thời gian) { org.joda.time.DateTime now = org.joda.time. DateTime.now(); org.joda.time.DateTime sau đó = new org.joda.time.DateTime (time.getTime()); trả về org.joda.time.Years.yearsBetween (bây giờ, sau đó) .getYears(); } ' – Nielsvh

0

Nếu bạn không muốn tính toán bằng cách sử dụng Lịch của java, bạn có thể sử dụng Androids Time class Nó được cho là nhanh hơn nhưng tôi không nhận thấy nhiều sự khác biệt khi tôi chuyển.

Tôi không thể tìm thấy bất kỳ chức năng được xác định trước nào để xác định thời gian giữa 2 ngày cho một độ tuổi trong Android. Có một số chức năng trợ giúp tốt đẹp để có được thời gian định dạng giữa các ngày trong DateUtils nhưng đó có thể không phải là những gì bạn muốn.

0

Tôi biết bạn đã yêu cầu một giải pháp sạch, nhưng đây là hai bẩn một lần:

 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

Hãy thử điều này:

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 quan tâm giải thích tại sao bạn lại bỏ phiếu này ... ehem ... câu trả lời tối ưu? – kleopatra

+0

Được giảm giá vì điều này không tính đến các ngày. – leparlon

1

tôi dường như không thể bình luận nào, nhưng Tôi nghĩ bạn chỉ có thể sử dụng DAY_OF_YEAR để tập luyện nếu bạn nên điều chỉnh năm xuống một (sao chép và sửa đổi từ câu trả lời hay nhất hiện tại)

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

Tương tự, bạn có thể chỉ cần phân biệt các biểu diễn ms của thời gian và chia cho số ms trong một năm. Chỉ cần giữ tất cả mọi thứ trong thời gian dài và điều đó phải đủ tốt hầu hết thời gian (năm nhuận, ouch) nhưng nó phụ thuộc vào ứng dụng của bạn cho số năm và cách thực hiện chức năng đó phải là thời tiết nó sẽ có giá trị mà loại hack.

+0

Sử dụng DAY_OF_YEAR dẫn đến lỗi với năm nhuận. – 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

Đây là những gì tôi nghĩ là một phương pháp tốt hơn:

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

EDIT

Ngoài một lỗi mà tôi cố định, phương pháp này không làm việc tốt với năm nhuận. Đây là một bộ thử nghiệm hoàn chỉnh. Tôi đoán bạn nên sử dụng câu trả lời được chấp nhận.

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

điều này dường như không hoạt động –

+0

Đã xảy ra lỗi liên quan đến ngày dựa trên một ngày. Nhưng điều này cũng không hoạt động tốt với những năm nhuận. Vui lòng xem chỉnh sửa của tôi. – SnakE

4

tl; dr

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

java.time

Các cũ ngày thời gian lớp học thực sự là xấu, xấu như vậy mà cả hai Sun & Oracle đồng ý để thay thế chúng với java.time các lớp học. Nếu bạn làm bất kỳ công việc quan trọng nào cả với các giá trị ngày giờ, việc thêm một thư viện vào dự án của bạn là đáng giá.Thư viện Joda-Time rất thành công và được đề xuất, nhưng hiện đang trong chế độ bảo trì. Nhóm này khuyên bạn nên di trú sang các lớp java.time.

Hầu hết các chức năng java.time được back-chuyển đến Java 6 & 7 trong ThreeTen-Backport và tiếp tục thích nghi với Android trong ThreeTenABP (xem 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); 

Dump to console.

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

bắt đầu: 2010-01-01 | dừng lại: 2016-09-06 | năm: 6

Các vấn đề liên quan