18

如果您可以想象的话,这会在我的软件中造成 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));
                }
        }
}
4

5 回答 5

47

这就是问题:

"dd-MMM-YYYY"

YYYY是周年,而不是日历年。你想要yyyy

2012 日历年的最后两天在 2013 年周的第一周。您通常应该只将周年与“周年”说明符 ( w) 一起使用。

于 2013-02-07T16:17:48.823 回答
7

我假设您正在使用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
于 2013-02-07T16:21:51.267 回答
3

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 的使用。

于 2013-02-07T16:21:02.587 回答
3

为了完整起见,这是使用的现代答案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)之前的几年里只会有区别。
于 2017-06-08T14:25:51.013 回答
2

您需要使用小写的 y 作为年份。试试这个:

   SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
于 2013-02-07T16:21:04.257 回答