Convertire java.util.Data a java.tempo.LocalDato


Qual è il modo migliore per convertire un oggetto java.util.Date nel nuovo JDK 8/JSR-310 java.time.LocalDate?

Date input = new Date();
LocalDate date = ???
Author: JodaStephen, 2014-01-20

12 answers

Risposta breve

Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

Spiegazione

Nonostante il suo nome, java.util.Date rappresenta un istante sulla linea temporale, non una "data". I dati effettivi memorizzati all'interno dell'oggetto sono un conteggio long di millisecondi dal 1970-01-01T00:00Z (mezzanotte all'inizio del 1970 GMT/UTC).

La classe equivalente a java.util.Date in JSR-310 è Instant, quindi esiste un metodo conveniente toInstant() per fornire la conversione:

Date input = new Date();
Instant instant = input.toInstant();

Un'istanza java.util.Date non ha il concetto di fuso. Questo potrebbe sembrare strano se chiami toString() su un java.util.Date, perché toString è relativo a un fuso orario. Tuttavia, questo metodo utilizza effettivamente il fuso orario predefinito di Java al volo per fornire la stringa. Il fuso orario non fa parte dello stato effettivo di java.util.Date.

An Instant inoltre non contiene alcuna informazione sul fuso orario. Pertanto, per convertire da un Instant a una data locale è necessario specificare un fuso orario. Questa potrebbe essere la zona predefinita - ZoneId.systemDefault() - o potrebbe essere un fuso orario che l'applicazione controlla, ad esempio un fuso orario dalle preferenze dell'utente. Utilizzare il metodo atZone() per applicare il fuso orario:

Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());

A ZonedDateTime contiene lo stato costituito dalla data e dall'ora locali, dal fuso orario e dall'offset da GMT/UTC. Come tale la data - LocalDate - può essere facilmente estratta usando toLocalDate():

Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
LocalDate date = zdt.toLocalDate();

Java 9 risposta

In Java SE 9, è stato aggiunto un nuovo metodo che semplifica leggermente questo compito:

Date input = new Date();
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());

Questa nuova alternativa è più diretto, creando meno spazzatura, e quindi dovrebbe funzionare meglio.

 656
Author: JodaStephen, 2018-01-21 17:34:21

Il modo migliore è:

Date date = ...;
Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate()

Vantaggi di questa versione:

  • Funziona indipendentemente dall'input è un'istanza di java.util.Date o è sottoclasse java.sql.Date (a differenza del modo di @JodaStephen). Questo è comune con i dati originati da JDBC. java.sql.Date.toInstant() genera sempre un'eccezione.

  • È lo stesso per JDK8 e JDK7 con backport JSR-310

Io personalmente uso una classe di utilità (ma questo non è compatibile con backport):

/**
 * 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.
 */
public class DateConvertUtils {

    /**
     * Calls {@link #asLocalDate(Date, ZoneId)} with the system default time zone.
     */
    public static 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.
     */
    public static LocalDate asLocalDate(java.util.Date date, ZoneId zone) {
        if (date == null)
            return null;

        if (date instanceof java.sql.Date)
            return ((java.sql.Date) date).toLocalDate();
        else
            return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDate();
    }

    /**
     * Calls {@link #asLocalDateTime(Date, ZoneId)} with the system default time zone.
     */
    public static LocalDateTime asLocalDateTime(java.util.Date date) {
        return asLocalDateTime(date, ZoneId.systemDefault());
    }

    /**
     * Creates {@link LocalDateTime} from {@code java.util.Date} or it's subclasses. Null-safe.
     */
    public static LocalDateTime asLocalDateTime(java.util.Date date, ZoneId zone) {
        if (date == null)
            return null;

        if (date instanceof java.sql.Timestamp)
            return ((java.sql.Timestamp) date).toLocalDateTime();
        else
            return Instant.ofEpochMilli(date.getTime()).atZone(zone).toLocalDateTime();
    }

    /**
     * Calls {@link #asUtilDate(Object, ZoneId)} with the system default time zone.
     */
    public static 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)
     */
    public static java.util.Date asUtilDate(Object date, ZoneId zone) {
        if (date == null)
            return null;

        if (date instanceof java.sql.Date || date instanceof java.sql.Timestamp)
            return new java.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);

        throw new UnsupportedOperationException("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.
     */
    public static Instant asInstant(Date date) {
        if (date == null)
            return null;
        else
            return Instant.ofEpochMilli(date.getTime());
    }

    /**
     * Calls {@link #asZonedDateTime(Date, ZoneId)} with the system default time zone.
     */
    public static ZonedDateTime asZonedDateTime(Date date) {
        return asZonedDateTime(date, ZoneId.systemDefault());
    }

    /**
     * Creates {@link ZonedDateTime} from {@code java.util.Date} or it's subclasses. Null-safe.
     */
    public static ZonedDateTime asZonedDateTime(Date date, ZoneId zone) {
        if (date == null)
            return null;
        else
            return asInstant(date).atZone(zone);
    }

}

Il metodo asLocalDate() qui è null-safe, usa toLocalDate(), se l'input è java.sql.Date (può essere sovrascritto dal driver JDBC per evitare problemi di fuso orario o calcoli non necessari), altrimenti usa il metodo sopra menzionato.

 124
Author: Oliv, 2015-10-22 11:42:24

Se stai usando Java 8, la risposta di @JodaStephen è ovviamente la migliore. Tuttavia, se stai lavorando con il backport JSR-310, sfortunatamente devi fare qualcosa del genere:

Date input = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(input);
LocalDate date = LocalDate.of(cal.get(Calendar.YEAR),
        cal.get(Calendar.MONTH) + 1,
        cal.get(Calendar.DAY_OF_MONTH));
 15
Author: dhalsim2, 2014-10-27 22:09:49
LocalDate ld = new java.sql.Date( new java.util.Date().getTime() ).toLocalDate();
 14
Author: Gustavo, 2015-01-11 16:30:46
LocalDate localDate = LocalDate.parse( new SimpleDateFormat("yyyy-MM-dd").format(date) );
 12
Author: ceklock, 2015-03-22 00:54:43

È possibile convertire in una riga :

public static LocalDate getLocalDateFromDate(Date date){
   return LocalDate.from(Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()));
}
 6
Author: Sahil Chhabra, 2018-01-31 16:58:58

Innanzitutto, è facile convertire una data in un istante

Instant timestamp = new Date().toInstant(); 

Quindi, è possibile convertire l'istante in qualsiasi api data in jdk 8 utilizzando il metodo ofInstant ():

LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault()); 
 5
Author: Shedom Wei, 2018-02-24 02:39:14
public static LocalDate Date2LocalDate(Date date) {
        return LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy"))

Questo formato è da Date#tostring

    public String toString() {
        // "EEE MMM dd HH:mm:ss zzz yyyy";
        BaseCalendar.Date date = normalize();
        StringBuilder sb = new StringBuilder(28);
        int index = date.getDayOfWeek();
        if (index == BaseCalendar.SUNDAY) {
            index = 8;
        }
        convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
        convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
        CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd

        CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
        CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
        CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
        TimeZone zi = date.getZone();
        if (zi != null) {
            sb.append(zi.getDisplayName(date.isDaylightTime(), TimeZone.SHORT, Locale.US)); // zzz
        } else {
            sb.append("GMT");
        }
        sb.append(' ').append(date.getYear());  // yyyy
        return sb.toString();
    }
 1
Author: 宏杰李, 2017-08-17 12:57:50

Ho avuto problemi con l'implementazione di @JodaStephen su JBoss EAP 6. Quindi, ho riscritto la conversione seguendo il tutorial Java di Oracle in http://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html.

    Date input = new Date();
    GregorianCalendar gregorianCalendar = (GregorianCalendar) Calendar.getInstance();
    gregorianCalendar.setTime(input);
    ZonedDateTime zonedDateTime = gregorianCalendar.toZonedDateTime();
    zonedDateTime.toLocalDate();
 0
Author: rogerio_gentil, 2015-08-20 18:40:54

Cosa c'è di sbagliato in questa 1 linea semplice?

new LocalDateTime(new Date().getTime()).toLocalDate();
 0
Author: Lawrence, 2018-02-21 12:59:58

Possiamo usare java.sql.Date come casting intermedio per convertire tra LocalDate e util.Date

Per ottenere util.Date da LocalDate ottenere sql.date da LocalDate e cast a util.Date

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

Per ottenere LocalDate da util.Date lanciare prima util.Date su sql.Date, quindi chiamare toLocalDate() su sql.Date

LocalDate localDate = ((java.sql.Date)java.util.Date).toLocalDate();
 -4
Author: Tharaka Dilshan, 2018-10-02 14:51:55

Ho risolto questa domanda con la soluzione sotto

  import org.joda.time.LocalDate;
  Date myDate = new Date();
  LocalDate localDate = LocalDate.fromDateFields(myDate);
  System.out.println("My date using Date" Nov 18 11:23:33 BRST 2016);
  System.out.println("My date using joda.time LocalTime" 2016-11-18);

In questo caso localDate stampa la tua data in questo formato"aaaa-MM-gg"

 -8
Author: estevamdf, 2016-11-21 11:48:54