【问题标题】:Java calculate days in year, or between two datesJava 计算一年中的天数,或两个日期之间的天数
【发布时间】:2023-03-29 13:40:02
【问题描述】:

在任何本机 Java 类中是否有一种方法可以计算特定年份的天数?例如,它是 Leap year(366 天)还是正常年份(365 天)?

还是需要我自己写?

我正在计算两个日期之间的天数,例如,距离我的生日还有多少天。我想考虑到闰年的 2 月 29 日。除了 29 号,我都完成了。

【问题讨论】:

    标签: java calendar leap-year


    【解决方案1】:

    另一种方法是向Calendar 类询问给定年份的实际最大天数:

    Calendar cal = Calendar.getInstance();
    cal.setTime(new Date());
    
    int numOfDays = cal.getActualMaximum(Calendar.DAY_OF_YEAR);
    System.out.println(numOfDays);
    

    这将返回 366 表示双分裂年份,365 表示正常年份。

    注意,我使用了getActualMaximum 而不是getMaximum,它总是返回 366。

    【讨论】:

    • @NoodleofDeath 实际上,这个答案在 2014 年的 Java 8 中已经过时了。麻烦的旧日期时间类如 java.util.Datejava.util.Calendarjava.text.SimpleTextFormat 现在是 legacy,被java.time 类取代。见Tutorial by Oracle
    • @BasilBourque 我同意,如果可能的话,您应该使用 java.time 类。但是对于我们这些没有奢侈使用 Java 8 的人来说,这个答案并不过时。 OP 指的是 java.util.Calendar 和 java.util.Date,这个答案对我们许多人来说仍然非常适用。这就是我一直在寻找的答案。
    • @SamuraiSoul java.time 的大部分功能都在ThreeTen-Backport 项目中向后移植到Java 6 和Java 7。在ThreeTenABP 项目中进一步适用于Android。所以没有理由为可怜的遗产Date/Calendar/等而受苦。类。详情请见my Answer
    【解决方案2】:

    tl;博士

    Year.of( 2015 ).length()
    

    ……和……

    Year.isLeap( 2015 )
    

    java.time.Year

    在 Java 8 及更高版本中,我们有 java.time package。 (Tutorial)

    length

    Year 类表示单个年份值。你可以询问它的长度。

    int daysInYear = Year.of( 2015 ).length();
    

    isLeap

    您也可以询问某年是否为闰年。

    Boolean isLeapYear = Year.isLeap( 2015 );
    

    例如,使用Java的ternary operator获取一年中的天数,如:

    minVal = (a

    在我们的例子中,我们需要一年中的天数。非闰年是 365,闰年是 366。

    int daysInYear = ( Year.isLeap( 2015 ) ) ? 366 : 365 ;
    

    一年中的某一天

    您可以获得日期的年份编号。这个数字从 1 到 365,或闰年为 366。

    int dayOfYear = LocalDate.now( ZoneId.of( "America/Montreal" ).getDayOfYear() ;
    

    换个方向,获取一年中某一天的日期。

    Year.now( ZoneId.of( "America/Montreal" ) ).atDay( 159 ) ;
    

    在处理一年时,您可以通过比较这些日期数来确定经过的天数。但是有一种更简单的方法;继续阅读。

    经过的天数

    使用ChronoUnit 枚举来计算经过的天数。

    LocalDate start = LocalDate.of( 2017 , 2 , 23 ) ;
    LocalDate stop = LocalDate.of( 2017 , 3 , 11 ) ;
    int daysBetween = ChronoUnit.DAYS.between( start , stop );
    

    自动处理Leap Year


    关于java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

    Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    从哪里获取 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

    • 这很好,但不要“调整”我的英语。
    • 你,先生,赢得奖牌?谢谢!
    【解决方案3】:

    GregorianCalendar 标准类有一个isLeapyear() 方法。如果你得到的只是一个年份数字(比如2008),那么使用this构造函数构造一个日期,然后检查isLeapYear()方法。

    【讨论】:

    • 呸。愚蠢的 Java 及其适用于一切的库。 :-P (+1)
    • 是的,使用库作为日期很糟糕。通过你自己的闰年、不同月份、闰秒、加法数学的测试是……没关系的方法。 :)
    • 但是,您可以轻松地将“MyCalendar”定义为新标准,它会神奇地通过所有相关测试。
    • @Autocracy:只有内置的日期库很烂。询问 Jon Skeet。
    • 是的,我是在深夜写的,我忘了提到我正在使用 Calendar 类和 Calendar.get(Calendar.DAY_OF_YEAR) 来计算差异。我只有一个疑问 - 如果我这样做,例如 Calendar.add(Calendar.MONTH, 14) 是否会将结果年份设置为闰年?还是所有年份都只有 365 天?
    【解决方案4】:

    JAVA 8

    一年中的天数:

    LocalDate d = LocalDate.parse("2020-12-31");                   // import java.time.LocalDate;
    return d.lengthOfYear();                                       // 366
    

    离我生日还有几天:

    LocalDate birth = LocalDate.parse("2000-02-29");
    LocalDate today = LocalDate.now();                             // or pass a timezone as the parameter
    
    LocalDate thisYearBirthday = birth.withYear(today.getYear());  // it gives Feb 28 if the birth was on Feb 29, but the year is not leap.
    LocalDate nextBirthday = today.isAfter(thisYearBirthday)
        ? birth.withYear(today.getYear() + 1)
        : thisYearBirthday;
    
    return DAYS.between(today, nextBirthday);                      // import static java.time.temporal.ChronoUnit.DAYS;
    

    【讨论】:

    • OP 说“...计算两个日期之间的天数”
    • 你是对的。我已更正并删除了我的评论。我编辑了问题的标题以使其清晰完整。
    【解决方案5】:

    对于日期时间计算,我强烈建议使用JodaTime 库。特别是对于您需要的东西,它将是一个衬里:

    Days.daysBetween(date1, date2).getDays();
    

    我希望这会有所帮助。

    【讨论】:

    • 对仅仅为了做一个简单的计算而实现整个库不感兴趣。
    【解决方案6】:
    【解决方案7】:

    您可以查看the Wikipedia page 以获得一些非常好的伪代码:

    if year modulo 400 is 0
           then is_leap_year
    else if year modulo 100 is 0
           then not_leap_year
    else if year modulo 4 is 0
           then is_leap_year
    else
           not_leap_year
    

    我相信您可以弄清楚如何在 Java 中实现该逻辑。 :-)

    【讨论】:

    • 这看起来像是在重新发明轮子。
    • 是的,同意,这是在我了解 Java 的 GregorianCalendar 类之前。撇开 Java 的许多其他日期/时间问题不谈,这就是这种情况下要走的路!
    • 为什么投反对票?这是查找闰年的“最佳”算法。
    • @Cem Catikkas:这绝对是正确的,但问题是“这是一个有用的答案”。这是一个 Java 问题,所以我可以看到使用 Java 库是一个更好的答案和重新发明轮子是不好的论点。感谢您的支持! :-)
    【解决方案8】:

    Joda 和这个特定的 example 可能最好地解决您的确切用例。

    【讨论】:

      【解决方案9】:

      您可以使用TimeUnit 类。对于您的特定需求,应该这样做:

      public static int daysBetween(Date a, Date b) {
          final long dMs = a.getTime() - b.getTime();
          return TimeUnit.DAYS.convert(dMs, TimeUnit.MILLISECONDS);
      }
      

      老实说,不过,我看不出闰年在这个计算中起到什么作用。也许我错过了你问题的某些方面?

      编辑:愚蠢的我,闰年魔法发生在Date.getTime()。反正你不用这样处理。

      【讨论】:

        猜你喜欢
        • 2021-07-08
        • 1970-01-01
        • 1970-01-01
        • 2013-12-08
        • 1970-01-01
        • 2015-02-26
        • 2019-09-27
        相关资源
        最近更新 更多