कन्वर्ट java.util.ate to java.time.ocalDate


494

किसी java.util.Dateवस्तु को नए JDK 8 / JSR-310 में परिवर्तित करने का सबसे अच्छा तरीका क्या है java.time.LocalDate?

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

जवाबों:


828

संक्षिप्त जवाब

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

व्याख्या

अपने नाम के बावजूद, java.util.Dateसमय-रेखा पर एक तात्कालिक का प्रतिनिधित्व करता है, न कि एक "तारीख"। ऑब्जेक्ट के भीतर संग्रहीत वास्तविक डेटा long1970-01-01T00: 00Z (1970 GMT / UTC की शुरुआत में मध्यरात्रि) के बाद से मिलीसेकंड की गणना है।

java.util.DateJSR-310 में समतुल्य वर्ग है Instant, इस प्रकार toInstant()रूपांतरण प्रदान करने के लिए एक सुविधाजनक तरीका है:

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

एक java.util.Dateउदाहरण में समय-क्षेत्र की कोई अवधारणा नहीं है। यदि आप कॉल toString()करते हैं तो यह अजीब लग सकता है java.util.Date, क्योंकि यह toStringटाइम-ज़ोन के सापेक्ष है। हालाँकि वह विधि वास्तव में स्ट्रिंग प्रदान करने के लिए मक्खी पर जावा के डिफ़ॉल्ट समय-क्षेत्र का उपयोग करती है। समय-क्षेत्र वास्तविक स्थिति का हिस्सा नहीं है java.util.Date

एक Instantभी समय क्षेत्र के बारे में कोई जानकारी नहीं है। इस प्रकार, Instantकिसी स्थानीय दिनांक से परिवर्तित करने के लिए समय-क्षेत्र निर्दिष्ट करना आवश्यक है। यह डिफ़ॉल्ट क्षेत्र हो सकता है - ZoneId.systemDefault()- या यह समय-क्षेत्र हो सकता है कि आपका अनुप्रयोग नियंत्रित हो, जैसे कि उपयोगकर्ता की प्राथमिकताओं से समय-क्षेत्र। atZone()समय-क्षेत्र लागू करने के लिए विधि का उपयोग करें :

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

एक ZonedDateTimeराज्य में स्थानीय तिथि और समय, समय-क्षेत्र और GMT / UTC से ऑफसेट शामिल हैं। इस तरह की तारीख - LocalDate- का उपयोग करके आसानी से निकाला जा सकता है toLocalDate():

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

जावा 9 जवाब

जावा एसई 9 में, एक नया तरीका जोड़ा गया है जो इस कार्य को थोड़ा सरल करता है:

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

यह नया विकल्प अधिक प्रत्यक्ष है, जिससे कम कचरा पैदा होता है, और इस प्रकार बेहतर प्रदर्शन करना चाहिए।


14
मुझे LocalDate.from(Instant.ofEpochMilli(date.getTime()))लगता था कि यह आपके बराबर है, लेकिन अधिक प्रत्यक्ष है।
मार्को टोपोलनिक

9
@MarkoTopolnik जो संकलित करता है लेकिन चलता नहीं है। एक झटपट में टाइम-ज़ोन नहीं होता है इसलिए लोकलडेट को प्राप्त करने का कोई तरीका नहीं होता है।
JodaStephen

11
@assylias बस sqlDate.toLocalDate () का उपयोग करें!
JodaStephen

25
@ JodaStephen Dateमें टाइम-ज़ोन की कोई अवधारणा Instantनहीं है, इसमें टाइम-ज़ोन के बारे में जानकारी शामिल नहीं है। LocalDateएपीआई कहते हैं, "एक समय-क्षेत्र के बिना एक तारीख"। तो फिर से परिवर्तित Dateकरने के लिए Instantकरने के लिए LocalDateकी जरूरत है atZone(ZoneId.systemDefault())?
गुस्तावो

8
@ गुस्तावो: LocalDateऔर LocalDateTime"एक समय या समय-क्षेत्र को स्टोर या प्रतिनिधित्व नहीं करते" (रेफ: javadocs)। हालांकि वे इसे संग्रहीत नहीं करते हैं- कक्षाएं Localदिनांक और / या समय का प्रतिनिधित्व करती हैं , इसलिए स्थानीय तिथि / समय में रूपांतरण का अर्थ है एक समयक्षेत्र।
15

158

बेहतर तरीका है:

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

इस संस्करण के लाभ:

  • इनपुट की परवाह किए बिना काम करता है java.util.Dateया यह java.sql.Date(@ JodaStephen के विपरीत) का एक उपवर्ग है । यह JDBC के मूल डेटा के साथ आम है। java.sql.Date.toInstant()हमेशा एक अपवाद फेंकता है।

  • JSR-310 बैकपोर्ट के साथ JDK8 और JDK7 के लिए भी ऐसा ही है

मैं व्यक्तिगत रूप से एक उपयोगिता वर्ग का उपयोग करता हूं (लेकिन यह बैकपोर्ट-संगत नहीं है):

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

}

यहाँ asLocalDate()विधि शून्य-सुरक्षित है, उपयोग करती है toLocalDate(), यदि इनपुट है java.sql.Date(यह समय सारणी की समस्याओं या अनावश्यक गणनाओं से बचने के लिए JDBC ड्राइवर द्वारा ओवरराइड किया जा सकता है), अन्यथा उपरोक्त विधि का उपयोग करता है।


12
यदि यह बेहतर तरीका है, तो यह बहुत बदसूरत और क्रिया है। बहुत दर्दनाक।
13

3
यह स्वीकृत उत्तर की तुलना में बेहतर है, मैं समझाता हूं कि क्यों। हाँ, यह बदसूरत है, लेकिन इसीलिए लिखा गया है DateConvertUtils
ओलिव

मुझे समझ नहीं आता कि उन्होंने नए एपीआई में रूपांतरण वर्ग क्यों लागू नहीं किया।
सेक्लॉक

@ इस्कलॉक, उन्होंने रूपांतरण वर्ग नहीं, बल्कि कुछ रूपांतरण विधियों को लागू कियाDate.toInstant()
ओले वीवी

2
क्या कोई कोटलिन पुस्तकालय है जो इन्हें विस्तार कार्यों के रूप में पैकेज करता है ताकि एक डेवलपर निम्नलिखित कार्य कर सके। तारीख x = ...; x.asLocalDate ();
मार्क एशवर्थ

20
LocalDate localDate = LocalDate.parse( new SimpleDateFormat("yyyy-MM-dd").format(date) );

7
यहां, SimpleDateFormatउदाहरण वर्तमान थ्रेड तक ही सीमित है। इसका उपयोग थ्रेड-सेफ तरीके से किया जाता है। अब, SimpleDateFormat'महंगे होने के लिए प्रतिष्ठित' (सभी आंतरिक डेटा संरचनाओं के लिए आवश्यक है) के हिसाब से इसे प्रतिष्ठित किया जा सकता है , लेकिन आप इसे 'सिंगलटन' के रूप में साझा नहीं कर सकते हैं (इसे एक्सेस किए बिना), क्योंकि यह वास्तव में थ्रेड नहीं है- सुरक्षित। (एक ThreadLocalसमाधान काम कर सकता है अगर इसमें कोड 'प्रदूषणकारी' Threadथ्रेड के जीवनचक्र के लिए जिम्मेदार है ... लेकिन ऐसा शायद ही कभी होता है)। अजीब। बचना SimpleDateFormatहै उपयोग करने का कारण । javax.time
डेविड बुलॉक

6
इस दृष्टिकोण में बहुत अधिक ओवरहेड है: 'महंगी' SimpleDateFormat(जिसे फेंक दिया जाता है), मध्यवर्ती स्ट्रिंग (जिसे फेंक दिया जाता है), और पार्सिंग की लागत। यह एक समाधान है, लेकिन अनुशंसित नहीं है।
डेविड बुलॉक

2
@ इस्कलॉक लेकिन फिर आपको समस्या आती है कि यह थ्रेड-सेफ नहीं है
फ़्लॉप

4
@ceklock SimpleDateFormat एक समय में केवल एक ही तारीख को प्रोसेस कर सकता है, यदि आप इसे समवर्ती रूप से उपयोग करते हैं, तो यह आम परिणाम देगा। तो हाँ, यह महत्वपूर्ण है। एक वैश्विक चर में SimpleDateFormat का एक भी उदाहरण न बनाएँ।
फ्लॉप

19

यदि आप Java 8 का उपयोग कर रहे हैं, तो @ JodaStephen का उत्तर स्पष्ट रूप से सबसे अच्छा है। हालाँकि, यदि आप JSR-310 बैकपोर्ट के साथ काम कर रहे हैं, तो आपको दुर्भाग्य से ऐसा कुछ करना होगा:

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));

4
सच नहीं है, @ JodaStephen का जवाब अभी भी काम करता है। आपको बस java.util को कन्वर्ट करने के लिए एक और तरीका चाहिए। इसके लिए आप org.threeten.bp.DateTimeUtils.toInstant: threeten.org/threetenbp/apidocs/org/threeten/bp/…
क्रिश्चियन सियाच

3
DateTimeUtils तब उपलब्ध नहीं थी जब मैं बैकपोर्ट का उपयोग कर रहा था, लेकिन आप सही हैं कि यह थ्री टेन बैकपोर्ट 1.0 या उसके बाद के किसी भी व्यक्ति के लिए उपलब्ध है। इस पर ध्यान दिलाने के लिए धन्यवाद।
dhalsim2

14
LocalDate ld = new java.sql.Date( new java.util.Date().getTime() ).toLocalDate();

1
और यह सबसे सरल अहसास है: LocalDate.of (getYear () + 1900, getMonth () + 1,
getDate

रेखाएँ जो कहती हैं कि वंचित हैं: |
TheRealChx101

8

आप एक पंक्ति में परिवर्तित कर सकते हैं:

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

मैं इस पद्धति का उपयोग इस तरह एक त्रुटि प्राप्त: java.time.DateTimeException: 2018-01-31T11: 54: TemporalAccessor से LOCALDATE प्राप्त करने में असमर्थ प्रकार java.time.Instant की 27.964Z
लुइगी रुबिनो

@LuigiRubino इशारा करने के लिए धन्यवाद। कृपया अद्यतन उत्तर देखें। मैं पहले ज़ोन जोड़ना भूल गया।
साहिल छाबड़ा

8

पहले, किसी दिनांक को तत्काल में बदलना आसान है

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

फिर, आप इंस्टेंट () विधि का उपयोग करके jdk 8 में इंस्टेंट को किसी भी तारीख एपीआई में परिवर्तित कर सकते हैं:

LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault()); 

2:40 बजे लोकलडेट, लोकलडायटाइम, लोकलटाइम
शोडी वेई

जोनआईड को यहां निर्दिष्ट करने का क्या मतलब है। अगर मुझे दिनांक मिलती है -> एपीआई से त्वरित और मैं इसके बारे में यूटीसी में 1970 से मिलीसेकंड के रूप में सोच सकता हूं। जब मैं एपी से किसी भी समयक्षेत्र में परिवर्तित नहीं होने के दृष्टिकोण से केवल संबंधित लोकलडेट (yyyy-mm-dd) प्राप्त करना चाहता हूं, तो क्या मुझे अपने स्थानीय समयक्षेत्र के लिए यह तत्काल ऑफसेट नहीं करने के लिए ZoneOffset.UTC का उपयोग करना चाहिए। ZoneId.systemDefault () के साथ आपका उदाहरण तारीख प्रपत्र सर्वर स्थानांतरण नहीं है। पूर्व। तत्काल 2018-10-20 0:00 का प्रतिनिधित्व करता है और फिर UTC से अमेरिका / Los_Angeles में स्थानांतरित हो जाता है जो मुझे 2018-10-20 के बजाय स्थानीय तिथि 2018-10-19 में मिलता है?
मिचेल जियोब्रो

यह टूट जाता है, तो आपके पास का क्या import java.sql.Dateआपकी फ़ाइल में: toInstant()की विधि java.sql.Dateहमेशा फेंकता है।
ओलिव

4
Date input = new Date();
LocalDateTime  conv=LocalDateTime.ofInstant(input.toInstant(), ZoneId.systemDefault());
LocalDate convDate=conv.toLocalDate();

Dateउदाहरण के तारीख के साथ भी साथ समय होते हैं, जबकि करता है LocalDateनहीं करता है। तो आप सबसे पहले इसे LocalDateTimeइसकी विधि का उपयोग करके रूपांतरित कर सकते हैं, ofInstant()यदि आप इसे बिना समय के चाहते हैं तो उदाहरण को रूपांतरित करें LocalDate


1
public static LocalDate Date2LocalDate(Date date) {
        return LocalDate.parse(date.toString(), DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy"))

इस प्रारूप से है 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();
    }

0

मुझे JBoss EAP 6 पर @ JodaStephen के कार्यान्वयन में समस्याएँ आईं, इसलिए, मैंने http://docs.oracle.com/javase/tutorial/datetime/iso/legn.html में Oracle के जावा ट्यूटोरियल के बाद रूपांतरण को फिर से लिखा है ।

    Date input = new Date();
    GregorianCalendar gregorianCalendar = (GregorianCalendar) Calendar.getInstance();
    gregorianCalendar.setTime(input);
    ZonedDateTime zonedDateTime = gregorianCalendar.toZonedDateTime();
    zonedDateTime.toLocalDate();

-2

इस 1 सरल रेखा के साथ क्या गलत है?

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

जावा शिकायत करता है कि यह आदिम प्रकार पर लंबे समय तक () को लागू नहीं कर सकता है। मैंने एक वास्तविक दिनांक ऑब्जेक्ट का उपयोग किया; शायद वहाँ रगड़ है ??
जीइको ६१

-8

मैंने नीचे दिए गए समाधान के साथ इस प्रश्न को हल किया

  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);

इस स्थिति में स्थानीय दिनांक इस प्रारूप में अपनी तिथि "yyyy-MM-dd" प्रिंट करें


1
प्रश्न java.timeJDK8 में कक्षाओं का उपयोग करते हुए एक समाधान की तलाश में है, न कि Joda Time के साथ।
19
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.