it-swarm.com.de

Konvertieren Sie Java.util.Date in Java.time.LocalDate

Wie konvertiere ich ein Java.util.Date-Objekt am besten in das neue JDK 8/JSR-310 Java.time.LocalDate?

Date input = new Date();
LocalDate date = ???
411
JodaStephen

Kurze Antwort

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

Erklärung

Trotz seines Namens stellt Java.util.Date einen Moment auf der Zeitleiste dar, kein "Datum". Die tatsächlich im Objekt gespeicherten Daten sind long Millisekunden seit 1970-01-01T00: 00Z (Mitternacht zu Beginn von 1970 GMT/UTC).

Die Äquivalentklasse zu Java.util.Date in JSR-310 ist Instant. Daher gibt es eine praktische Methode toInstant(), um die Konvertierung bereitzustellen:

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

Eine Java.util.Date-Instanz hat kein Zeitzonen-Konzept. Dies kann seltsam erscheinen, wenn Sie toString() für einen Java.util.Date aufrufen, da die toString relativ zu einer Zeitzone ist. Bei dieser Methode wird jedoch tatsächlich die Standardzeitzone von Java verwendet, um die Zeichenfolge bereitzustellen. Die Zeitzone ist nicht Teil des tatsächlichen Status von Java.util.Date.

Eine Instant enthält auch keine Informationen zur Zeitzone. Um von einer Instant in ein lokales Datum zu konvertieren, muss daher eine Zeitzone angegeben werden. Dies kann die Standardzone sein - ZoneId.systemDefault() - oder es kann eine Zeitzone sein, die von Ihrer Anwendung gesteuert wird, z. B. eine Zeitzone aus den Benutzervorgaben. Verwenden Sie die atZone()-Methode, um die Zeitzone anzuwenden:

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

Eine ZonedDateTime enthält einen Zustand, der aus dem lokalen Datum und der Uhrzeit, der Zeitzone und dem Offset von GMT/UTC besteht. Daher kann das Datum - LocalDate - mit toLocalDate() leicht extrahiert werden:

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

Java 9 Antwort

In Java SE 9 wurde eine neue Methode hinzugefügt, die diese Aufgabe etwas vereinfacht:

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

Diese neue Alternative ist direkter, erzeugt weniger Müll und sollte daher bessere Ergebnisse erzielen.

715
JodaStephen

Besserer Weg ist:

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

Vorteile dieser Version:

  • funktioniert unabhängig davon, ob die Eingabe eine Instanz von Java.util.Date oder der Unterklasse Java.sql.Date ist (im Gegensatz zu @ JodaStephen). Dies ist bei JDBC-Daten üblich. Java.sql.Date.toInstant() löst immer eine Ausnahme aus.

  • dies gilt auch für JDK8 und JDK7 mit JSR-310 Backport

Ich persönlich verwende eine Utility-Klasse (diese ist jedoch nicht für den Backport geeignet):

/**
 * 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);
    }

}

Die asLocalDate()-Methode ist hier nullsicher, verwendet toLocalDate(), wenn die Eingabe Java.sql.Date ist (sie kann vom JDBC-Treiber überschrieben werden, um Zeitzonenprobleme oder unnötige Berechnungen zu vermeiden), ansonsten wird die oben genannte Methode verwendet.

139
Oliv

Wenn Sie Java 8 verwenden, ist @ JodaStephens Antwort offensichtlich die beste. Wenn Sie jedoch mit dem JSR-310-Backport arbeiten, müssen Sie leider Folgendes tun:

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));
17
dhalsim2
LocalDate localDate = LocalDate.parse( new SimpleDateFormat("yyyy-MM-dd").format(date) );
15
ceklock
LocalDate ld = new Java.sql.Date( new Java.util.Date().getTime() ).toLocalDate();
13
Gustavo

Sie können in einer Zeile konvertieren:

public static LocalDate getLocalDateFromDate(Date date){
   return LocalDate.from(Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()));
}
7
Sahil Chhabra

zunächst ist es einfach, ein Datum in ein Instant zu konvertieren

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

Dann können Sie den Instant in eine beliebige Datums-API in jdk 8 mithilfe der ofInstant () -Methode konvertieren:

LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault()); 
6
Shedom Wei
public static LocalDate Date2LocalDate(Date date) {
        return LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy"))

dieses Format stammt von 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
宏杰李

Was ist los mit dieser einfachen Zeile?

new LocalDateTime(new Date().getTime()).toLocalDate();
0
Lawrence

Ich hatte Probleme mit der Implementierung von @ JodaStephen auf JBoss EAP 6. Daher habe ich die Konvertierung nach dem Oracle-Tutorial von Oracle in http://docs.Oracle.com/javase/tutorial/datetime/iso/legacy.html neu geschrieben.

    Date input = new Date();
    GregorianCalendar gregorianCalendar = (GregorianCalendar) Calendar.getInstance();
    gregorianCalendar.setTime(input);
    ZonedDateTime zonedDateTime = gregorianCalendar.toZonedDateTime();
    zonedDateTime.toLocalDate();
0
rogerio_gentil
Date input = new Date();
LocalDateTime  conv=LocalDateTime.ofInstant(input.toInstant(), ZoneId.systemDefault());
LocalDate convDate=conv.toLocalDate();

Die Date-Instanz enthält neben dem Datum auch Zeit, während LocalDate keine Zeit hat. Sie können es also zuerst mit der Methode ofInstant() in LocalDateTime konvertieren. Wenn Sie es ohne time wollen, dann konvertieren Sie die Instanz in LocalDate.

0
Arun Raaj