首页 文章

将GregorianCalendar与SimpleDateFormat一起使用

提问于
浏览
24

因此,我一直在思考这个(应该是)简单的练习,让程序将日期字符串转换为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;
    }
}

我得到的错误是:

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 [time =?,areFieldsSet = false,areAllFieldsSet = false,lenient = true,zone = sun.util.calendar.ZoneInfo [id =“America / Vancouver”,offset = -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值都是正确的,因为它们是我传递给它的数字 .

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

edit

原始问题得到澄清(谢谢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;
    }

}

last edit

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

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

5 回答

  • 4

    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;
    
  • 2

    为什么会出现这样

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

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

    dateFormat.format(calendar.getTime());
    

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

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

    我的建议是:谷歌搜索不是这里的解决方案 . 阅读API documentation是你需要做的 .

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

    • 函数new GregorianCalendar中的月份(年,月,日)是从0开始的 . 从那里的月份减去1 .

    • 更改第二个函数的主体,以便:

    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作为输出,即使你被告知返回“一个字符串” .

    将格式化函数的 Headers 更改为

    public static String format(Date date)
    

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

    • 在出现意外异常后,请自行捕捉,不要理解问题 .
  • 47

    tl;博士

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

    避免遗留日期时间类

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

    使用java.time

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

    指定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.DateCalendarSimpleDateFormat .

    现在位于maintenance modeJoda-Time项目建议迁移到java.time类 .

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

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

    从哪里获取java.time类?

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

相关问题