Использование GregorianCalendar с SimpleDateFormat

Итак, я ломал голову над этим (должно быть) простым упражнением, чтобы программа превратила строку даты в объект GregorianCalendar, отформатировала ее и вернула ее снова как строку, когда она будет сделана.

Это последний маленький бит программы, которая принимает патрон текста из файла, разбивает его на отдельные записи, затем разбивает записи на отдельные фрагменты данных и назначает их объекту person.

Я проверил код в несколько места и код делает именно то, что он должен делать, пока я не вызову функцию format, которая выдает IllegalArgumentException. Gergoriancalendar объект присваивается значения, которые он должен быть назначен (хотя печать это, опять же, целая другая история, как показано ниже...), однако формат не принимает объект для форматирования.

к сожалению, инструктор не был слишком уверен в том, как использовать GregorianCalendar и SimpleDateFormat (но назначил нас на работу с ними) и сказал: "Просто 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 правильно?? Когда я распечатываю значение этого объекта (должно быть, правильно дата?) Я понимаю:

значения year, month и day_of_month верны, поскольку они являются числами, которые я передал в его создание.

мысли, предложения, я даже близко?

редактировать

оригинальные проблемы прояснились (спасибо assylias!) но я все еще не могу печатать правильно, потому что две функции не связаны, и требования должны иметь значение даты GregorianCalendar, распечатанное из объекта person (поскольку дата рождения 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 вместе, но использовать их в тандеме. Сначала преобразуйте дату рождения в GregorianCalendar и сохраните ее в объекте person. Затем в заявлении печати просто скажите программе отформатировать эту дату по мере ее печати. Проблема была решена. Все работы согласно спецификациям теперь, и я я чувствую себя еще глупее, потому что последний день или около того я барахтался, как рыба, вытащенная из воды, с классом DateUtil, пытаясь заставить их работать одновременно.

Спасибо за помощь все на свидание в правильно!

5 ответов


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;

почему такие осложнения?

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, как указывает его название, форматирует даты. Не Календарь. Поэтому, если вы хотите отформатировать GregorianCalendar с помощью SimpleDateFormat, вы должны сначала преобразовать календарь в дату:

dateFormat.format(calendar.getTime());

и то, что вы видите напечатанным, является представлением toString () календаря. Предполагаемое использование-отладка. Он не предназначен для отображения даты в графическом интерфейсе. Для этого используйте (простой)DateFormat.

наконец, чтобы преобразовать строку в дату, вам следует также использовать (простой)DateFormat (его parse() метод), а не разделение строки, как вы делаете. Это даст вам объект даты, и вы можете создать календарь с даты, создав его экземпляр (Calendar.getInstance()) и времени (calendar.setTime()).

мой совет был бы: Googling не является решением здесь. Чтение документация по 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 в качестве вывода, даже вам говорят вернуть "строку".

измените заголовок функции Your format на

public static String format(Date date) 

и внести соответствующие изменения. fmt.format() примет объект даты радостно.

  1. всегда после возникновения неожиданного исключения ловите его самостоятельно, не позволяйте java-машине делать это. Таким образом, вы поймете проблема.

tl; dr

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

избегайте устаревших классов даты и времени

вопрос и другие ответы теперь устарели, используя хлопотные старые классы даты-времени, которые теперь являются наследием, вытесненным java.классы время.

использование java.время

вы, похоже, имеете дело только со значениями даты. Поэтому не используйте класс date-time. Вместо этого используйте LocalDate. The LocalDate класс представляет значение только даты без времени суток и без часовой пояс.

указать Locale определить (а) человеческий язык для перевода названия дня, названия месяца и тому подобного, и (Б) культурные нормы, решающие вопросы аббревиатуры, капитализации, пунктуации, разделителей и тому подобного.

парсить строку.

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.

вход: 23-Mar-2017

ld.toString (): 2017-03-23

выход: 23-Mar-2017


о java.время

на java.время framework встроен в Java 8 и более поздние версии. Эти классы вытесняют беспокойных старых наследие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

на Joda Времени, теперь режим обслуживания, советует миграцию в java.время классы.

чтобы узнать больше, см. В Oracle Учебник. И search Stack Overflow для многих примеров и объяснений. Спецификация в JSR 310.

С помощью драйвер JDBC соответствуют JDBC 4.2 или позже вы можете обменять java.время объекты непосредственно с вашей базой данных. Нет необходимости в строках или java.язык SQL.* учебные занятия.

где получить java.время занятий?

  • Java SE 8, Java SE 9, и позже
    • встроенный.
    • часть стандартного API Java с встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport.
  • Android
    • более поздние версии Android bundle реализации java.классы время.
    • для более раннего Android, ThreeTenABP проект приспосабливается ThreeTen-Backport (упоминалось выше). См.как использовать ThreeTenABP....

на ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательной площадкой для возможных будущих дополнений к java.время. Здесь вы можете найти полезные классы, такие как Interval, YearWeek, YearQuarter и больше.