Java日期年计算按年份停止两天

Java日期年计算按年份停止两天,java,date,calendar,simpledateformat,Java,Date,Calendar,Simpledateformat,如果你能想象的话,这在我的软件中造成了一个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日期实用程序的哪一部分会导致这样的错误 代码(因为测试太小,我包含

如果你能想象的话,这在我的软件中造成了一个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;
导入java.util.Date;
导入java.text.simpleDataFormat;
公共类日期{
私有静态字符串getFormattedBackscanStartTime(整数天){
SimpleDataFormat dateFormat=新的SimpleDataFormat(“dd MMM YYYY”);
日历工作日期=Calendar.getInstance();
workingDate.add(Calendar.DATE,-1*天);
String formattedStartTime=dateFormat.format(workingDate.getTime());
返回格式化的开始时间;
}
公共静态void main(字符串参数[]){
对于(int i=35;i<45;i++){
System.out.println(getFormattedBackscanStartTime(i));
}
}
}
这就是问题所在:

"dd-MMM-YYYY"
YYYY
是周年,而不是日历年。您想要的是
yyyy


2012日历年的最后两天是2013年第一周。通常应仅将周-年与“年中的周”说明符(
w
)一起使用。

问题在于日期格式字符串-年应为
yyyy
而不是
yyyy

Y -> week-year
y -> year
如果在循环的每个迭代中打印
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");

我假设您使用的是
Java1.7

上面的代码片段将不适用于
java 1.6
,因为
SimpleDataFormat(“dd-MMM-YYYY”)
将引发
java.lang.IllegalArgumentException
(yyyyy在
java 1.6
中不可用)

您需要使用
yyyy
而不是
yyy

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

为了完整起见,下面是使用
LocalDate
(由Basil Bourque在评论中推荐)的现代答案

需要注意的几点:

  • 为格式化程序提供一个显式的区域设置,以控制输出的语言。即使您只是传递了
    Locale.getDefault()
    ,您也在告诉读者您已经考虑了Locale并做出了决定
  • 类似地,为
    LocalDate.now()
    指定一个明确的时区,告诉读者您已经做出了决定(例如
    ZoneId.of(“美国/纽约”)
    用于特定时区;
    ZoneId.systemDefault()
    用于JVM的当前时区设置)
  • 我发现代码比使用老式的
    Calendar
    类的代码更简单、更直接。这对于较新的类是典型的
  • 我已经使用
    uuu
    一年了
    yyyy
    (小写)也能起作用,在普通纪元(又名公元前)之前的几年里只会有不同

我想你会从中受益。请注意,
Calendar
&
SimpleDateFormat
类现在已启用。被班级取代了。现代方法使用
LocalDate
ZoneId
DateTimeFormatter
类。请将
LocalDate分开。现在,
行分成单独的命令,以便您可以看到正在使用的类。以及。。。下面是一种从
java.util.Date
转换的方法:如果您使用的库依赖于旧日期,则不确定这是否有意义。
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