Using GregorianCalendar with SimpleDateFormat
所以我一直在绞尽脑汁做这个(应该是)简单的练习,让程序把一个日期字符串转换成一个公历日历对象,格式化它,并在完成后将它作为字符串返回。
这是一个程序的最后一点,它从一个文件中接收一堆文本,将其分解成单独的记录,然后将这些记录分解成单独的数据块,并将它们分配给一个Person对象。
我已经在多个地方检查了代码,代码执行了它应该执行的操作,直到我调用了格式函数,它抛出了IllegalArgumentException。GergorianCalendar对象被分配了它应该被分配的值(尽管再次打印它是一个完整的另一个故事,如下所示…),但是格式将不接受对象进行格式化。
不幸的是,老师不太确定如何使用公历日历和simpledateformat(还指派我们与他们合作),并说"只需谷歌它"…我试过了,但没发现有什么帮助。
到目前为止,我得到的代码是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class DateUtil { public static GregorianCalendar convertFromDMY(String dd_mm_yy) throws ParseException{ // this actually works, got rid of the original code idea String[] splitDate = dd_mm_yy.split("-"); int days = Integer.parseInt(splitDate[0]); int month = Integer.parseInt(splitDate[1]); int year = Integer.parseInt(splitDate[2]); // dates are going in right, checked in print statement, // but the object is not getting formatted... GregorianCalendar dateConverted = new GregorianCalendar(year, month, days); format(dateConverted); return dateConverted; } public static String format(GregorianCalendar date){ SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy"); String dateFormatted = fmt.format(date); return dateFormatted; } } |
我得到的错误是:
1 2 3 4 5 6 7 8 | Exception in thread"main" java.lang.IllegalArgumentException: Cannot format given Object >as a Date at java.text.DateFormat.format(DateFormat.java:281) at java.text.Format.format(Format.java:140) at lab2.DateUtil.format(DateUtil.java:26) at lab2.DateUtil.convertFromDMY(DateUtil.java:19) at lab2.Lab2.createStudent(Lab2.java:75) at lab2.Lab2.main(Lab2.java:34) |
还有一件事,我是不是在使用公历??当我打印出该对象的值时(应该得到正确的日期?)我明白这一点:
java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Vancouver",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=189,lastRule=java.util.SimpleTimeZone[id=America/Vancouver,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=1985,MONTH=4,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=22,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]
月份值的年、月和日都是正确的,因为它们是我在创建它时传递给它的数字。
想法,建议,我是不是很亲近?
编辑
原始问题已经解决了(谢谢你,混蛋!)但我仍然无法正确打印,因为这两个功能没有链接,并且要求从Person对象中打印出一个Gregoricalendar日期值(因为birthdate是Gregoricalendar)。
更新代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class DateUtil { static SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy"); public static GregorianCalendar convertFromDMY(String dd_mm_yy) throws ParseException{ // this actually works, got rid of the original code idea String[] splitDate = dd_mm_yy.split("-"); int days = Integer.parseInt(splitDate[0]); int month = (Integer.parseInt(splitDate[1]) - 1); int year = Integer.parseInt(splitDate[2]); // dates go in properly GregorianCalendar dateConverted = new GregorianCalendar(year, month, days); String finalDate = format(dateConverted); return ; } public static String format(GregorianCalendar date) throws ParseException{ fmt.setCalendar(date); String dateFormatted = fmt.format(date.getTime()); System.out.println(dateFormatted); return dateFormatted; } } |
最后编辑
好吧,看起来我是个白痴,不需要将两个dateutil函数链接在一起,而是串联使用它们。首先,将生日转换为公历日历并存储在Person对象中。然后在打印语句中,只需告诉程序在打印时格式化该日期。问题解决了。现在所有的工作都是按照规范进行的,我觉得这太愚蠢了,因为在最后一天,我就像一条鱼一样在水里挣扎着,和dateutil一起努力让他们同时工作。
谢谢你的帮助,让我们的约会顺利进行!
1 2 3 4 5 6 | public static String format(GregorianCalendar calendar){ SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy"); fmt.setCalendar(calendar); String dateFormatted = fmt.format(calendar.getTime()); return dateFormatted; } |
还要注意,月份从0开始,所以您可能是指:
1 |
为什么会这样复杂?
1 2 3 4 5 6 7 8 | public static GregorianCalendar convertFromDMY(String dd_mm_yy) throws ParseException { SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy"); Date date = fmt.parse(dd_mm_yy); GregorianCalendar cal = GregorianCalendar.getInstance(); cal.setTime(date); return cal; } |
simpledateformat,顾名思义,格式化日期。不是日历。因此,如果要使用simpledateformat格式化公历日历,必须首先将日历转换为日期:
1 | dateFormat.format(calendar.getTime()); |
您看到的是日历的toString()表示。它的预期用途是调试。它不用于在GUI中显示日期。为此,请使用(简单)日期格式。
最后,要从字符串转换为日期,您还应该使用(简单的)日期格式(它的
我的建议是:谷歌不是解决办法。阅读API文档是您需要做的。
DR
1 2 3 4 |
避免传统日期时间类
问题和其他答案现在已经过时了,使用了麻烦的旧日期时间类,这些类现在是遗留的,被java.time类所取代。
使用JavaTimes你似乎只处理日期价值观。所以不要使用日期时间类。改为使用
指定一个
解析字符串。
1 2 3 |
生成字符串。
1 |
如果您得到的是数字而不是文本,则使用
1 | LocalDate ld = LocalDate.of( 2017 , 3 , 23 ); // ( year , month 1-12 , day-of-month ) |
请在ideone.com上查看此代码。
input: 23-Mar-2017
ld.toString(): 2017-03-23
output: 23-Mar-2017
关于JavaTimes
JavaTimeFr框架是在Java 8和之后构建的。这些类取代了麻烦的旧遗留日期时间类,如
现在处于维护模式的joda time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程。以及搜索堆栈溢出以获得许多示例和解释。规格为JSR 310。
使用符合JDBC4.2或更高版本的JDBC驱动程序,可以直接与数据库交换java.time对象。不需要字符串,也不需要Java.SQL.*类。
在哪里获取java.time类?
- Java SE 8、Java SE 9及以后
- 内置的。
- 标准JAVA API的一部分与捆绑实现。
- Java 9添加了一些小的特性和修复。
- Java SE 6和Java SE 7
- 大部分JavaTimeActudio都被移植到TealEnter后端的Java 6和7中。
- 安卓
- java.time类的Android包实现的更高版本。
- 对于早期的android,threetenabp项目适应threeten backport(如上所述)。看看如何使用三连珠……
threeten额外项目使用额外的类扩展java.time。这个项目是将来可能添加到java.time的一个试验场。您可以在这里找到一些有用的类,如
你在这里输入的是两位数的年份。第一世纪。公历始于16世纪。我想,你今年应该再增加2000个。
新公历日历函数中的月份(年、月、日)以0为基础。从那里的月份中减去1。
将第二个函数的主体更改为:
1 2 3 4 5 6 7 8 9 | String dateFormatted = null; SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy"); try { dateFormatted = fmt.format(date); } catch ( IllegalArgumentException e){ System.out.println(e.getMessage()); } return dateFormatted; |
调试之后,您将看到,仅仅是gregoricalendar不能是fmt.format()的参数;
实际上,没有人需要将公历作为输出,即使要求您返回"字符串"。
将格式函数的头改为
做出适当的改变。