我想计算考虑闰年的确切年龄。我在网上研究过,找到了一些教程,但是闰年确切地计算了日期的差异,似乎是[1]中的那个:https://answers.yahoo.com/question/index?qid=20110629162003AAof4mT这个链接,这是“最佳答案”。我分析了代码但有两个问题:
1)为什么在“计算天数生活”部分下面写下“days = days + 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 :(得分:3)
执行此操作的正确方法是使用Period
包中的LocalDate
和java.time
类。但是,您似乎正在尝试为自己重新计算。
我建议这样做的方法是编写一个类,让您计算给定日期的“日期编号” - 即指定日期和过去某个任意日期之间的天数。然后,当您想要查找两个指定日期之间的天数时,您可以使用两个日期计算“日期数”,然后减去它们。
我在这里完成了这个,纯粹的格里高利历。在Gregorian切换之前这个类是没有好处的 - 我没有尝试构建历史上准确的Julian / Gregorian混合日历,例如JDK提供的。并且它计算日期的过去的任意日期是12BC,12BC。当然,这个日期并不是格里高利历的一部分;但对于我们这里的目的,没关系。
由于您不太可能在格里高利转换之前遇到任何日期,因此本课程应该足以满足您的目的。对于生产代码,我仍然建议使用Period
和LocalDate
类而不是此类。这就是这里所以你可以看到如何进行计算。
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)
回答问题1。 你每年增加1天的每一年。作者使用这些知识,首先计算如果所有年份都正常,已经过了多少天:
days = days + (365 * yearsLived);
然后添加了一些leapyears(记住1个leapyear = 1个额外的一天)。
关于第二个问题: 代码寻找birthDate(读取:startDate)和dueDate(读取endDate)之间的区别。因此,要计算开始和结束之间的差异,您必须为这些整数提供日期输入,代码将完成剩下的工作。
答案 2 :(得分:1)
long ageInDays =
ChronoUnit.DAYS.between(
LocalDate.of( 1960 , 1 , 2 ) ,
LocalDate.now( ZoneId.of( "America/Montreal" ) )
);
如果您正在探索该算法,请参阅correct Answer by David Wallace。
如果您正在为高效工作而这样做,那么不滚动您自己的日期时间类。避免旧的日期时间类(.Date
,.Calendar
等)并使用java.time类。
ChronoUnit
枚举具有惊人的效用,包括计算经过时间。在我们的案例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 8及更高版本中。这些类取代了麻烦的旧日期时间类,例如java.util.Date
,.Calendar
和&amp; java.text.SimpleDateFormat
。
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。
大部分java.time功能都被反向移植到Java 6&amp; ThreeTen-Backport中的7,并进一步适应Android中的ThreeTenABP(见How to use…)。
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
等。