将GregorianCalendar与SimpleDateFormat一起使用

因此,我一直在思考这个(应该是)简单的练习,让程序将日期字符串转换为GregorianCalendar对象,格式化它,并在完成时将其作为字符串再次返回。

这是一个程序的最后一点,它从文件中获取文本,将其分解为单个记录,然后将记录分成单独的数据并将它们分配给一个人对象。

我已经在多个地方检查了代码,代码完全按照它应该执行的操作,直到我调用格式函数,这会抛出IllegalArgumentException。 GergorianCalendar对象被赋予它应该被分配的值(虽然打印它是另一个故事,如下所示……),但格式不接受格式化的对象。

不幸的是,导师不太确定如何使用GregorianCalendar和SimpleDateFormat(但指派我们使用它们)并且说“Just Google it”……我试过,我发现没有任何帮助。

我到目前为止的代码是:

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; } } 

我得到的错误是:

线程“main”中的exceptionjava.lang.IllegalArgumentException:无法将给定的Object>格式化为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)
    在lab2.Lab2.main(Lab2.java:34)

还有一件事,我甚至使用GregorianCalendar吗? 当我打印出该对象的值(应该是一个正确的日期?)我得到这个:

java.util.GregorianCalendar中的[时间= ?, areFieldsSet =假,areAllFieldsSet =假,宽松= TRUE,区= sun.util.calendar.ZoneInfo [ID = “美洲/温哥华”,偏移量= -28800000,dstSavings = 3600000,useDaylight =真,过渡= 189,lastRule = java.util.SimpleTimeZone中[ID =美国/温哥华,偏移= -28800000,dstSavings = 3600000,useDaylight =真,startYear = 0,STARTMODE = 3,startMonth = 2,朝九特派= 8, startDayOfWeek = 1,开始时间= 7200000,startTimeMode = 0,endMode = 3,endMonth = 10,endday指定= 1,一个endDayOfWeek = 1,结束时间= 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,微差= ?, ZONE_OFFSET = ?, DST_OFFSET =?]

year,month和day_of_month值都是正确的,因为它们是我传递给它的数字。

思考,建议,我甚至关闭?

编辑

原始问题得到澄清(谢谢assylias!)但我仍然无法正确打印,因为这两个函数没有链接,并且要求是从person对象打印出GregorianCalendar日期值(因为birthdate是GregorianCalendar)。

更新的代码:

 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函数链接在一起,但是串联使用它们。 首先,将birthdate转换为GregorianCalendar并将其存储在person对象中。 然后在print语句中只需告诉程序在打印日期时格式化该日期。 问题解决了。 现在所有的工作都按照规格进行,我感觉很愚蠢,因为我在最后一天左右用水甩掉了鱼,用DateUtil类,试图让它们同时工作。

感谢所有关于正确使用日期的帮助!

SimpleDateFormat#format方法将Date作为参数。 您可以通过调用getTime方法从Calendar获取Date

 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开始,因此您可能意味着:

 int month = Integer.parseInt(splitDate[1]) - 1; 

为什么会出现这样

 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格式化GregorianCalendar,则必须先将日历转换为日期:

 dateFormat.format(calendar.getTime()); 

而你看到的是日历的toString()表示。 它的用途是调试。 它不是用于在GUI中显示日期。 为此,使用(简单)DateFormat。

最后,要从String转换为Date,您还应该使用(Simple)DateFormat(它的parse()方法),而不是像您一样拆分String。 这将为您提供一个Date对象,您可以通过实例化( Calendar.getInstance() )并设置其时间( calendar.setTime() )从Date创建日历。

我的建议是:谷歌搜索不是这里的解决方案。 阅读API文档是您需要做的。

  1. 你这两年的年份。 第一世纪。 格里高利历始于16世纪。 我想,你应该在今年增加2000。

  2. 函数new GregorianCalendar(年,月,日)中的月份为0。 从那里的月份减去1。

  3. 更改第二个函数的主体,使:

      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; 

调试后你会发现简单的GregorianCalendar不能是fmt.format()的参数;

真的,没有人需要GregorianCalendar作为输出,即使你被告知返回“一个字符串”。

将格式化函数的标题更改为

 public static String format(Date date) 

并做出适当的改变。 fmt.format()将很乐意接受Date对象。

  1. 始终出现意外exception后,请自行捕获,不要让java机器执行此操作。 这样你就会明白这个问题。

TL;博士

 LocalDate.parse( "23-Mar-2017" , DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US ) ) 

避免遗留日期时间类

问题和其他答案现在已经过时,使用了现在遗留下来的麻烦的旧日期时间类,取而代之的是java.time类。

使用java.time

您似乎正在处理仅限日期的值。 所以不要使用日期时间类。 而是使用LocalDateLocalDate类表示没有时间且没有时区的仅日期值。

指定Locale以确定(a)用于翻译日期名称,月份名称等的人类语言,以及(b)决定缩写,大小写,标点符号,分隔符等问题的文化规范。

解析一个字符串。

 String input = "23-Mar-2017" ; DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MMM-uuuu" , Locale.US ) ; LocalDate ld = LocalDate.parse( input , f ); 

生成一个字符串。

 String output = ld.format( f ); 

如果您为年,月和日提供了数字而不是文本,请使用LocalDate.of

 LocalDate ld = LocalDate.of( 2017 , 3 , 23 ); // ( year , month 1-12 , day-of-month ) 

请参阅IdeOne.com上的此代码 。

输入:2017年3月23日

ld.toString():2017-03-23

产量:2017年3月23日


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

使用符合JDBC 4.2或更高版本的JDBC驱动程序 ,您可以直接与数据库交换java.time对象。 不需要字符串也不需要java.sql。*类。

从哪里获取java.time类?

  • Java SE 8Java SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6Java SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • 更高版本的Android捆绑java.time类的实现。
    • 对于早期的Android, ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。