Что пошло не так?
О, БОЖИЕ ПАУКИ уже объяснили некоторые из них в комментарии. В сентябре 30 дней. Ваш форматтер экстраполирует: 31 сентября означает день после 30 сентября, то есть 1 октября.
Но время суток, 14:00:00
? Это проблема часового пояса. Ваш форматтер, если не указано иное, использует настройку часового пояса JVM. Например, это может быть Австралия / Сидней, по крайней мере, ваш Date
отображает его как AEST
, что, как я понимаю, означает Австралийское восточное стандартное время. Таким образом, ваша строка анализируется на 1 октября в 00:00:00 по смещению +10: 00 от UTC. Это тот же момент времени, что и 30 сентября, 14:00:00 UTC. Поскольку Instant.toString()
отображает момент времени в UTC (обозначается суффиксом Z
), вы получаете 2018-09-30T14:00:00Z
.
Исправление
Когда они пытаются подшутить над вашей программой, я предлагаю вам действительно возражать. Я поняла, что вы хотели только свидание, а не время суток.
String dateString = "2018-09-31";
try {
LocalDate.parse(dateString);
} catch (DateTimeParseException dtpe) {
System.out.println(dtpe);
}
Это печатает:
java.time.format.DateTimeParseException: текст «2018-09-31» не может
быть проанализировано: неверная дата '31 сентября'
Если вы хотели экстраполирующего поведения, которое вы наблюдали:
DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE
.withResolverStyle(ResolverStyle.LENIENT);
System.out.println(LocalDate.parse(dateString, dateFormatter));
2018-10-01
Вы сказали, что ожидали 2018-09-30
, но я не знаю простого способа дать вам это. Мое первое предложение - подумайте еще раз и спросите, действительно ли вам это нужно.
В своем коде я использую java.time
, современный Java-интерфейс даты и времени. Я рекомендую это. A LocalDate
- это дата без времени суток. Мне кажется, что это хорошо соответствует вашим требованиям и с самого начала предотвращает проблему с часовым поясом.
Ваше имя метода, getSQLDateWithOnlyDate
, может указывать на то, что вы намереваетесь использовать свою дату с базой данных SQL? Одно из преимуществ LocalDate
(и других java.time
типов) заключается в том, что вы можете передать его непосредственно вашим PreparedStatement
setObject
методам, при условии, что вы используете как минимум Java 8 и как минимум JDBC 4.2. Ваша реализация JPA тоже должна с радостью принять объект LocalDate
.
Ссылка: Обучающее руководство по Oracle: Дата и время , объясняющее, как использовать java.time
.