Сравните время строки со временем локального сервера
Есть строковый объект с определенным форматом даты. Необходимо проверить, что dateStr после текущего времени на локальном компьютере. Возникли проблемы с конверсиями и LocalDateTime
String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
public static final String DATE_FORMAT = "MMM dd yyyy HH:mm:ss zzzZ";
Я знаю, что что-то подозрительно в приведенном ниже коде с использованием LocalDateTime
public static boolean isFutureDate(String dateStr){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
return(dateTime.isAfter(LocalDateTime.now()));
}
Проблема в часовых поясах и преобразованиях дат. Пожалуйста, помогите найти правильный способ проверки, если dateStr после текущей локальной даты это в Java 8?
2 ответа
При разборе на LocalDateTime
вы игнорируете смещение (+0000
), и я не уверен, действительно ли вы этого хотите.
В этом случае +0000
смещение означает дату / время 27 октября 2017 года в 02:29 по Гринвичу. Когда вы анализируете LocalDateTime
вы игнорируете смещение (поэтому оно представляет только "27 октября 2017 г. в 02:29", не привязанное к какому-либо часовому поясу) и сравниваете его с местной датой / временем (или текущей датой / временем в часовом поясе JVM по умолчанию)).
Если вы хотите сделать сравнение, которое также учитывает смещение, вы можете проанализировать его OffsetDateTime
и преобразовать в Instant
сравнить его с фактическим временем UTC, независимо от часового пояса.
Кроме того, название месяца на английском языке (я предполагаю, что это английский, но вы можете изменить это соответственно), поэтому вы должны java.util.Locale
в форматере (если вы не зададите языковой стандарт, он будет использовать JVM по умолчанию, и он не всегда будет английским):
// parse to OffsetDateTime (use the same formatter)
String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss zzzZ", Locale.US);
OffsetDateTime odt = OffsetDateTime.parse(dateStr, fmt);
// compare Instant's
System.out.println(odt.toInstant().isAfter(Instant.now()));
Хотя это работает для вас сейчас, имейте в виду, что локаль по умолчанию может быть изменена без уведомления, даже во время выполнения. Если ваш ввод имеет чувствительную к локали дату (например, названия месяцев), лучше указать ее, как указано выше.
Local…
у типов нет часового пояса
Вы используете неправильный тип для ваших данных.
Local…
типы в том числе LocalDateTime
намеренно не имеют понятия о часовом поясе или смещении от UTC. Как таковые, они не представляют момент на временной шкале, а лишь приблизительное представление о диапазоне возможных моментов. использование LocalDateTime
только когда часовой пояс неизвестен или не имеет значения; никогда не используйте это для фактического момента в истории.
использование OffsetDateDate
для значений со смещением от UTC - количество часов и минут.
использование ZonedDateTime
для значений с назначенным часовым поясом. Часовой пояс, такой как Asia/Kolkata
или же America/Montreal
является историей прошлого, настоящего и будущего региона относительно его смещения от UTC. Аномалии, такие как переход на летнее время (DST), означают изменение смещения.
Если вы знаете, что все ваши входы в GMT/UTC, используйте OffsetDateTime
, Если входы могут использовать часовые пояса, проанализируйте как ZonedDateTime
объекты.
Этот формат входных данных ужасен. Если у вас есть какой-либо элемент управления, используйте вместо этого стандартные форматы ISO 8601 при обмене значениями времени и даты в виде текста.
Все это уже много раз освещалось на Stack Exchange. Пожалуйста, ищите более тщательно перед публикацией. И поиск переполнения стека, чтобы узнать больше. Я держал свой ответ здесь кратким, так как это дубликат.