Перетворити java.time.LocalDate у тип java.util.Date


372

Я хочу перетворити java.time.LocalDateна java.util.Dateтип. Тому що я хочу встановити дату JDateChooser. Або є якийсь вибір дати, який підтримує java.timeдати?



2
LGoodDatePicker споконвічно використовує пакет java.time (він же Java 8 разів або JSR-310 . Зокрема, LGoodDatePicker використовує "java.time.LocalDate" для зберігання значень дати. Скріншоти та демонстрація знаходяться на
домашній

Відповіді:


560
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());

Це передбачає, що вибраний вами дат використовує часовий пояс системи за замовчуванням для перетворення дат у рядки.


JB Nizet, можливо, Java 8 знаходився на ранній стадії розробки / випуску, і @ user3509494 тестував це якось.
russellhoff

2
Чи можна цього уникнути atStartOfDay(), оскільки це змінює значення дати, наскільки я це розумію.
yegor256

1
@JBNizet ваша відповідь не має для мене особливого сенсу, тому я вирішив уточнити. Чому б вам не уточнити це, замість того, щоб робити марні коментарі?
yegor256

12
Тому що я не бачу, як і чому це потребує якихось уточнень. 232 особи підтримали цю відповідь, таким чином, визнавши її зрозумілою. Ви кажете, що atStartOfDay змінює значення дати. Це не має сенсу. atStartOfDay робить те, що говорить javadoc: він перетворює LocalDate в LocalDateTime, в ту ж дату і на початку дня.
JB Nizet

2
@cornz Ви впевнені, що ваші результати неправильні? Якщо ви перебуваєте в Німеччині, то це може бути що - то робити з другим глюком 6 хвилин 32 в той час в Німеччині, в квітні 1893. Див timeanddate.com/time/zone/germany/berlin?syear=1850 деяких деталей .
Dawood ibn Kareem

104

Ось клас корисності, який я використовую для перетворення нових java.timeкласів в java.util.Dateоб'єкти і навпаки:

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

public class DateUtils {

  public static Date asDate(LocalDate localDate) {
    return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
  }

  public static Date asDate(LocalDateTime localDateTime) {
    return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
  }

  public static LocalDate asLocalDate(Date date) {
    return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
  }

  public static LocalDateTime asLocalDateTime(Date date) {
    return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
  }
}

Відредаговано на основі коментаря @Oliv.


Не використовується ZoneId.systemDefault()проблематично, оскільки часові пояси змінюються протягом року. Тож якщо 01 січня я перебуваю у часовому поясі -05: 00 (центральний), але тоді 01 липня я перебуваю у часовому поясі -06: 00 (центральне денне світло), це не призведе до неточних результатів через економію денного світла час?
jhilden

94

Ви можете використовувати java.sql.Date.valueOf()метод як:

Date date = java.sql.Date.valueOf(localDate);

Тут не потрібно додавати інформацію про час та часовий пояс, оскільки вони приймаються неявно.
Дивіться LocalDate в java.util.Date і навпаки найпростіша конверсія?


Це було ідеально для мене, оскільки мені потрібно було передати LocalDate в SQL. Однак якщо ваш формат дат зробить щось із зміною часового поясу перед форматуванням дати, ви можете отримати один день занадто рано, залежно від місцевого часового поясу, і в цьому випадку ви хочете скористатися одним із перерахованих вище варіантів.
Том Діббл

7
java.sql.Dateпризначений для рівня баз даних, JDBC, JPA. Веб-шар (або будь-яка клієнтська програма) повинен абсолютно не бути залежним від java.sql.*.
Крихітні

2
@Tiny java.sql.Date проживає в rt.jar. Зовнішніх залежностей немає. Ви просто використовуєте мовні функції.
Джордж

2
java.sql.DateСправедливий java.util.Dateчас, 00:00:00але в дизайнерській перспективі справа java.sql.*не в тому, що призначений для переднього шару, з яким взаємодіють клієнти, як Servlets / JSP. java.util.Dateна стороні Java та java.sql.Timestampабо що інше застосовується з java.sql.*боку JDBC .
Крихітний

5
Це "жахливий злом" згідно з java.time. * Автор: stackoverflow.com/questions/33066904/… . У Java 9 java.sql.*класи будуть окремою залежністю.
Дерік

16

java.time має інтерфейс Temporal, який можна використовувати для створення миттєвих об’єктів з більшості класів часу. Миттєвий сигнал відображає мілісекунди на часовій шкалі в Епоху - базовій посиланні для всіх інших дат і часу.

Нам потрібно перетворити дату в ZonedDateTime, з часом і зоною, щоб здійснити перетворення:

LocalDate ldate = ...;
Instant instant = Instant.from(ldate.atStartOfDay(ZoneId.of("GMT")));
Date date = Date.from(instant);

12

Щоб створити java.util.Date з java.time.LocalDate , ви повинні

  • додайте час до LocalDate
  • інтерпретувати дату та час у часовому поясі
  • отримати кількість секунд / мілісекунд з епохи
  • створити java.util.Date

Код може виглядати наступним чином:

LocalDate localDate = LocalDate.now();
Date date = new Date(localDate.atStartOfDay(ZoneId.of("America/New_York")).toEpochSecond() * 1000);

1
Typo in zone id (ZoneIf)
assylias

localDate.atStartOfDay () створює ZonedDateTime, але для ZonedDateTime немає методу toEpochSecond ().
Кевін Садлер

@KevinSadler: метод toEpochSecondуспадкований від java.time.chrono.ChronoZonedDateTime. Дивіться docs.oracle.com/javase/8/docs/api/java/time/chrono/…
nosid

@nosid Дякую за виправлення Коли я використовую завершення коду в Eclipse, він (і toInstance) не є опцією. Але якщо я введу його повністю, здається, це прийнято. Я неправильно зробив висновок, що це не метод через цей факт, і що я не бачив його на Javadoc для ZonedDateTime, оскільки він, як ви говорите, вказаний як спадковий метод. Вибачте, будь ласка, прийміть клік :)
Кевін Садлер

11

Це працює для мене:

java.util.Date d = new SimpleDateFormat("yyyy-MM-dd").parse(localDate.toString());

https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#toString--


6
це досить неефективно
AndresQ

1
Перехід до Миттєвого може бути багатослівним, але побудувати та проаналізувати струну - це як поїхати з Нью-Йорка до Мехіко через Токіо ...
ehecatl

1
Так, не настільки ефективно, але більшість рішень дуже багатослівні. Це просто багатослівне, і його легше читати та розуміти.
ceklock

2
@ehecatl Обережно ... в майбутньому Нью-Йорк -> Токіо -> Мехіко може бути зроблено протягом години;)
Стефан

3

Рішення Котліна:

1) Вставити цю функцію розширення кудись.

fun LocalDate.toDate(): Date = Date.from(this.atStartOfDay(ZoneId.systemDefault()).toInstant())

2) Використовуйте його, і ніколи більше не гуглите це.

val myDate = myLocalDate.toDate()

11
Як просто "перейти на Котлін"? Це питання Java.
ehecatl

1
Перетворення Java LocalDate на дату є загальною, дратівливою проблемою для будь-якого розробника JVM. Це рішення для розробників Kotlin.
gyoder

-1
public static Date convertToTimeZone(Date date, String tzFrom, String tzTo) {
    return Date.from(LocalDateTime.ofInstant(date.toInstant(), ZoneId.of(tzTo)).atZone(ZoneId.of(tzFrom)).toInstant());
} 

2
Будь ласка, поясніть своє рішення.
Мартін Забель


-3
java.util.Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());

чим ваша відповідь відрізняється від прийнятої через 4 роки? Скопіюйте-вставте для досягнення репутації?
stinger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.