【问题标题】:Cannot create a Date object representing December 29, 2019无法创建表示 2019 年 12 月 29 日的 Date 对象
【发布时间】:2020-04-10 04:13:29
【问题描述】:

我希望这不是 JDK 错误,或者我很想兑现我所有的银行账户,然后把它扔到床垫里...... 这是代码。请注意,将日期设置为 12 月 29 日会立即将年份滚动到 2020 年。此外,toString() 输出显示 Calendar 似乎认为周数为“1”。

import java.util.*; // headers MUST be above the first class
import java.text.*;

public class JDKCalendarBug {

    public static void main(String[] args) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd-YYYY kk:mm");
        Calendar cal = java.util.Calendar.getInstance(TimeZone
                .getTimeZone("EST"));
        cal.clear();
        cal.set(Calendar.YEAR, 2019);
        cal.set(Calendar.MONTH, Calendar.DECEMBER);

        cal.set(Calendar.DAY_OF_MONTH, 26);
        Date t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

        cal.set(Calendar.DAY_OF_MONTH, 27);
        t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

        cal.set(Calendar.DAY_OF_MONTH, 28);
        t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

        cal.set(Calendar.DAY_OF_MONTH, 29);
        t = cal.getTime();
        System.out.print("\n"+sdf.format(t));
        System.out.print("\n"+cal.toString());

    }

}

输出:

12-26-2019 24:00 java.util.GregorianCalendar[time=1577336400000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false ,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=2019,MONTH=11,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=26,DAY_OF_YEAR=?,DAY_OF_WEEK=?, DAY_OF_WEEK_IN_MONTH=?,AM_PM=?,HOUR=?,HOUR_OF_DAY=?,MINUTE=?,SECOND=?,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]

2019 年 12 月 27 日 24:00 java.util.GregorianCalendar[time=1577422800000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false ,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=52,WEEK_OF_MONTH=4,DAY_OF_MONTH=27,DAY_OF_YEAR=361,DAY_OF_WEEK=6, DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=0] 2019 年 12 月 28 日 24:00 java.util.GregorianCalendar[time=1577509200000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false ,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=52,WEEK_OF_MONTH=4,DAY_OF_MONTH=28,DAY_OF_YEAR=362,DAY_OF_WEEK=7, DAY_OF_WEEK_IN_MONTH=4,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=0]

12-29-2020 24:00 java.util.GregorianCalendar[time=1577595600000,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="EST",offset=-18000000,dstSavings=0,useDaylight=false ,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=5,DAY_OF_MONTH=29,DAY_OF_YEAR=363,DAY_OF_WEEK=1, DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=-18000000,DST_OFFSET=0]

【问题讨论】:

  • 你有关于你的 JDK 和你的区域设置的信息吗?根据您的语言环境,一年中最后一周的周数可以是 1 或 52。您的语言环境也决定了 12 月 29 日的星期数
  • jre1.8.0_231:与 Eclipse 一起打包。按照您的指示,我使用“Locale.US”重新运行了代码,但得到了相同的结果。谢谢你的回复,弗雷德!
  • 我建议你不要使用CalendarDateTimeZoneSimpleDateFormat。这些类设计不良且过时,尤其是最后一个以麻烦着称。而是使用ZoneIdZonedDateTimeDateTimeFormatter,均来自java.time, the modern Java date and time API

标签: java.util.date java.util.calendar


【解决方案1】:

问题在于SimpleDateFormat。如果您将格式字符串更改为小写ys,则日期格式正确为12-29-2019 24:00

new SimpleDateFormat("MM-dd-yyyy kk:mm")

Y 对应于“周年”,与“年”不同,并非所有日历都始终支持。根据JavaDocs

如果指定了周年“Y”并且日历不支持任何 周年,则使用日历年 ('y')。的支持 周年可以通过调用来测试 getCalendar().isWeekDateSupported()。

在这种情况下,支持“周年”,因为底层 Calendar 实现是 GregorianCalendar。据其JavaDocs

一周年与 WEEK_OF_YEAR 周期同步。之间的所有星期 第一周和最后一周(含)具有相同的周年值。 因此,一周年的第一天和最后一天可能有不同的 日历年值。

【讨论】:

  • yyyy 是日历年,YYYY 是日期的周数的年份。在一年的第一周和最后一周,这两个可能不同
  • 你说得对,我查看的是较旧的 JavaDocs,而 Y 不是受支持的符号,这导致了我的困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
  • 2012-09-24
  • 2013-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多