Java日期年度计算按年计算,为期两天
如果你能想象的话,这会在我的软件中引起Y2K风格的错误。 奇怪的是,一年的计算只发生在一年中的两天,我不太确定如何排除故障。
输出:
03-Jan-2013 02-Jan-2013 01-Jan-2013 31-Dec-2013 ** strange 30-Dec-2013 ** strange 29-Dec-2012 28-Dec-2012 27-Dec-2012 26-Dec-2012 25-Dec-2012
我不确定Java日期实用程序的哪一部分可能导致此类错误。
代码(因为测试很小,我包括一个完整的工作程序):
import java.util.Calendar; import java.util.Date; import java.text.SimpleDateFormat; public class DateT { private static String getFormattedBackscanStartTime(int days) { SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-YYYY"); Calendar workingDate = Calendar.getInstance(); workingDate.add(Calendar.DATE, -1 * days); String formattedStartTime = dateFormat.format(workingDate.getTime()); return formattedStartTime; } public static void main(String args[]) { for(int i = 35; i < 45; i++) { System.out.println(getFormattedBackscanStartTime(i)); } } }
这就是问题:
"dd-MMM-YYYY"
YYYY
是周年,而不是日历年。 你想要yyyy
。
2012日历年的最后两天是在2013年的第一周。您通常只应将周年与“一年中的一周”说明符( w
)结合使用。
我假设你使用的是java 1.7
。
上面的代码片段不适用于java 1.6
因为SimpleDateFormat("dd-MMM-YYYY")
将引发java.lang.IllegalArgumentException
(YYYY在java 1.6
不可用)
你需要使用yyyy
而不是YYYY
。
Y -> week-year y -> year
这里
编辑
与yyyy
:
$ java DateT 03-Jan-2013 02-Jan-2013 01-Jan-2013 31-Dec-2012 30-Dec-2012 29-Dec-2012 28-Dec-2012 27-Dec-2012 26-Dec-2012 25-Dec-2012
问题在于你的日期格式字符串 – 年份应该是yyyy
而不是YYYY
。
如果在循环的每次迭代中打印workingDate.getTime()
的值,您将看到它具有预期值:
Thu Jan 03 11:19:33 EST 2013 Wed Jan 02 11:19:33 EST 2013 Tue Jan 01 11:19:33 EST 2013 Mon Dec 31 11:19:33 EST 2012 Sun Dec 30 11:19:33 EST 2012 Sat Dec 29 11:19:33 EST 2012 Fri Dec 28 11:19:33 EST 2012 Thu Dec 27 11:19:33 EST 2012 Wed Dec 26 11:19:33 EST 2012 Tue Dec 25 11:19:33 EST 2012
因此问题在于SimpleDateFormat的用法。
你需要使用年份小写y。 尝试这个:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
为了完整起见,这里是使用LocalDate
的现代答案(由Basil Bourque在评论中推荐)。
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Locale; public class DateT { private static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MMM-uuuu", Locale.US); private static String getFormattedBackscanStartTime(int days) { return LocalDate.now(ZoneId.systemDefault()).minusDays(days).format(dateFormatter); } public static void main(String args[]) { for(int i = 155; i < 165; i++) { System.out.println(getFormattedBackscanStartTime(i)); } } }
我今天跑了这个
04-Jan-2017 03-Jan-2017 02-Jan-2017 01-Jan-2017 31-Dec-2016 30-Dec-2016 29-Dec-2016 28-Dec-2016 27-Dec-2016 26-Dec-2016
有几点需要注意:
- 为您的格式化程序提供明确的区域设置以控制输出的语言。 即使您只是传递
Locale.getDefault()
您也会告诉读者您已经考虑过区域设置并做出决定。 - 同样地给
LocalDate.now()
一个明确的时区告诉读者你已经做出决定(例如ZoneId.of("America/New_York")
用于特定时区;ZoneId.systemDefault()
用于JVM当前时区设定)。 - 我发现代码比使用旧式
Calendar
类的代码更简单,更直接。 这对于较新的类来说是典型的。 - 我一年都用过
uuuu
。yyyy
(小写)也有效,在共同时代(AKA BC)之前几年只会有差异。