有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java日历。加错年份

我的程序获取当前日期,然后在循环中,在该日期上加上一周,并打印出新日期。比如:

Calendar cal = Calendar.getInstance();
for (int i=0; i < 52; i++) {
cal.add(Calendar.DATE, 7);
// print date out
}

add方法的工作方式与我预期的一样,直到12月30日,从2012年跳到2013年

因此,使用今天的2012年4月16日,我测试了几个不同的输入:

this - cal.add(Calendar.DATE, 38*7);
yields- "date:1/7/2013"
this - cal.add(Calendar.DATE, 37*7);
yields- "date:12/31/2013"
this - cal.add(Calendar.DATE, 37*7-1);
yields- "date:12/30/2013"
this - cal.add(Calendar.DATE, 37*7-2);
yields- "date:12/29/2012"

所以我注意到这一年在12月30日和31日之前是正确的,然后当它回到1月份时,它会再次自我修正。这有什么原因吗?这和2012年是闰年有什么关系吗?还是我误解了加法


共 (3) 个答案

  1. # 1 楼答案

    tl;博士

    使用现代java。时间类,而不是可怕的遗留类,如Calendar

    LocalDate                      // Represent a date-only value with `LocalDate`, without time-of-day and without time zone.
    .now(                          // Capture the current date.
        ZoneId.systemDefault()     // Specify your desired/expected time zone explicitly.
    )                              // Returns a `LocalDate` object.
    .plusWeeks( 1 )                // Add a week, producing a new `LocalDate` object with values based on the original, per the immutable objects pattern.
    .toString()                    // Generate text representing this date value in standard ISO 8601 format of YYYY-MM-DD.
    

    2019-01-23

    爪哇。时间

    现代方法使用java。时间课程

    {}和{}类很糟糕,设计得很糟糕,有缺陷。避开它们。现在被ZonedDateTime类特别替换

    LocalDate

    {a1}类表示一个只包含日期的值,不包含一天中的时间,也不包含time zoneoffset-from-UTC

    时区对于确定日期至关重要。在任何一个特定的时刻,世界各地的日期都因地区而异。例如,在Paris France午夜后几分钟是新的一天,而在Montréal Québec仍然是“昨天”

    如果未指定时区,JVM将隐式应用其当前默认时区。该默认值可能在运行时(!)期间change at any moment,因此,您的结果可能会有所不同。最好将所需/预期时区明确指定为参数

    Continent/Region的格式指定一个proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,如ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)

    ZoneId z = ZoneId.of( "America/Montreal" ) ;  
    LocalDate today = LocalDate.now( z ) ;
    

    要以标准ISO 8601格式生成表示该日期值的文本,只需调用toString

    String output = today.toString() ;
    

    日期数学很简单,有各种{}&minus…方法

    LocalDate weekLater = today.plusWeeks( 1 ) ;
    

    您还可以将时间跨度定义为PeriodDuration。然后再加上

    Period p = Period.ofWeeks( 1 ) ;
    LocalDate weekLater = today.plus( p ) ;
    

    你的榜样

    让我们测试一下您的示例日期

    LocalDate ld = LocalDate.of( 2012 , Month.APRIL , 16 ) ;
    
    Period period38Weeks = Period.ofWeeks( 38 ) ;
    Period period37Weeks = Period.ofWeeks( 37 ) ;
    Period period37WeeksLess1Days = period37Weeks.minusDays( 1 ) ;
    Period period37WeeksLess2Days = period37Weeks.minusDays( 2 ) ;
    
    LocalDate later_38 = ld.plus( period38Weeks ) ;
    LocalDate later_37 = ld.plus( period37Weeks ) ;
    LocalDate later_37_1 = ld.plus( period37WeeksLess1Days ) ;
    LocalDate later_37_2 = ld.plus( period37WeeksLess2Days ) ;
    

    运行code live at IdeOne.com。没问题。第38周是2013年,第37周是2012年

    later_38.toString(): 2013-01-07

    later_37.toString(): 2012-12-31

    later_37_1.toString(): 2012-12-30

    later_37_2.toString(): 2012-12-29


    关于java。时间

    java.time框架内置于Java8和更高版本中。这些类取代了麻烦的旧legacy日期时间类,如^{}^{}、&^{}

    现在位于maintenance modeJoda-Time项目建议迁移到java.time

    要了解更多信息,请参阅Oracle Tutorial。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310

    您可以交换java。时间对象直接与数据库连接。使用符合JDBC 4.2或更高版本的JDBC driver。不需要字符串,也不需要java.sql.*

    在哪里可以获得java。时间课

    ThreeTen-Extra项目扩展了java。额外上课的时间。这个项目是将来可能添加到java的一个试验场。时间您可以在这里找到一些有用的类,例如^{}^{}^{}more

  2. # 2 楼答案

    应该是:

    cal.add(Calendar.DAY_OF_YEAR, 7);
    

    Calendar.DATECalendar.DAY_OF_MONTH相同

  3. # 3 楼答案

    您是否使用SimpleDateFormat打印日期并使用YYYY生成年份?如果是这样,那就是问题所在。因为YYYY生成的是周年而不是日历年。2012年12月30日是2013年的第1个日历周,因此2013年是第1个日历周。要获取日历年,请在SimpleDateFormat格式字符串中使用yyyy

    https://bugs.openjdk.java.net/browse/JDK-8194625