Подтвердить что ты не робот

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

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

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

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

К сожалению, инструктор не был слишком уверен в том, как использовать GregorianCalendar и SimpleDateFormat (но нам поручили работать с ними), и сказал: "Просто Google это…" Я пытался, и ничего, что я нашел, не помогло.

Код, который у меня пока есть:

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, = startDay 8, startDayOfWeek = 1, начальный промежуток = 7200000, startTimeMode = 0, endMode = 3, endMonth = 10, endDay = 1, endDayOfWeek = 1, EndTime = 7200000, endTimeMode = 0]], firstDayOfWeek = 1, minimalDaysInFirstWeek = 1, ЭРА =?, ГОД = 1985, МЕСЯЦ = 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, ЧАС = 0, HOUR_OF_DAY = 0, МИНУТНЫЙ = 0, ВТОРОЙ = 0, миллисекунду =?, ZONE_OFFSET =?, DST_OFFSET =?]

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

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

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

Исходные проблемы устранены (спасибо, ассилиас!), Но я все еще не могу печатать должным образом, потому что две функции не связаны, и необходимо, чтобы значение даты 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 я бился, как рыба, из воды, пытаясь заставить их работать одновременно.

Спасибо всем за помощь в получении даты, чтобы войти правильно!

4b9b3361

Ответ 1

Метод 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;

Ответ 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;
}

Ответ 3

SimpleDateFormat, как указывает его имя, форматирует Date s. Не Calendar. Итак, если вы хотите отформатировать GregorianCalendar с использованием SimpleDateFormat, вы должны сначала преобразовать Calendar в Date:

dateFormat.format(calendar.getTime());

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

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

Мой совет: поиск в Google не является решением проблемы. Чтение документации по API - это то, что вам нужно сделать.

Ответ 4

  1. Вы помещаете туда двухзначный год. Первый век И григорианский календарь начался в 16 веке. Я думаю, что вы должны добавить 2000 к году.

  2. Месяц в функции new GregorianCalendar(year, month, days) основан на 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(final Date date) 

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

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

Ответ 5

ТЛ; др

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

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

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

Использование java.time

Кажется, вы имеете дело только с датами. Поэтому не используйте класс даты и времени. Вместо этого используйте LocalDate. Класс 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-Мар-2017

ld.toString(): 2017-03-23

выпуск: 23-Мар-2017


О java.time

Рамка java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют неприятные старые устаревшие классы времени, такие как java.util.Date, Calendar и SimpleDateFormat.

Проект Joda-Time, теперь в режиме обслуживания, советует перейти на классы java.time.

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

Используя JDBC-драйвер, совместимый с JDBC 4.2 или более поздней версией, вы можете обменивать объекты java.time непосредственно с вашей базой данных. Нет необходимости в строках или классах java.sql. *.

Где можно получить классы java.time?

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

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