将GregorianCalendar与SimpleDateFormat一起使用

时间:2012-05-31 08:27:19

标签: java simpledateformat illegalargumentexception gregorian-calendar

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

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

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

不幸的是,教练不太确定如何使用GregorianCalendar和SimpleDateFormat(但指派我们使用它们)并说“只是谷歌”......我试过,我发现没有任何帮助

我到目前为止的代码是:

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

我得到的错误是:

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)

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

  

java.util.GregorianCalendar中[时间= ?, areFieldsSet =假,areAllFieldsSet =假,宽大=真,区= 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 =?]

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

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

修改

原始问题得到澄清(谢谢assylias!)但我仍然无法正确打印,因为这两个函数没有链接,并且要求是从person对象打印出一个GregorianCalendar日期值(因为生日是一个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课程中像鱼一样甩水,试图让它们同时工作。

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

5 个答案:

答案 0 :(得分:48)

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

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;

答案 1 :(得分:4)

为什么会出现这种并发症?

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

答案 2 :(得分:2)

SimpleDateFormat,如其名称所示,格式化日期。不是日历。因此,如果您想使用SimpleDateFormat格式化GregorianCalendar,您必须先将日历转换为日期:

dateFormat.format(calendar.getTime());

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

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

我的建议是:谷歌搜索不是解决方案。阅读API documentation是您需要做的事情。

答案 3 :(得分:1)

  1. 你的年份是两位数。第一世纪。格里高利历从16世纪开始。我想,你应该在今年增加2000个。

  2. 新功能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;
    
  4. 调试后你会看到简单的GregorianCalendar不能成为fmt.format()的参数;

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

    将格式化功能的标题更改为

    public static String format(Date date) 
    

    并进行适当的更改。 fmt.format()很乐意接受Date对象。

    1. 在出现意外异常后,请自行捕获,不要让java机器执行此操作。这样你就可以理解这个问题了。

答案 4 :(得分:1)

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 )

请参阅此code run live at IdeOne.com

  

输入:2017年3月23日

     

ld.toString():2017-03-23

     

输出:2017年3月23日

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

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

从哪里获取java.time类?

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