Apa cara terbaik untuk mengkonversi jawa.util.Tanggal
objek baru JDK 8/JSR-310 jawa.waktu.LocalDate
?
Date input = new Date();
LocalDate date = ???
Jawaban singkat
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
Penjelasan
Meskipun namanya, jawa.util.Tanggal
merupakan sekejap pada waktu-line, bukan "tanggal". Data aktual yang disimpan dalam objek adalah lama
hitungan milidetik sejak 1970-01-01T00:00Z (tengah malam pada awal tahun 1970 GMT/UTC).
Setara dengan kelas jawa.util.Date
di JSR-310 adalah Instan
, sehingga ada metode yang mudah toInstant()
untuk memberikan konversi:
Date input = new Date();
Instant instant = input.toInstant();
A jawa.util.Tanggal
contoh tidak memiliki konsep zona waktu. Ini mungkin tampak aneh jika anda menelepon toString()
pada jawa.util.Tanggal
, karena toString
adalah relatif terhadap zona waktu. Namun metode yang benar-benar menggunakan Java's default-time-zone on the fly untuk memberikan string. Zona waktu bukan bagian dari keadaan yang sebenarnya dari jawa.util.Date
.
Sebuah Instan
juga tidak mengandung informasi apapun tentang zona waktu. Dengan demikian, untuk mengkonversi dari yang Instan
untuk lokal tanggal itu adalah diperlukan untuk menentukan zona waktu. Ini mungkin menjadi default zona - ZoneId.systemDefault()
- atau mungkin zona waktu yang anda kontrol aplikasi, seperti zona waktu dari preferensi pengguna. Gunakan atZone()
metode untuk menerapkan zona waktu:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
A ZonedDateTime
berisi negara yang terdiri dari lokal tanggal dan waktu, zona waktu dan offset dari GMT/UTC. Seperti tanggal - LocalDate
- dapat dengan mudah diekstraksi menggunakan toLocalDate()
:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
LocalDate date = zdt.toLocalDate();
Jawa 9 jawaban
Di Jawa SE-9, baru method telah menambahkan bahwa sedikit menyederhanakan tugas ini:
Date input = new Date();
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());
Ini alternatif baru yang lebih langsung, menciptakan sampah kurang, dan dengan demikian harus tampil lebih baik.
Cara yang lebih baik adalah:
Date date = ...;
Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate()
Kelebihan dari versi ini:
bekerja tanpa masukan adalah sebuah contoh dari jawa.util.Date
atau's subclass jawa.sql.Tanggal
(tidak seperti @JodaStephen's cara). Ini adalah umum dengan JDBC berasal dari data. jawa.sql.Tanggal.toInstant()
selalu melempar pengecualian.
it's yang sama untuk JDK8 dan JDK7 dengan JSR-310 backport
Saya pribadi menggunakan sebuah kelas utilitas (tapi ini tidak backport-kompatibel):
/**
* 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);
}
}
The asLocalDate()
metode di sini adalah null-aman, menggunakan toLocalDate()
, jika input adalah jawa.sql.Tanggal
(ini dapat diganti oleh JDBC driver untuk menghindari zona masalah atau tidak perlu perhitungan), jika tidak menggunakan metode tersebut.
Jika anda're menggunakan Java 8, @JodaStephen's jawabannya adalah jelas yang terbaik. Namun, jika anda're bekerja dengan JSR-310 backport, sayangnya anda harus melakukan sesuatu seperti ini:
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));
Anda dapat mengkonversi dalam satu baris :
public static LocalDate getLocalDateFromDate(Date date){
return LocalDate.from(Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()));
}
pertama, it's mudah untuk mengkonversi Tanggal untuk Sekejap
Instant timestamp = new Date().toInstant();
Kemudian, anda dapat mengkonversi Instan untuk setiap tanggal api di jdk 8 menggunakan ofInstant() metode:
LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault());
Date input = new Date();
LocalDateTime conv=LocalDateTime.ofInstant(input.toInstant(), ZoneId.systemDefault());
LocalDate convDate=conv.toLocalDate();
Date
contoh tidak mengandung waktu bersama dengan tanggal saat LocalDate
doesn't. Jadi pertama anda dapat mengubahnya menjadi LocalDateTime
menggunakan metode ofInstant()
maka jika anda ingin tanpa waktu kemudian mengkonversi contoh ke LocalDate
.
public static LocalDate Date2LocalDate(Date date) {
return LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy"))
format ini adalah dari Tanggal#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();
}
Saya memiliki masalah dengan @JodaStephen's implementasi pada JBoss EAP 6. Jadi, saya menulis ulang konversi berikut Oracle's Jawa Tutorial 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();
Aku memecahkan pertanyaan ini dengan solusi di bawah ini
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);
Dalam hal ini localDate cetak tanggal dalam format ini "yyyy-MM-dd"