2016-09-14 271 views
2

我想计算考虑闰年的确切年龄。我在网络上进行了研究,发现了一些教程,但用闰年精确计算日期差异的日子似乎是[1]:https://answers.yahoo.com/question/index?qid=20110629162003AAof4mT此链接中的一个,即“最佳答案”。我分析代码,但有两个问题:计算考虑闰年的java年龄

1)为什么它写道:“天=天数+ leapYears”下面的“计算日子的生活”部分,

2)最后,我怎么能输入的生日日期的日,月以及年和当日,月,年,并在主要方法中的代码中发现这两个日期在天内的差异?我非常感谢你的帮助。提前致谢 !

PS:为了方便起见,我已经包括来自链接我上面显示的代码:

public class Days { 


     static int leapYear(int year) { 
int leap; 
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { 
leap = 1; 
} 
else { 
leap = 0; 
} 
return leap; 
} 

static int daysBefore(int month, int day, int year){ 
int days = 0; 
int monthDays[] = new int[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
if (leapYear(year) == 1){ 
monthDays[1] = 29; 
} 
for (int b = 0; b < month - 1; b++){ 
days = days + monthDays[b]; 
} 
days = days + day; 
return days; 
} 
public static void main(String[] args) { 
//Birth date 
int birthMonth = 0; 
int birthDay = 0; 
int birthYear = 0; 

//Due date 
int dueMonth = 0; 
int dueDay = 0; 
int dueYear = 0; 

//(1) Calculate years lived 
int yearsLived = dueYear - birthYear + 1; 

//(2) Calculate leap years 
int leapYears = 0; 
for (int year = birthYear; year < dueYear+1; year++) 
{ 
leapYears = leapYears + leapYear(year); 
} 

//(3) Calculate the number of days in your birth year before birth 
int daysBeforeBirth = daysBefore(birthMonth, birthDay, birthYear); 

//(4) Calculate the number of days remaining in the current year after the due date 
int daysRemaining = 365 - daysBefore(dueMonth, dueDay, dueYear); 

//Calculate days lived 
int days = 0; 
days = days + (365 * yearsLived); 
days = days + leapYears; 
days = days - daysBeforeBirth; 
days = days - daysRemaining; 
} 
} 
+0

只需使用日历 –

+1

您是想从第一原则自己计算还是使用现有的JDK类? –

+5

只需使用日期/时间API,而不是日历:) –

回答

3

正确的方法是使用java.time包中的PeriodLocalDate类。但是,您似乎正在尝试为自己重新进行计算。

我推荐这样做的方法是编写一个类,让您计算给定日期的“日数” - 即指定日期和过去某个任意日期之间的天数。然后,当您想要查找两个指定日期之间的天数时,只需使用两个日期的“日数”计算,然后减去它们即可。

我已经做了,在这里,对于一个纯粹的公历。在格里高利的转换之前,这门课并不好 - 我还没有尝试构建历史上精确的儒略/格里历混合日历,比如JDK提供的。过去的任意日期是计算日数的日期是12月31日,2BC。这个日期当然不是公历的一部分,但为了我们的目的,这并不重要。

因为你不可能遇到Gregorian转换之前的任何日期,这个类应该是绰绰有余为您的目的。对于生产代码,我仍然建议使用PeriodLocalDate类而不是这个类。这只是在这里,所以你可以看到如何做计算。

public class GregorianDate { 

    private final int day; 
    private final int month; 
    private final int year; 

    private static final int[] DAYS_PER_MONTH = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 

    public GregorianDate(int day, int month, int year) { 
     this.day = day; 
     this.month = month; 
     this.year = year; 
    } 

    public boolean isValid() { 
     return month >= 1 && month <= 12 && day >= 1 && day <= daysThisMonth(); 
    } 

    public static int daysBetween(GregorianDate from, GregorianDate to) { 
     return to.dayNumber() - from.dayNumber(); 
    } 

    public static int daysBetween(int fromDay, int fromMonth, int fromYear, int toDay, int toMonth, int toYear) { 
     return daysBetween(new GregorianDate(fromDay, fromMonth, fromYear), new GregorianDate(toDay, toMonth, toYear)); 
    } 

    private int daysThisMonth() { 
     return (isLeapYear() && month == 2) ? 29 : DAYS_PER_MONTH[month]; 
    } 

    private int dayNumber() { 
     return year * 365 + leapYearsBefore() + daysInMonthsBefore() + day; 
    } 

    private boolean isLeapYear() { 
     return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; 
    } 

    private int leapYearsBefore() { 
     return year/4 - year/100 + year/400; 
    } 

    private int daysInMonthsBefore() { 
     switch(month) { 
     case 1: 
      return 0; 
     case 2: 
      return 31; 
     default: 
      // Start with the number in January and February combined 
      int toReturn = isLeapYear() ? 60 : 59; 
      for (int monthToConsider = 3; monthToConsider < month; monthToConsider++) { 
       toReturn += DAYS_PER_MONTH[monthToConsider]; 
      } 
      return toReturn; 
     } 
    } 

} 
1

要回答的问题1. 每leapyear优1号添加一天的一年。笔者首先计算多少天,如果所有的表现还算正常已生活使用这方面的知识:

days = days + (365 * yearsLived); 

,然后添加leapyears(记住1个leapyear = 1额外的一天)的数量。

对于第二个问题: 该代码寻求birthDate(read:startDate)和dueDate(read endDate)之间的区别。因此,要计算开始和结束之间的差异,您必须给这些整数输入日期,代码将完成剩余的部分。

+0

是的,我明白了。谢谢大家的好意和深刻的解释! –

1

TL;博士

long ageInDays = 
    ChronoUnit.DAYS.between( 
     LocalDate.of(1960 , 1 , 2) , 
     LocalDate.now(ZoneId.of("America/Montreal")) 
    ); 

使用java.time

如果您正在探索的算法,请参阅显然correct Answer by David Wallace

如果您正在为此进行有效的工作,那么请做而不是推出您自己的日期 - 时间课程。避免旧的日期时间类(.Date,.Calendar等)并使用java.time类。

枚举具有令人惊讶的数量的效用,包括计算经过时间。传递几个Temporal对象,在我们的例子中为LocalDate对象。

LocalDate start = LocalDate.of(1960 , 1 , 2) ; 
LocalDate today = LocalDate.now(ZoneId.of("America/Montreal")) ; 
long ageInDays = ChronoUnit.DAYS.between(start , today) ; 

关于java.time

java.time框架是建立在Java 8和更高版本。这些课程取代了麻烦的旧日期时间课程,如java.util.Date,.Calendar,& java.text.SimpleDateFormat

Joda-Time项目现在位于maintenance mode,建议迁移到java.time。请参阅Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。

大部分的java.time功能后移植到Java 6 和ThreeTenABP还适于Android(见How to use…)。

ThreeTen-Extra项目扩展java.time与其他类。这个项目是未来可能增加java.time的一个试验场。你可以在这里找到一些有用的类,如Interval,YearWeek,YearQuarter,等等。