Разбор строки в формате даты в java по умолчанию равен 1, а месяца - январю
Я пытаюсь принять вводимую пользователем дату в формате, подобном: "2000 часов, четверг, 20 июля 2015 г.". Затем я преобразоваю это в формат даты, чтобы выполнить с ним операции. Но при преобразовании строки в дату по умолчанию используется значение месяца в январе, а даты - в 1. Вот фрагмент кода :
String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, YYYY";
SimpleDateFormat userDateFormatter = new SimpleDateFormat(userDateFormat);
String reference_date = "2000 hrs, Thursday, July 20, 2015";
Date date = null;
try {
date = userDateFormatter.parse(reference_date);
} catch (ParseException e) {
System.out.println("Date must be in the format " + userDateFormat);
}
System.out.println(userDateFormatter.format(date));
Печатается блок следующего метода :
2000 часов, четверг, 01 января 2015 г.
Есть какие-нибудь подсказки, почему?
Переведено автоматически
Ответ 1
Потому что вы использовали YYYY
когда вам было нужно yyyy
, а 20 июля 2015 года было понедельником. Вы хотели что-то вроде
String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, yyyy";
SimpleDateFormat userDateFormatter = new SimpleDateFormat(
userDateFormat);
String reference_date = "2000 hrs, Monday, July 20, 2015";
который затем выводит
2000 hrs, Monday, July 20, 2015
Затем SimpleDateFormat
Javadoc сообщает (частично)
Letter Date or Time Component Presentation Examples
G Era designator Text AD
y Year Year 1996; 96
Y Week year Year 2009; 09
Ответ 2
java.time
DateTimeFormatter userDateTimeFormatter
= DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);
String referenceDate = "2000 hrs, Monday, July 20, 2015";
LocalDateTime dateTime = LocalDateTime.parse(referenceDate, userDateTimeFormatter);
System.out.println(dateTime.format(userDateTimeFormatter));
Вывод:
2000 часов, понедельник, 20 июля 2015 г.
Ответ Эллиота Фриша верен. Я привожу современный ответ, используя java.time
современный Java date and time API. Когда был задан этот вопрос, он отсутствовал полтора года. Сейчас ему четыре года, и он широко распространен. Кроме того, я даю явный язык. Ваша дата и время указаны на английском языке, и хотя ваша локаль по умолчанию, вероятно, тоже, код, который полагается на это, сломается, если однажды вы запустите его на компьютере в другой локали или просто измените свои собственные настройки локали.
Вы далеко не единственный, кто совершает ошибку, используя неправильный регистр в строке шаблона формата. Вопросы по этому поводу постоянно задаются в Stack Overflow. SimpleDateFormat
известен своим капризом: он выдает неверный результат и притворяется, что все в порядке, хотя на самом деле вы ожидали, что он уведомит вас о том, что что-то не так, например, путем выдачи исключения.
Современный API действительно выдает исключение, когда вы вводите неверные данные, которые он может обнаружить. Например:
DateTimeFormatter userDateTimeFormatter
= DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, YYYY", Locale.ENGLISH);
String referenceDate = "2000 hrs, Thursday, July 20, 2015";
Результат:
java.time.Исключение DateTimeException: не удается получить LocalDate из TemporalAccessor: {MonthOfYear=7, DayOfWeek=4, WeekBasedYear[WeekFields[ВОСКРЕСЕНЬЕ,1]]=2015, DayOfMonth=20}, ISO разрешен до 20:00 типа java.time.format.Parsed
Это не очень удобно для чтения. Следует обратить внимание на "WeekBasedYear”. Год, основанный на неделе, полезен только с номером недели, поэтому здесь это неправильно. И в документах вам скажут, что именно заглавные буквы YYYY
дали вам это. Давайте исправим:
DateTimeFormatter userDateTimeFormatter
= DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);
С DateTimeFormatter
обычно используется uuuu
для обозначения года. yyyy
работает и для лет после 0 года. Однако мы еще не закончили:
java.time.Исключение DateTimeException: обнаружен конфликт: поле DayOfWeek 1 отличается от поля DayOfWeek 4, полученного из 2015-07-20
Современный API также отказывается принимать неверный день недели, поэтому вы получаете полную проверку вашей даты (однако есть хитрость, чтобы убедить его, если вы не хотите этой проверки). Как уже сказал Эллиот Фриш, 20 июля 2015 года был понедельник (первый день недели), а не четверг. В моем первом фрагменте выше я также исправил эту ошибку, так что это работает.
Руководство по Oracle: дата и время Ссылка: объяснение использования java.time
.