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年是闰年有什么关系吗?还是我误解了加法
# 1 楼答案
tl;博士
使用现代java。时间类,而不是可怕的遗留类,如
Calendar
爪哇。时间
现代方法使用java。时间课程
{}和{}类很糟糕,设计得很糟糕,有缺陷。避开它们。现在被
ZonedDateTime
类特别替换LocalDate
{a1}类表示一个只包含日期的值,不包含一天中的时间,也不包含time zone或offset-from-UTC
时区对于确定日期至关重要。在任何一个特定的时刻,世界各地的日期都因地区而异。例如,在Paris France午夜后几分钟是新的一天,而在Montréal Québec仍然是“昨天”
如果未指定时区,JVM将隐式应用其当前默认时区。该默认值可能在运行时(!)期间change at any moment,因此,您的结果可能会有所不同。最好将所需/预期时区明确指定为参数
以
Continent/Region
的格式指定一个proper time zone name,例如America/Montreal
、Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4个字母的缩写,如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)要以标准ISO 8601格式生成表示该日期值的文本,只需调用
toString
日期数学很简单,有各种{}&
minus…
方法您还可以将时间跨度定义为
Period
或Duration
。然后再加上你的榜样
让我们测试一下您的示例日期
运行code live at IdeOne.com。没问题。第38周是2013年,第37周是2012年
关于java。时间
java.time框架内置于Java8和更高版本中。这些类取代了麻烦的旧legacy日期时间类,如^{} 、^{} 、&^{}
现在位于maintenance mode的Joda-Time项目建议迁移到java.time类
要了解更多信息,请参阅Oracle Tutorial。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310
您可以交换java。时间对象直接与数据库连接。使用符合JDBC 4.2或更高版本的JDBC driver。不需要字符串,也不需要
java.sql.*
类在哪里可以获得java。时间课
ThreeTen-Extra项目扩展了java。额外上课的时间。这个项目是将来可能添加到java的一个试验场。时间您可以在这里找到一些有用的类,例如^{} 、^{} 、^{} 和more
# 2 楼答案
应该是:
Calendar.DATE
与Calendar.DAY_OF_MONTH
相同# 3 楼答案
您是否使用
SimpleDateFormat
打印日期并使用YYYY
生成年份?如果是这样,那就是问题所在。因为YYYY
生成的是周年而不是日历年。2012年12月30日是2013年的第1个日历周,因此2013年是第1个日历周。要获取日历年,请在SimpleDateFormat
格式字符串中使用yyyy
见https://bugs.openjdk.java.net/browse/JDK-8194625