Bir java.util.Date
nesneyi yeni JDK 8 / JSR-310'a dönüştürmenin en iyi yolu nedir java.time.LocalDate
?
Date input = new Date();
LocalDate date = ???
Bir java.util.Date
nesneyi yeni JDK 8 / JSR-310'a dönüştürmenin en iyi yolu nedir java.time.LocalDate
?
Date input = new Date();
LocalDate date = ???
Yanıtlar:
Kısa cevap
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
açıklama
İsmine rağmen, java.util.Date
bir "tarih" değil, zaman çizgisinde bir anı temsil eder. Nesne içinde saklanan gerçek veriler, long
1970-01-01T00: 00Z'den (1970 GMT / UTC'nin başında gece yarısı) bu yana geçen milisaniye sayısıdır.
java.util.Date
JSR-310'daki eşdeğer sınıf Instant
, bu nedenle toInstant()
dönüşümü sağlamak için uygun bir yöntem vardır :
Date input = new Date();
Instant instant = input.toInstant();
Bir java.util.Date
örneğin saat dilimi kavramı yoktur. Aradığınızda, bu garip görünebilir toString()
bir üzerinde java.util.Date
çünkü toString
bir zaman dilimine göre yapılır. Ancak bu yöntem aslında dizeyi sağlamak için Java'nın varsayılan saat dilimini anında kullanır. Saat dilimi, gerçek durumunun bir parçası değildir java.util.Date
.
Bir Instant
de zaman dilimine hakkında herhangi bir bilgi içermez. Bu nedenle, Instant
bir değeri yerel bir tarihe dönüştürmek için bir saat dilimi belirtmek gerekir. Bu varsayılan bölge olabilir - ZoneId.systemDefault()
- veya uygulamanızın kontrol ettiği bir saat dilimi olabilir, örneğin kullanıcı tercihlerinden bir saat dilimi. atZone()
Saat dilimini uygulamak için yöntemi kullanın :
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
A ZonedDateTime
, yerel tarih ve saat, saat dilimi ve GMT / UTC'den ofsetten oluşan bir durum içerir. Bu nedenle tarih - LocalDate
- kullanılarak kolayca çıkarılabilir toLocalDate()
:
Date input = new Date();
Instant instant = input.toInstant();
ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());
LocalDate date = zdt.toLocalDate();
Java 9 yanıtı
Java SE 9'da, bu görevi biraz basitleştiren yeni bir yöntem eklendi:
Date input = new Date();
LocalDate date = LocalDate.ofInstant(input.toInstant(), ZoneId.systemDefault());
Bu yeni alternatif daha doğrudandır, daha az çöp oluşturur ve bu nedenle daha iyi performans göstermelidir.
Date
saat dilimi kavramına Instant
sahip değildir , ayrıca saat dilimi hakkında bilgi içermez. LocalDate
API "bir zaman dilimi bulunmayan bir tarih" diyor. O zaman neden dönüştürme Date
için Instant
hiç LocalDate
ihtiyaçları atZone(ZoneId.systemDefault())
?
LocalDate
ve LocalDateTime
"bir saat veya saat dilimini saklama veya temsil etme" (ref: javadocs). Saklamasalar da - sınıflar bir Local
tarih ve / veya saati temsil eder , dolayısıyla yerel tarih / saate dönüşüm bir saat dilimi anlamına gelir.
Daha iyi bir yol:
Date date = ...;
Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate()
Bu sürümün avantajları:
girdinin bir örneği java.util.Date
veya alt sınıfı ne olursa olsun çalışır java.sql.Date
(@ JodaStephen'in yolunun aksine). Bu JDBC kaynaklı verilerde yaygındır. java.sql.Date.toInstant()
her zaman bir istisna atar.
JSR-310 backport ile JDK8 ve JDK7 için aynıdır
Şahsen bir yardımcı sınıf kullanıyorum (ancak backport uyumlu değil):
/**
* 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);
}
}
Buradaki asLocalDate()
yöntem null güvenlidir, toLocalDate()
girdi ise kullanır java.sql.Date
(saat dilimi sorunlarını veya gereksiz hesaplamaları önlemek için JDBC sürücüsü tarafından geçersiz kılınabilir), aksi takdirde yukarıda belirtilen yöntemi kullanır.
DateConvertUtils
.
Date.toInstant()
.
LocalDate localDate = LocalDate.parse( new SimpleDateFormat("yyyy-MM-dd").format(date) );
SimpleDateFormat
örnek geçerli iş parçacığı ile sınırlıdır . Bu edilir kullanılan bir iş parçacığı güvenli bir şekilde. Şimdi, SimpleDateFormat
(ihtiyacı iç veri yapılarının tüm hesabıyla) 'örneğini pahalı' olmak ünlüdür ama olamaz paylaşmak çünkü, (bu bilgilere erişimi senkronizasyon olmadan) 'tekil' olarak birini o gerçekten parçacığı değil kasa. ( EğerThreadLocal
çözüm 'kirletici' ise iş parçacığının yaşam döngüsünden sorumluysa ... ama bu nadiren olur). Garip. Kaçınmak olduğunu kullanılmasının sebebi . Thread
SimpleDateFormat
javax.time
SimpleDateFormat
(atılan), ara ip (atılan) ve ayrıştırma maliyeti. Bu bir çözüm, ama önerilmez.
Java 8 kullanıyorsanız, @ JodaStephen'in cevabı kesinlikle en iyisidir. Ancak, JSR-310 backport ile çalışıyorsanız , maalesef böyle bir şey yapmanız gerekir:
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));
LocalDate ld = new java.sql.Date( new java.util.Date().getTime() ).toLocalDate();
Tek bir satıra dönüştürebilirsiniz:
public static LocalDate getLocalDateFromDate(Date date){
return LocalDate.from(Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()));
}
ilk olarak, bir Tarihi Anlık Olarak Dönüştürmek kolaydır
Instant timestamp = new Date().toInstant();
Daha sonra, ofInstant () yöntemini kullanarak Anında jdk 8'deki herhangi bir api tarihine dönüştürebilirsiniz:
LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault());
import java.sql.Date
Dosyanızda varsa kırılır : her zaman atar toInstant()
yöntemi java.sql.Date
.
Date input = new Date();
LocalDateTime conv=LocalDateTime.ofInstant(input.toInstant(), ZoneId.systemDefault());
LocalDate convDate=conv.toLocalDate();
Date
Örnek ise tarihle birlikte çok vakit içermiyor LocalDate
değil. Eğer öncelikle dönüştürebilir Yani LocalDateTime
onun yöntemini kullanarak ofInstant()
olmadan bunu istersen o zaman zaman sonra içine örneği dönüştürmek LocalDate
.
public static LocalDate Date2LocalDate(Date date) {
return LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy"))
bu biçim şuradan 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();
}
@ JodaStephen'in JBoss EAP 6'daki uygulamasında sorun yaşadım. Bu yüzden, http://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html adresindeki Oracle'ın Java Eğitimi'ni izleyerek dönüşümü yeniden yazdım .
Date input = new Date();
GregorianCalendar gregorianCalendar = (GregorianCalendar) Calendar.getInstance();
gregorianCalendar.setTime(input);
ZonedDateTime zonedDateTime = gregorianCalendar.toZonedDateTime();
zonedDateTime.toLocalDate();
Bu 1 basit çizgide yanlış olan ne?
new LocalDateTime(new Date().getTime()).toLocalDate();
Bu soruyu aşağıdaki çözümle çözdüm
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);
Bu durumda localDate tarihinizi "yyyy-AA-gg" biçiminde yazdırın
java.time
Joda Time ile değil JDK8'deki sınıfları kullanarak bir çözüm aramaktır.
LocalDate.from(Instant.ofEpochMilli(date.getTime()))
seninkine eşdeğer, ama daha doğrudan.