无法创建表示 2019 年 12 月 29 日的日期对象
Cannot create a Date object representing December 29, 2019
我希望这不是 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=?]
12-27-2019 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] 12-28-2019 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]
问题出在 SimpleDateFormat
。如果您将格式字符串更改为小写 y
s,则日期格式正确为 12-29-2019 24:00
new SimpleDateFormat("MM-dd-yyyy kk:mm")
Y
对应于 "Week Year",它与 "Year" 不同,并非所有日历都支持。根据 JavaDocs:
If week year 'Y' is specified and the calendar doesn't support any
week years, the calendar year ('y') is used instead. The support of
week years can be tested with a call to
getCalendar().isWeekDateSupported().
在这种情况下,支持 "week year",因为底层 Calendar
实现是 GregorianCalendar
。根据其 JavaDocs:
A week year is in sync with a WEEK_OF_YEAR cycle. All weeks between
the first and last weeks (inclusive) have the same week year value.
Therefore, the first and last days of a week year may have different
calendar year values.
我希望这不是 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=?]
12-27-2019 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] 12-28-2019 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]
问题出在 SimpleDateFormat
。如果您将格式字符串更改为小写 y
s,则日期格式正确为 12-29-2019 24:00
new SimpleDateFormat("MM-dd-yyyy kk:mm")
Y
对应于 "Week Year",它与 "Year" 不同,并非所有日历都支持。根据 JavaDocs:
If week year 'Y' is specified and the calendar doesn't support any week years, the calendar year ('y') is used instead. The support of week years can be tested with a call to getCalendar().isWeekDateSupported().
在这种情况下,支持 "week year",因为底层 Calendar
实现是 GregorianCalendar
。根据其 JavaDocs:
A week year is in sync with a WEEK_OF_YEAR cycle. All weeks between the first and last weeks (inclusive) have the same week year value. Therefore, the first and last days of a week year may have different calendar year values.