Несмотря на свое название, java.util.Date представляет момент в строке времени, а не "дату". Фактические данные, хранящиеся внутри объекта, представляют собой long количество миллисекунд с 1970-01 по 01T00:00Z (полночь в начале 1970 года по Гринвичу / UTC).
Эквивалентным классом для java.util.Date в JSR-310 является Instant, таким образом, существует удобный метод toInstant() для обеспечения преобразования:
У java.util.Date экземпляра нет понятия часового пояса. Это может показаться странным, если вы вызываете toString() для java.util.Date, потому что toString относится к часовому поясу. Однако этот метод фактически использует часовой пояс Java по умолчанию "на лету" для предоставления строки. Часовой пояс не является частью фактического состояния java.util.Date.
An Instant также не содержит никакой информации о часовом поясе. Таким образом, для преобразования из an Instant в локальную дату необходимо указать часовой пояс. Это может быть зона по умолчанию - ZoneId.systemDefault() - или это может быть часовой пояс, которым управляет ваше приложение, например часовой пояс из пользовательских настроек. Используйте метод atZone() для применения часового пояса:
A ZonedDateTime содержит состояние, состоящее из местных даты и времени, часового пояса и смещения от GMT / UTC. Таким образом, date - LocalDate - можно легко извлечь с помощью toLocalDate():
работает независимо от того, является ли ввод экземпляром java.util.Date или это подкласс java.sql.Date (в отличие от способа @JodaStephen). Это обычное дело для данных, созданных на JDBC. java.sql.Date.toInstant() всегда выдает исключение.
то же самое для JDK8 и JDK7 с обратным портом JSR-310
Я лично использую служебный класс (но он не совместим с обратным портом):
/** * Utilities for conversion between the old and new JDK date types * (between {@code java.util.Date} and {@code java.time.*}). * * <p> * All methods are null-safe. */ publicclassDateConvertUtils {
/** * Calls {@link #asLocalDate(Date, ZoneId)} with the system default time zone. */ publicstatic LocalDate asLocalDate(java.util.Date date) { return asLocalDate(date, ZoneId.systemDefault()); }
/** * Creates {@link LocalDate} from {@code java.util.Date} or it's subclasses. Null-safe. */ publicstatic LocalDate asLocalDate(java.util.Date date, ZoneId zone) { if (date == null) returnnull;
/** * Calls {@link #asUtilDate(Object, ZoneId)} with the system default time zone. */ publicstatic java.util.Date asUtilDate(Object date) { return asUtilDate(date, ZoneId.systemDefault()); }
/** * Creates a {@link java.util.Date} from various date objects. Is null-safe. Currently supports:<ul> * <li>{@link java.util.Date} * <li>{@link java.sql.Date} * <li>{@link java.sql.Timestamp} * <li>{@link java.time.LocalDate} * <li>{@link java.time.LocalDateTime} * <li>{@link java.time.ZonedDateTime} * <li>{@link java.time.Instant} * </ul> * * @param zone Time zone, used only if the input object is LocalDate or LocalDateTime. * * @return {@link java.util.Date} (exactly this class, not a subclass, such as java.sql.Date) */ publicstatic java.util.Date asUtilDate(Object date, ZoneId zone) { if (date == null) returnnull;
if (date instanceof java.sql.Date || date instanceof java.sql.Timestamp) returnnewjava.util.Date(((java.util.Date) date).getTime()); if (date instanceof java.util.Date) return (java.util.Date) date; if (date instanceof LocalDate) return java.util.Date.from(((LocalDate) date).atStartOfDay(zone).toInstant()); if (date instanceof LocalDateTime) return java.util.Date.from(((LocalDateTime) date).atZone(zone).toInstant()); if (date instanceof ZonedDateTime) return java.util.Date.from(((ZonedDateTime) date).toInstant()); if (date instanceof Instant) return java.util.Date.from((Instant) date);
thrownewUnsupportedOperationException("Don't know hot to convert " + date.getClass().getName() + " to java.util.Date"); }
/** * Creates an {@link Instant} from {@code java.util.Date} or it's subclasses. Null-safe. */ publicstatic Instant asInstant(Date date) { if (date == null) returnnull; else return Instant.ofEpochMilli(date.getTime()); }
/** * Calls {@link #asZonedDateTime(Date, ZoneId)} with the system default time zone. */ publicstatic ZonedDateTime asZonedDateTime(Date date) { return asZonedDateTime(date, ZoneId.systemDefault()); }
/** * Creates {@link ZonedDateTime} from {@code java.util.Date} or it's subclasses. Null-safe. */ publicstatic ZonedDateTime asZonedDateTime(Date date, ZoneId zone) { if (date == null) returnnull; else return asInstant(date).atZone(zone); }
}
asLocalDate() Метод здесь безопасен для null, использует toLocalDate(), если входные данные есть java.sql.Date (он может быть переопределен драйвером JDBC, чтобы избежать проблем с часовым поясом или ненужных вычислений), в противном случае использует вышеупомянутый метод.
Если вы используете Java 8, ответ @JodaStephen, очевидно, лучший. Однако, если вы работаете с исходным портом JSR-310, вам, к сожалению, придется сделать что-то вроде этого: