首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java Calendar.add给出了错误的年份

Java Calendar.add给出了错误的年份
EN

Stack Overflow用户
提问于 2012-04-17 04:22:31
回答 3查看 1.8K关注 0票数 6

我的程序获取当前日期,然后在循环中向该日期添加一周,并打印出新的日期。类似于:

代码语言:javascript
运行
复制
Calendar cal = Calendar.getInstance();
for (int i=0; i < 52; i++) {
cal.add(Calendar.DATE, 7);
// print date out
}

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

因此,使用今天的日期4/16/2012,我测试了一些不同的输入:

代码语言:javascript
运行
复制
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日和12月31日,这一年是正确的,然后当它回到1月份时,它又进行了自我修正。它这样做有什么原因吗?这与2012年是闰年有什么关系,还是我误解了add方法

EN

回答 3

Stack Overflow用户

发布于 2019-01-07 02:09:31

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

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

票数 6
EN

Stack Overflow用户

发布于 2019-01-08 07:06:07

tl;dr

使用现代的java.time类,而不是像Calendar这样可怕的遗留类。

代码语言:javascript
运行
复制
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.time

现代方法使用java.time类。

CalendarGregorianCalendar类很糟糕,设计得很糟糕,有缺陷。避开他们。现在专门被ZonedDateTime类所取代。

LocalDate

LocalDate类表示不带时间和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,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

代码语言:javascript
运行
复制
ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

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

代码语言:javascript
运行
复制
String output = today.toString() ;

日期数学很简单,有各种plus…minus…方法。

代码语言:javascript
运行
复制
LocalDate weekLater = today.plusWeeks( 1 ) ;

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

代码语言:javascript
运行
复制
Period p = Period.ofWeeks( 1 ) ;
LocalDate weekLater = today.plus( p ) ;

你的例子

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

代码语言:javascript
运行
复制
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.time

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

现在在maintenance mode中的项目建议迁移到java.time类。

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

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

从哪里获取java.time类?

  • ,、、和更高版本-标准Java API的一部分,具有捆绑的实现。
    • Java9添加了一些次要功能和fixes.

  • 和.

中的

  • 大多数java.time功能已向后移植到Java6和7

    • 更高版本的Android捆绑实现的java.time类。
    • 对于较早的Android (<26),项目适配 (如上所述)。请参阅.

项目使用额外的类扩展了java.time。这个项目是未来可能添加到java.time中的试验场。您可能会在这里找到一些有用的类,如IntervalYearWeekYearQuartermore

票数 1
EN

Stack Overflow用户

发布于 2012-04-17 04:27:54

它应该是:

代码语言:javascript
运行
复制
cal.add(Calendar.DAY_OF_YEAR, 7);

Calendar.DATECalendar.DAY_OF_MONTH相同。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10181138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档