जावा 8: कई इकाइयों में दो लोकल डेटाइम के बीच अंतर


266

मैं दो के बीच के अंतर की गणना करने की कोशिश कर रहा हूं LocalDateTime

आउटपुट को प्रारूप का होना चाहिए y years m months d days h hours m minutes s seconds। यहाँ मैंने जो लिखा है:

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;

public class Main {

    static final int MINUTES_PER_HOUR = 60;
    static final int SECONDS_PER_MINUTE = 60;
    static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;

    public static void main(String[] args) {
        LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 9, 19, 46, 45);
        LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);

        Period period = getPeriod(fromDateTime, toDateTime);
        long time[] = getTime(fromDateTime, toDateTime);

        System.out.println(period.getYears() + " years " + 
                period.getMonths() + " months " + 
                period.getDays() + " days " +
                time[0] + " hours " +
                time[1] + " minutes " +
                time[2] + " seconds.");


    }

    private static Period getPeriod(LocalDateTime dob, LocalDateTime now) {
        return Period.between(dob.toLocalDate(), now.toLocalDate());
    }

    private static long[] getTime(LocalDateTime dob, LocalDateTime now) {
        LocalDateTime today = LocalDateTime.of(now.getYear(),
                now.getMonthValue(), now.getDayOfMonth(), dob.getHour(), dob.getMinute(), dob.getSecond());
        Duration duration = Duration.between(today, now);

        long seconds = duration.getSeconds();

        long hours = seconds / SECONDS_PER_HOUR;
        long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
        long secs = (seconds % SECONDS_PER_MINUTE);

        return new long[]{hours, minutes, secs};
    }
}

मुझे जो आउटपुट मिल रहा है वह है 29 years 8 months 24 days 12 hours 0 minutes 50 seconds। मैंने इस वेबसाइट (मानों 12/16/1984 07:45:55और 09/09/2014 19:46:45) के साथ अपना परिणाम चेक किया है । निम्न स्क्रीनशॉट आउटपुट दिखाता है:

युग परिवर्तक

मुझे पूरा यकीन है कि महीने के मूल्य के बाद के क्षेत्र मेरे कोड से गलत आ रहे हैं। कोई भी सुझाव बहुत मददगार होगा।

अपडेट करें

मैंने अपना परिणाम किसी अन्य वेबसाइट से परीक्षण किया है और मुझे जो परिणाम मिला है वह अलग है। यहाँ यह है: दो तिथियों के बीच की अवधि की गणना करें (परिणाम: 29 वर्ष, 8 महीने, 24 दिन, 12 घंटे, 0 मिनट और 50 सेकंड)।

अपडेट करें

चूंकि मुझे दो अलग-अलग साइटों से दो अलग-अलग परिणाम मिले, इसलिए मैं सोच रहा हूं कि मेरी गणना का एल्गोरिथ्म वैध है या नहीं। अगर मैं निम्नलिखित दो LocalDateTimeवस्तुओं का उपयोग करता हूं :

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);

फिर आउटपुट आ रहा है: 29 years 8 months 25 days -1 hours -5 minutes -10 seconds.

इस लिंक से यह होना चाहिए 29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds। इसलिए एल्गोरिथ्म को नकारात्मक संख्याओं को भी संभालने की आवश्यकता है।

ध्यान दें प्रश्न यह नहीं है कि किस साइट ने मुझे क्या परिणाम दिया है, मुझे सही एल्गोरिथ्म जानने की आवश्यकता है और सही परिणाम होने की आवश्यकता है।


बस एक अनुमान है, लेकिन Period.between()कुछ गोलाई लागू कर सकते हैं?
थॉमस

3
मैंने सिर्फ एक बार और कोड को देखा और ऐसा लगता है कि वेबसाइट गलत है (स्वयं की गणना करने का प्रयास करें)। यदि आप वर्ष, महीने और दिन में दिनांक, यानी अंतर को छोड़ देते हैं, तो आपको प्रारंभ समय 7:45:55और अंतिम समय 19:46:45(या 7:46:45PM) मिलेगा । तो उन दो समय के बीच का अंतर 12 घंटे, 0 मिनट और 50 सेकंड है और कभी भी 23 घंटे, 34 मिनट और 12 सेकंड नहीं है। तो आपकी गणना वास्तविक सही प्रतीत होती है, कम से कम समय भाग पर।
थॉमस

1
उस वेबसाइट पर दिलचस्प घटना: शुरू होने की तारीख में 10 साल जोड़ें और 23 से 8 तक घंटे के अंतर में अंतर - निश्चित रूप से बग का संकेत है।
थॉमस

8
ध्यान दें कि चूंकि LocalDateTimeकोई समय क्षेत्र नहीं है, इसलिए अद्वितीय उत्तर नहीं हो सकता है। यहां तक ​​कि अगर आप शुरू और अंत समय क्षेत्रों को एक ही मानते हैं, तो कुछ क्षेत्रों में 2014-09-09 जैसे डेलाइट सेविंग टाइम या समर टाइम और अन्य में नहीं होगा। यह एक घंटे से चीजों को फेंक सकता है। इसलिए जब तक यह हल नहीं हो जाता तब तक दूसरे के अंतर को समझना व्यर्थ है।
स्टुअर्ट मार्क्स

2
क्या आप समझते हैं कि LocalDateTimeपैदावार का उपयोग अवास्तविक परिणामों के रूप में किया जाता है, क्योंकि उस वर्ग में समय क्षेत्र या ऑफसेट-यूटीसी की किसी भी अवधारणा का अभाव है? यथार्थवादी मूल्यों के लिए, ZoneIdउपयोग के माध्यम से एक समय क्षेत्र असाइन करें ZonedDateTime
बेसिल बॉर्क

जवाबों:


163

दुर्भाग्यवश, ऐसा पीरियड क्लास नहीं लगता जो समय के साथ-साथ फैलता है, इसलिए आपको गणना अपने दम पर करनी पड़ सकती है।

सौभाग्य से, तिथि और समय वर्गों में बहुत अधिक उपयोगिता विधियां हैं जो कुछ हद तक इसे सरल बनाती हैं। यहां अंतर की गणना करने का एक तरीका है, हालांकि जरूरी नहीं कि सबसे तेज:

LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);

LocalDateTime tempDateTime = LocalDateTime.from( fromDateTime );

long years = tempDateTime.until( toDateTime, ChronoUnit.YEARS );
tempDateTime = tempDateTime.plusYears( years );

long months = tempDateTime.until( toDateTime, ChronoUnit.MONTHS );
tempDateTime = tempDateTime.plusMonths( months );

long days = tempDateTime.until( toDateTime, ChronoUnit.DAYS );
tempDateTime = tempDateTime.plusDays( days );


long hours = tempDateTime.until( toDateTime, ChronoUnit.HOURS );
tempDateTime = tempDateTime.plusHours( hours );

long minutes = tempDateTime.until( toDateTime, ChronoUnit.MINUTES );
tempDateTime = tempDateTime.plusMinutes( minutes );

long seconds = tempDateTime.until( toDateTime, ChronoUnit.SECONDS );

System.out.println( years + " years " + 
        months + " months " + 
        days + " days " +
        hours + " hours " +
        minutes + " minutes " +
        seconds + " seconds.");

//prints: 29 years 8 months 24 days 22 hours 54 minutes 50 seconds.

मूल विचार यह है: एक अस्थायी शुरुआत की तारीख बनाएं और अंत तक पूरे वर्ष प्राप्त करें। फिर उस तिथि को वर्षों की संख्या से समायोजित करें ताकि प्रारंभ तिथि कम हो और अंत से एक वर्ष हो। अवरोही क्रम में प्रत्येक समय इकाई के लिए इसे दोहराएं।

अंत में एक डिस्क्लेमर : मैंने अलग-अलग टाइमज़ोन को ध्यान में नहीं रखा (दोनों तिथियां एक ही टाइमज़ोन में होनी चाहिए) और मैंने यह भी परीक्षण नहीं किया कि कैलेंडर में समय की बचत या अन्य परिवर्तन कैसे होते हैं (जैसे समोआ में टाइमज़ोन में परिवर्तन) इस गणना को प्रभावित करें। इसलिए सावधानी से प्रयोग करें।


1
आपके पास एक ही मूल विचार है, इसलिए मेरा उत्थान है, लेकिन कृपया एक ही इनपुट का उपयोग करने का प्रयास करें अन्यथा अलग परिणाम भ्रामक है।
Meno Hochschild

@MenoHochschild यह एक ही इनपुट है, बस उस अपडेट से लिया गया है जहाँ ओपी नेगेटिव समय के साथ समस्याएँ हैं। ;)
थॉमस

1
अच्छा एल्गोरिथ्म, लेकिन गलत प्रकार (थॉमस अस्वीकरण देखें)। अपनी गणना करने से पहले, आपको अपने LocalDateTime चर को ZonedDateTime में परिवर्तित करना चाहिए, उदाहरण के लिए डिफ़ॉल्ट समय क्षेत्र (या किसी भी समय क्षेत्र की आवश्यकता) का उपयोग करके: ZonedDateTime fromZonedDateTime = fromDateTime.adZone (ZoneId.systemDefault ());
ट्रिस्टन

2
@ थोमस आपका उदाहरण जावा 8 का भी उपयोग कर रहा है - और प्रश्न को जावा -8 के रूप में टैग किया गया है। वास्तव में आपका उदाहरण भी ChronoUnit:) का उपयोग कर रहा है लेकिन "हाथ से" काम कर रहा है।
यूजीन बेरेसोव्स्की

3
@EugeneBeresovsky ओह हाँ, तुम सही हो। पूरी तरह से याद किया;) - इसके अलावा, आपको अभी भी अंतराल से बड़ी इकाइयों को घटाना long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);होगा क्योंकि उदाहरण के लिए कम से कम 1 घंटे के अंतराल के लिए 59 से अधिक संख्या लौटाएगा - और यह वही है जो ओपी चाहता है। इसे ध्यान में रखते हुए आप केवल 6 कॉल करने ChronoUnit#between()और करने में सक्षम नहीं होंगे ।
थॉमस

503

मुझे ऐसा करने का सबसे अच्छा तरीका मिला ChronoUnit।

long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);
long hours = ChronoUnit.HOURS.between(fromDate, toDate);

अतिरिक्त दस्तावेज यहां हैं: https://docs.oracle.com/javase/tutorial/datetime/iso/period.html


8
मुझे वास्तविक सुधार दिखाई नहीं दे रहा है। स्वीकृत थॉमस के उत्तर की तुलना में आप बस के tempDateTime.until( toDateTime, ChronoUnit.YEARS)साथ प्रतिस्थापित करते हैं ChronoUnit.YEARS.between(fromDate, toDate)। लेकिन महत्वपूर्ण अतिरिक्त लाइनें जैसे tempDateTime.plusYears( years )आदि आपके उत्तर में पूरी तरह से गायब हैं, इसलिए यह ओपी की मदद नहीं करता है। पूरा एल्गोरिथ्म मायने रखता है!
मेनो होच्स्चिल्ड

9
मुझे यह बेहतर लगता है क्योंकि यह अधिक रसीला है, और अधिक पठनीय है। यह दो तिथियों के बीच अंतर खोजने का सबसे अच्छा तरीका है।
सोमैया कुमारबेरा

7
@SomaiahKumbera नहीं आप पूरी तरह से महत्वपूर्ण बिंदु को याद करते हैं। ओपी केवल एक इकाई में नहीं बल्कि कई इकाइयों में एक अवधि चाहता है , और इसलिए यह उत्तर बिल्कुल वास्तविक उत्तर नहीं है। ओपी की चिंता का कोई मतलब नहीं है। कृपया फिर से सवाल पढ़ने के लिए दयालु बनें। (बहुत से उत्थानकर्ताओं को यह प्रश्न गलत लगा है)।
मेन्हो होचस्चिल

125
@MenoHochschild, मुझे लगता है कि आप वास्तव में महत्वपूर्ण बिंदु को याद कर रहे हैं। ओपी को उनका जवाब एक साल पहले मिल गया था। इस सवाल को देखने वाले 36 हजार लोग ओपी के विशिष्ट प्रश्न की परवाह नहीं करते हैं। वे Google द्वारा यहां नेतृत्व कर रहे थे और मेरे उत्तर ने उन्हें वही प्रदान किया जो वे ढूंढ रहे थे - दो तिथियों के बीच अंतर प्राप्त करने के लिए एक स्वच्छ और सरल समाधान।
तृप्ति

10
मुझे दो तारीखों के बीच सेकंड के अंतर की आवश्यकता थी और अपने स्वयं के समाधान को लागू करना शुरू कर दिया। कुछ ही समय में यह जटिल लगता है और मैंने Google पर लिया। satnam उत्तर ओपी प्रश्न का उत्तर नहीं दे सकता है, लेकिन यकीन है कि इससे मुझे बहुत मदद मिली और मैंने मेरे जैसे कई अन्य लोगों को धोखा दिया।
जूलियन

43

यहाँ 'hh: mm: ss' फॉर्मेट प्राप्त करने के लिए Duration और TimeUnit का उपयोग करके एक एकल उदाहरण दिया गया है।

Duration dur = Duration.between(localDateTimeIni, localDateTimeEnd);
long millis = dur.toMillis();

String.format("%02d:%02d:%02d", 
        TimeUnit.MILLISECONDS.toHours(millis),
        TimeUnit.MILLISECONDS.toMinutes(millis) - 
        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
        TimeUnit.MILLISECONDS.toSeconds(millis) - 
        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

2
यह वास्तव में ऐसा करना संभव है String.format("%02d:%02d:%02d",dur.toHoursPart(), dur.toMinutesPart(), dur.toSecondsPart());:। भाग विधियाँ आपको एक स्ट्रिंग बनाने के लिए सही संख्याएँ देती हैं। मुझे लगता है कि यह अधिक पठनीय है।
दांती

मेरी पिछली टिप्पणी पर ध्यान दें: भाग विधियाँ केवल JDK 9 और ऊपर से उपलब्ध हैं।
दांती

40

यह सरल होना चाहिए!

Duration.between(startLocalDateTime, endLocalDateTime).toMillis();

1
मेरा मानना ​​है कि यह वास्तव में जावा 8 से शुरू होने वाला शब्दार्थिक रूप से सही समाधान है। और उस संस्करण से पहले, जोडामेट वही करता है।
वरकफाल

9

टी एल; डॉ

Duration duration = Duration.between(start, end);
duration = duration.minusDays(duration.toDaysPart()); // essentially "duration (mod 1 day)"
Period period = Period.between(start.toLocalDate(), end.toLocalDate());

और फिर तरीकों का उपयोग period.getYears(), period.getMonths(), period.getDays(), duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart()


विस्तारित उत्तर

मैं मूल प्रश्न का उत्तर दूंगा, अर्थात LocalDateTimesवर्ष, महीने, दिन, घंटे और मिनट में दो का अंतर कैसे प्राप्त करें , जैसे कि विभिन्न इकाइयों के लिए सभी मानों का "योग" (नीचे नोट देखें) अस्थायी अंतर है, और इस तरह है कि प्रत्येक इकाई में मूल्य अगले बड़ा यूनिट यानी तुलना में छोटी है minutes < 60, hours < 24, और इतने पर।

दो LocalDateTimes startऔर end, जैसे

LocalDateTime start = LocalDateTime.of(2019, 11, 29, 17, 15);
LocalDateTime end = LocalDateTime.of(2020, 11, 30, 18, 44);

हम दोनों के बीच के निरपेक्ष काल का प्रतिनिधित्व कर सकते हैं - का उपयोग करते हुए एक Durationछिद्र के साथ Duration.between(start, end)। लेकिन सबसे बड़ी इकाई हम एक Durationदिन से बाहर निकाल सकते हैं (24 घंटों के लिए एक अस्थायी इकाई के रूप में) - विवरण के लिए नीचे दिए गए नोट को देखें। बड़ी इकाइयों (महीनों, वर्षों) का उपयोग करने के लिए हम इसका Durationएक जोड़ी ( Period, Duration) के साथ प्रतिनिधित्व कर सकते हैं , जहाँ Periodमाप दिन की शुद्धता तक अंतर और Durationशेष का प्रतिनिधित्व करता है:

Duration duration = Duration.between(start, end);
duration = duration.minusDays(duration.toDaysPart()); // essentially "duration (mod 1 day)"
Period period = Period.between(start.toLocalDate(), end.toLocalDate());

अब हम बस तरीकों पर परिभाषित उपयोग कर सकते हैं Periodऔर Durationव्यक्तिगत इकाइयों को निकालने के लिए:

System.out.printf("%d years, %d months, %d days, %d hours, %d minutes, %d seconds",
        period.getYears(), period.getMonths(), period.getDays(), duration.toHoursPart(),
        duration.toMinutesPart(), duration.toSecondsPart());
1 years, 0 months, 1 days, 1 hours, 29 minutes, 0 seconds

या, डिफ़ॉल्ट प्रारूप का उपयोग कर:

System.out.println(period + " + " + duration);
P1Y1D + PT1H29M

वर्षों, महीनों और दिनों पर ध्यान दें

ध्यान दें कि, java.timeगर्भाधान में, "महीने" या "वर्ष" जैसी "इकाइयाँ" एक निश्चित, पूर्ण अस्थायी मूल्य का प्रतिनिधित्व नहीं करती हैं - वे तिथि और कैलेंडर-निर्भर हैं, जैसा कि निम्नलिखित उदाहरण दिखाता है:

LocalDateTime
        start1 = LocalDateTime.of(2020, 1, 1, 0, 0),
        end1 = LocalDateTime.of(2021, 1, 1, 0, 0),
        start2 = LocalDateTime.of(2021, 1, 1, 0, 0),
        end2 = LocalDateTime.of(2022, 1, 1, 0, 0);
System.out.println(Period.between(start1.toLocalDate(), end1.toLocalDate()));
System.out.println(Duration.between(start1, end1).toDays());
System.out.println(Period.between(start2.toLocalDate(), end2.toLocalDate()));
System.out.println(Duration.between(start2, end2).toDays());
P1Y
366
P1Y
365

5

तापस बोस कोड और थॉमस कोड के लिए कुछ समस्या है। यदि समय विभेदक ऋणात्मक है, तो सरणी ऋणात्मक मान प्राप्त करती है। उदाहरण के लिए यदि

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);

यह 0 वर्ष 0 महीने 1 दिन -1 घंटे 0 मिनट 0 सेकंड देता है।

मुझे लगता है कि सही आउटपुट है: 0 वर्ष 0 महीने 0 दिन 23 घंटे 0 मिनट 0 सेकंड।

मैं LocalDateTime लोकेशन को LocalDate और LocalTime उदाहरणों पर अलग करने का प्रस्ताव करता हूं। उसके बाद हम जावा 8 पीरियड और अवधि के उदाहरण प्राप्त कर सकते हैं। अवधि अवधि के बाद के सुधार के साथ अवधि की अवधि को दिन और पूरे दिन के समय मूल्य (<24 h) पर अलग किया जाता है। जब दूसरा लोकल टाइम वैल्यू फर्स्टलोकल टाइम वैल्यू से पहले हो, तो एक दिन के लिए अवधि कम करना आवश्यक है।

यहाँ LocalDateTime अंतर की गणना करने का मेरा तरीका है:

private void getChronoUnitForSecondAfterFirst(LocalDateTime firstLocalDateTime, LocalDateTime secondLocalDateTime, long[] chronoUnits) {
    /*Separate LocaldateTime on LocalDate and LocalTime*/
    LocalDate firstLocalDate = firstLocalDateTime.toLocalDate();
    LocalTime firstLocalTime = firstLocalDateTime.toLocalTime();

    LocalDate secondLocalDate = secondLocalDateTime.toLocalDate();
    LocalTime secondLocalTime = secondLocalDateTime.toLocalTime();

    /*Calculate the time difference*/
    Duration duration = Duration.between(firstLocalDateTime, secondLocalDateTime);
    long durationDays = duration.toDays();
    Duration throughoutTheDayDuration = duration.minusDays(durationDays);
    Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
            "Duration is: " + duration + " this is " + durationDays
            + " days and " + throughoutTheDayDuration + " time.");

    Period period = Period.between(firstLocalDate, secondLocalDate);

    /*Correct the date difference*/
    if (secondLocalTime.isBefore(firstLocalTime)) {
        period = period.minusDays(1);
        Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
                "minus 1 day");
    }

    Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
            "Period between " + firstLocalDateTime + " and "
            + secondLocalDateTime + " is: " + period + " and duration is: "
            + throughoutTheDayDuration
            + "\n-----------------------------------------------------------------");

    /*Calculate chrono unit values and  write it in array*/
    chronoUnits[0] = period.getYears();
    chronoUnits[1] = period.getMonths();
    chronoUnits[2] = period.getDays();
    chronoUnits[3] = throughoutTheDayDuration.toHours();
    chronoUnits[4] = throughoutTheDayDuration.toMinutes() % 60;
    chronoUnits[5] = throughoutTheDayDuration.getSeconds() % 60;
}

उपरोक्त विधि का उपयोग किसी भी स्थानीय तारीख और समय के मूल्यों के अंतर की गणना के लिए किया जा सकता है, उदाहरण के लिए:

public long[] getChronoUnits(String firstLocalDateTimeString, String secondLocalDateTimeString) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    LocalDateTime firstLocalDateTime = LocalDateTime.parse(firstLocalDateTimeString, formatter);
    LocalDateTime secondLocalDateTime = LocalDateTime.parse(secondLocalDateTimeString, formatter);

    long[] chronoUnits = new long[6];
    if (secondLocalDateTime.isAfter(firstLocalDateTime)) {
        getChronoUnitForSecondAfterFirst(firstLocalDateTime, secondLocalDateTime, chronoUnits);
    } else {
        getChronoUnitForSecondAfterFirst(secondLocalDateTime, firstLocalDateTime, chronoUnits);
    }
    return chronoUnits;
}

उपरोक्त विधि के लिए एक इकाई परीक्षण लिखना सुविधाजनक है (दोनों में से एक है PeriodDuration वर्ग के सदस्य)। यहाँ कोड है:

@RunWith(Parameterized.class)
public class PeriodDurationTest {

private final String firstLocalDateTimeString;
private final String secondLocalDateTimeString;
private final long[] chronoUnits;

public PeriodDurationTest(String firstLocalDateTimeString, String secondLocalDateTimeString, long[] chronoUnits) {
    this.firstLocalDateTimeString = firstLocalDateTimeString;
    this.secondLocalDateTimeString = secondLocalDateTimeString;
    this.chronoUnits = chronoUnits;
}

@Parameters
public static Collection<Object[]> periodValues() {
    long[] chronoUnits0 = {0, 0, 0, 0, 0, 0};
    long[] chronoUnits1 = {0, 0, 0, 1, 0, 0};
    long[] chronoUnits2 = {0, 0, 0, 23, 0, 0};
    long[] chronoUnits3 = {0, 0, 0, 1, 0, 0};
    long[] chronoUnits4 = {0, 0, 0, 23, 0, 0};
    long[] chronoUnits5 = {0, 0, 1, 23, 0, 0};
    long[] chronoUnits6 = {29, 8, 24, 12, 0, 50};
    long[] chronoUnits7 = {29, 8, 24, 12, 0, 50};
    return Arrays.asList(new Object[][]{
        {"2015-09-09 21:46:44", "2015-09-09 21:46:44", chronoUnits0},
        {"2015-09-09 21:46:44", "2015-09-09 22:46:44", chronoUnits1},
        {"2015-09-09 21:46:44", "2015-09-10 20:46:44", chronoUnits2},
        {"2015-09-09 21:46:44", "2015-09-09 20:46:44", chronoUnits3},
        {"2015-09-10 20:46:44", "2015-09-09 21:46:44", chronoUnits4},
        {"2015-09-11 20:46:44", "2015-09-09 21:46:44", chronoUnits5},
        {"1984-12-16 07:45:55", "2014-09-09 19:46:45", chronoUnits6},
        {"2014-09-09 19:46:45", "1984-12-16 07:45:55", chronoUnits6}
    });
}

@Test
public void testGetChronoUnits() {
    PeriodDuration instance = new PeriodDuration();
    long[] expResult = this.chronoUnits;
    long[] result = instance.getChronoUnits(this.firstLocalDateTimeString, this.secondLocalDateTimeString);
    assertArrayEquals(expResult, result);
}

}

सभी परीक्षण सफल रहे हैं या नहीं, पहले LocalDateTime का मान किसी भी LocalTime मानों के लिए है या नहीं।


मैं आपके कथन को पुन: पेश नहीं कर सकता कि आपके इनपुट के ऊपर थॉमस कोड मिश्रित संकेत देता है। मेरा आउटपुट है: "0 वर्ष 0 महीने 0 दिन 23 घंटे 0 मिनट 0 सेकंड।"। और मैंने अभी-अभी परीक्षण किया है।
मेनो होच्स्चिल्ड

टिप्पणी के लिये आपका धन्यवाद। मैंने थॉमस कोड का पूरी तरह से परीक्षण किया, वास्तव में, यह सही ढंग से काम कर रहा है! जादू स्थानीयडॉटटाइम द्वारा किया जाता है जब तक कि विधि क्रोनो इकाइयों को सही नहीं करती है। थॉमस कोड में नकारात्मक मान दिखाई देते हैं यदि पहली DateTime दूसरे से बाद में है। लेकिन यह आसानी से ठीक किया जा सकता है, उदाहरण के लिए, जैसा कि मैंने उपरोक्त कोड में किया था। एक बार फिर धन्यवाद।
गेनेडी कोलोमेट्स

वैसे, ड्यूरेशन की गणना के लिए एक ही एल्गोरिदम का उपयोग करते हुए थॉमस कोड और मेरा लाइब्रेरी टाइम 4 जे नकारात्मक संकेत पैदा कर सकता है लेकिन केवल पूरी अवधि के लिए। यह महत्वपूर्ण बिंदु है! संकेत पूरी अवधि से संबंधित है और इसलिए वर्णन करता है कि क्या शुरुआत अंत से बाद में है और एकल अवधि घटकों से संबंधित नहीं है। मिश्रित संकेत यहां संभव नहीं हैं और अंत के सापेक्ष शुरुआत की ऐसी व्याख्या को रोकेंगे (काउंटर उदाहरण समय-समय-अवधि हैं या java.time.Periodजहां उपयोगकर्ता अलग-अलग आंतरिक डिजाइन के कारण इस तरह के मिश्रित संकेतों को लागू कर सकते हैं / पैदा कर सकते हैं)।
मेनो होच्स्चिल्ड

5

और ग्रूवी में @Thomas का संस्करण मूल्यों को हार्डकोड करने के बजाय वांछित इकाइयों को एक सूची में लेता है। यह कार्यान्वयन (जो आसानी से जावा में पोर्ट किया जा सकता है - मैंने फ़ंक्शन की घोषणा को स्पष्ट कर दिया है) थॉमस के दृष्टिकोण को अधिक पुन: प्रयोज्य बनाता है।

def fromDateTime = LocalDateTime.of(1968, 6, 14, 0, 13, 0)
def toDateTime = LocalDateTime.now()
def listOfUnits = [
    ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS,
    ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS,
    ChronoUnit.MILLIS]

println calcDurationInTextualForm(listOfUnits, fromDateTime, toDateTime)    

String calcDurationInTextualForm(List<ChronoUnit> listOfUnits, LocalDateTime ts, LocalDateTime to)
{
    def result = []

    listOfUnits.each { chronoUnit ->
        long amount = ts.until(to, chronoUnit)
        ts = ts.plus(amount, chronoUnit)

        if (amount) {
            result << "$amount ${chronoUnit.toString()}"
        }
    }

    result.join(', ')
}

इस लेखन के समय, ऊपर का कोड रिटर्न करता है 47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis। और, @Gennady Kolomoets इनपुट के लिए, कोड रिटर्न करता है 23 Hours

जब आप इकाइयों की एक सूची प्रदान करते हैं तो उसे इकाइयों के आकार के अनुसार क्रमबद्ध किया जाना चाहिए (सबसे पहले):

def listOfUnits = [ChronoUnit.WEEKS, ChronoUnit.DAYS, ChronoUnit.HOURS]
// returns 2495 Weeks, 3 Days, 8 Hours

4

यहाँ आपके प्रश्न का बहुत ही सरल उत्तर है। यह काम करता हैं।

import java.time.*;
import java.util.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

public class MyClass {
public static void main(String args[]) {
    DateTimeFormatter T = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
    Scanner h = new Scanner(System.in);

    System.out.print("Enter date of birth[dd/mm/yyyy hh:mm]: ");
    String b = h.nextLine();

    LocalDateTime bd = LocalDateTime.parse(b,T);
    LocalDateTime cd = LocalDateTime.now();

    long minutes = ChronoUnit.MINUTES.between(bd, cd);
    long hours = ChronoUnit.HOURS.between(bd, cd);

    System.out.print("Age is: "+hours+ " hours, or " +minutes+ " minutes old");
}
}

1
मुझे यह उल्लेख करना चाहिए कि यह सही नहीं है। इसके साथ प्रयास करें। यह 1 मिनट का अंतर कहता है। LocalDateTime bd = LocalDateTime.of (2019, 11, 26, 15, 03, 55); LocalDateTime cd = LocalDateTime.of (2019, 11, 26, 15, 04, 45);
मार्क अमाबाइल

मैं कल रात एक समय में प्रवेश किया और गया Age is: 0 years,0 months, 1 days, -10 hours, -48 minutes old। मुझे नहीं लगता कि यह वही था जो वांछित था।
ओले वीवी

@ OleV.V। उस मुद्दे को तय किया
SavedBeau

1

Joda समय

चूंकि कई उत्तरों के लिए एपीआई 26 समर्थन की आवश्यकता थी और मेरा न्यूनतम एपीआई 23 था, इसलिए मैंने इसे नीचे दिए गए कोड द्वारा हल किया:

import org.joda.time.Days

LocalDate startDate = Something
LocalDate endDate = Something
// The difference would be exclusive of both dates, 
// so in most of use cases we may need to increment it by 1
Days.daysBetween(startDate, endDate).days

1
Joda समय परियोजना, रखरखाव मोड में है इसके निर्माता स्टीफन Colebourne बनाने के लिए पर चला गया हो रही है java.time JSR 310 में परिभाषित वर्गों के अधिकांश java.time कार्यक्षमता में जावा 6 और 7 को वापस भेजा है ThreeTen- बैकपोर्ट परियोजना। आगे तीनटीनबप प्रोजेक्ट में शुरुआती एंड्रॉइड के लिए अनुकूलित ।
तुलसी बोर्क

1

पांच साल से अधिक समय के बाद मैं अपने प्रश्न का उत्तर देता हूं। मुझे लगता है कि एक नकारात्मक अवधि के साथ समस्या को एक सरल सुधार द्वारा हल किया जा सकता है:

LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);

Period period = Period.between(fromDateTime.toLocalDate(), toDateTime.toLocalDate());
Duration duration = Duration.between(fromDateTime.toLocalTime(), toDateTime.toLocalTime());

if (duration.isNegative()) {
    period = period.minusDays(1);
    duration = duration.plusDays(1);
}
long seconds = duration.getSeconds();
long hours = seconds / SECONDS_PER_HOUR;
long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
long secs = (seconds % SECONDS_PER_MINUTE);
long time[] = {hours, minutes, secs};
System.out.println(period.getYears() + " years "
            + period.getMonths() + " months "
            + period.getDays() + " days "
            + time[0] + " hours "
            + time[1] + " minutes "
            + time[2] + " seconds.");

नोट: साइट https://www.epochconverter.com/date-difference अब समय के अंतर की सही गणना करता है।

आपकी चर्चा और सुझावों के लिए आप सभी का धन्यवाद।


जवाब के लिए धन्यवाद। घंटे और छोटे के लिए आप से फायदा हो सकता toHours, toMinutesऔरtoSeconds के तरीकों Duration। जावा 9 से toMinutesPart()और भी अधिक और toSecondsPart()। और मैं घंटों, मिनटों और सेक में अरिपन को केवल फिर से बाहर निकालने के लिए एक सरणी में नहीं देखता। आम तौर पर एक अच्छा जवाब है, हालांकि।
ओले वीवी

पांच साल से अधिक समय के बाद मैं अपने प्रश्न का उत्तर देता हूं।प्रश्न एक अलग नाम, शीर्षक और स्थान के साथ एक खाते से पोस्ट किया गया था, बहुत समानता नहीं लगती है? ऐसा नहीं है कि इसका कोई महत्व है, बस आश्चर्य है।
ओले वीवी

"पांच साल से अधिक समय के बाद मैं अपने प्रश्न का उत्तर देता हूं" मुझे लगता है कि मैं ओपी था :)
तापस बोस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.