Вопрос по java, gregorian-calendar, illegalargumentexception, simpledateformat – Использование GregorianCalendar с SimpleDateFormat

25

Таким образом, я ломал голову над этим (должно быть) простым упражнением, чтобы заставить программу превратить строку даты в объект 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[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/Vancouver",offset=-28800000,dstSavings=3600000,useDaylight=true,transitions=189,lastRule=java.util.SimpleTimeZone[id=America/Vancouver,offset=-28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=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,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]

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

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

edit

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

}

last edit

Итак, кажется, что я идиот, и DIDN 'T нужно связать две функции DateUtil вместе, но использовать их в тандеме. Сначала преобразуйте дату рождения в GregorianCalendar и сохраните ее в объекте person. Затем в заявлении на печать просто скажите программе отформатировать эту дату, когда она печатается. Проблема была решена. Теперь все работает в соответствии со спецификациями, и я чувствую себя намного глупее, потому что в последний день или около того с классом DateUtil я бился, как рыба, из воды, пытаясь заставить их работать одновременно.

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

К вашему сведению, чтобы отформатировать код в StackOverflow, начните строку с 4 (или более) пробелами. использование> только для не кодовых кавычек. assylias
ах приятно знать, спасибо = P RejectionHurts

Ваш Ответ

5   ответов
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 функции = / ничего не бывает просто LOL RejectionHurts
строка об операторе возврата выдает ошибку «невозможно преобразовать из void в GregorianCalendar» RejectionHurts
@RejectionHurts: я исправил код. Вам нужно разделить его на две строки.
Ну, вы можете разделить это на 2methods (не функции), если хотите :)
2

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

dateFormat.format(calendar.getTime());

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

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

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

1

tl;dr

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

Avoid legacy date-time classes

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

Using 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.

input: 23-Mar-2017

ld.toString(): 2017-03-23

output: 23-Mar-2017


About java.time

java.time фреймворк встроен в Java 8 и выше. Эти классы вытесняют хлопотное староенаследие классы даты и времени, такие какjava.util.Date, Calendar& amp;SimpleDateFormat.

Joda-Time проект, сейчас вРежим технического обслуживанияПосоветует миграцию наjava.time классы.

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

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

Где взять классы java.time?

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

1
  1. You are putting there two-digits year. The first century. And the gregorian calendar started in 16th century. I think, you should add 2000 to the year.

  2. Month in the function new GregorianCalendar(year, month, days) is 0-based. Subtract 1 from the month there.

  3. Change the body of the second function so:

        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. Always after an unexpected exception arises, catch it yourself, don't allow java machine to do it. This way you'll understand the problem.
Конечно, вы можете сделать передачу GregorianCalendar.getTime () тоже внутри функции. Например, fmt.format (date.getTime ()). Но также очень плохо называть переменную GregorianCalendar переменной Date. Имена должны сидеть с их типами.
только что отредактировал пост с моим обновленным кодом внизу =] RejectionHurts
к сожалению, я не могу внести последнее предложенное вами изменение, поскольку в нем говорится, что это функции, которые нужно использовать, я не могу их изменить = / я уже исправил -1, совершенно забыл, что год, кажется, не проблема, и тело моей функции форматирования теперь работает правильно, когда assylias & apos; изменения были внесены = P я добавил оператор печати в функцию форматирования, чтобы увидеть, и они распечатываются в соответствии с требованиями упражнения. плохо обновить код выше RejectionHurts
Год является проблемой - в первом веке нашей эры не было григорианского календаря. Правильная функция проверит ввод для даты, которая была после того, как был впервые установлен григорианский календарь.
47

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;
Вы также можете захотетьset календарь вSimpleDateFormat, так что он знает, чтобы использовать это, а не другую систему календаря.
и я исправил это, поиграв с оператором print, toString () был не прав, как указал JB Nizet ниже. Спасибо всем! RejectionHurts
@JonSkeet я редактировал - спасибо.
Хорошо, да, чтобы исправить ошибку, я чувствую себя идиотом, который не различает дату и календарь & gt; & lt; Единственная проблема заключается в том, что при печати даты теперь я получаю эту длинную строку для данных GergorianCalendar, а не фактическую дату RejectionHurts
лол, я думал, что было что-то на сегодняшний день, но я какое-то время дурачился с этим и не мог заставить его работать, поэтому я отказался от этого = P я сообщу в нескольких RejectionHurts

Похожие вопросы