30 मार्च और 1 मार्च 2020 के बीच का अंतर 29 के बजाय 28 दिन क्यों देता है?


124
TimeUnit.DAYS.convert(
   Math.abs(
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("30-03-2020 00:00:00").getTime() - 
      new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").parse("1-03-2020 00:00:00").getTime()
   ),
   TimeUnit.MILLISECONDS)

परिणाम 28 है, जबकि यह 29 होना चाहिए।

क्या समय क्षेत्र / स्थान समस्या हो सकती है?


17
नोट: कृपया इसका उपयोग न करें SimpleDateFormat, क्योंकि यह अप्रचलित है। java.timeइसके बजाय पैकेज का उपयोग करें । में SimpleDateFormatके मामले, उपयोग DateTimeFormatter। जावा 7 के मामले में, एंडी टर्नर की टिप्पणी नीचे देखें।
एमसी सम्राट

28
समय पर गणित मत करो । एक उचित समय पुस्तकालय का उपयोग करें ( java.time[हालांकि मैं आपको जावा 7 पर ध्यान देता हूं], थ्रीटेनबप , जोडा)।
एंडी टर्नर

14
मुझे लगता है कि बैठक में किसी को "ठीक है, अब है कि हम timezones मिल गया है पता चल जाएगा प्यार करता हूँ चलो 100% गधा मोड जाने के लिए और इस बात को लागू करने के लिए दिन के उजाले बचत कहा जाता है जो मेरे एसिड यात्रा के बाद एक सपने में मेरे पास आया पिछली रात।"
मंकीज़े

5
@ Gmauch TimeUnitDST के बारे में कुछ भी जानने का दिखावा नहीं करता है। जैसा कि जैवाडॉक कहता है: एक नैनोसेकंड को एक हजार माइक्रोसेकंड के एक हजारवें हिस्से के रूप में परिभाषित किया गया है, एक माइक्रोसेकंड एक हजार मिलीसेकंड के एक हजारवें हिस्से के रूप में, एक सेकंड के एक हजारवें हिस्से के रूप में एक मिलीसेकंड, साठ सेकंड के रूप में एक मिनट, साठ मिनट के रूप में एक घंटे और एक दिन के रूप में परिभाषित किया गया है। चौबीस घंटे--- चूंकि DST वर्ष के 2 दिनों का कारण ठीक 24 घंटे नहीं है, TimeUnitइसलिए यह गलत हो जाता है जब DST शामिल होता है।
एंड्रियास

1
यह समस्या केवल उन कंप्यूटरों पर होती है जो डेलाइट बचत के साथ समय क्षेत्र में होते हैं। यह समय क्षेत्र में दिन (29) की सही संख्या देता है जिसमें दिन की बचत नहीं होती है!
गोपीनाथ

जवाबों:


207

समस्या यह है कि डेलाइट सेविंग टाइम शिफ्ट (रविवार, 8 मार्च, 2020) के कारण, उन तिथियों के बीच 28 दिन और 23 घंटे हैं । परिणाम को 28 दिन तक TimeUnit.DAYS.convert(...) काट देता है।

समस्या को देखने के लिए (मैं अमेरिका के पूर्वी समय क्षेत्र में हूँ):

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
            fmt.parse("1-03-2020 00:00:00").getTime();

System.out.println(diff);
System.out.println("Days: " + TimeUnit.DAYS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Hours: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS));
System.out.println("Days: " + TimeUnit.HOURS.convert(Math.abs(diff), TimeUnit.MILLISECONDS) / 24.0);

उत्पादन

2502000000
Days: 28
Hours: 695
Days: 28.958333333333332

ठीक करने के लिए, उस समय क्षेत्र का उपयोग करें जिसमें DST नहीं है, जैसे UTC :

SimpleDateFormat fmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
long diff = fmt.parse("30-03-2020 00:00:00").getTime() -
            fmt.parse("1-03-2020 00:00:00").getTime();

उत्पादन

2505600000
Days: 29
Hours: 696
Days: 29.0

121
"ठीक करने के लिए" समय के साथ गणित नहीं करते हैं। एक उचित तिथि / समय पुस्तकालय का उपयोग करें।
एंडी टर्नर

62
@AndyTurner ठीक करने के लिए, अंतर्निहित जावा 7 एपीआई का उपयोग कर। चूंकि यह तय किया जा सकता है, यह दिखाते हुए कि कैसे एक वैध उत्तर है। किसी को एक पूर्ण पुस्तकालय (जोडा-टाइम, थ्रीटेन, इत्यादि) शामिल करने के लिए मजबूर करने के लिए बस यह एक गणना ओवरकिल होगी। यकीन है, एक पुस्तकालय का उपयोग करने की सिफारिश की जाएगी, लेकिन आवश्यक नहीं है
एंड्रियास

38
मैं आदरपूर्वक असहमत हूं। यदि आप एक गणना करना चाहते हैं, तो इसे सही करें; इसे सही करने के लिए लागत का भुगतान करें।
एंडी टर्नर

16
मेरा € 0.02: किसी भी बाहरी पुस्तकालय के बिना जावा 7 में करने का "सही" तरीका एक GregorianCalendarवस्तु का उपयोग करना और अंतिम तिथि तक एक दिन में 1 दिन जोड़ना होगा। मैं उससे बचने के लिए एक उच्च कीमत चुकाऊंगा। और एक पुस्तकालय का बैकपोर्ट जोड़ना जो पहले से ही जावा 8, 9, 10, 11, 12, 13 का हिस्सा है, ... कोई उच्च कीमत नहीं है। इसके विपरीत, अगली बार आपको तारीख या समय के साथ कुछ भी करने की आवश्यकता है, यह पहले से ही एक लाभ होगा।
ओले वीवी

27
यूटीसी में भी जून का अंतिम दिन कभी-कभार एक सेकंड भी कम होता है, बिना किसी वास्तविक चेतावनी या पूर्वानुमान के। हमेशा डेट-टाइम लाइब्रेरी का उपयोग करें।
Affe

41

इस समस्या का कारण एंड्रियास के जवाब में पहले ही उल्लेख किया गया है ।

सवाल यह है कि आप वास्तव में क्या गिनना चाहते हैं। तथ्य यह है कि आप कहते हैं कि वास्तविक अंतर 28 के बजाय 29 होना चाहिए, और पूछें कि क्या "स्थान / क्षेत्र समय एक समस्या हो सकती है" , यह बताता है कि आप वास्तव में क्या गिनना चाहते हैं। जाहिर है, आप किसी भी समयक्षेत्र के अंतर से छुटकारा पाना चाहते हैं।

मुझे लगता है कि आप केवल समय और समय के बिना दिनों की गणना करना चाहते हैं।

जावा 8

नीचे, इस उदाहरण के बीच कि कैसे दिनों की संख्या को सही ढंग से गणना की जा सकती है, मैं एक ऐसे वर्ग का उपयोग कर रहा हूं जो सटीक रूप से प्रतिनिधित्व करता है - समय और समय के बिना एक तिथि - LocalDate

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d-MM-yyyy HH:mm:ss");
LocalDate start = LocalDate.parse("1-03-2020 00:00:00", formatter);
LocalDate end = LocalDate.parse("30-03-2020 00:00:00", formatter);

long daysBetween = ChronoUnit.DAYS.between(start, end);

ध्यान दें ChronoUnit, DateTimeFormatterऔर टैग के LocalDateअनुसार, कम से कम जावा 8 की आवश्यकता है, जो आपके लिए उपलब्ध नहीं है । हालांकि, यह शायद भविष्य के पाठकों के लिए है।

जैसा कि ओले वीवी द्वारा उल्लेख किया गया है, थ्रीटेन बैकपोर्ट भी है , जो जावा 6 और 7 की जावा 8 दिनांक और समय एपीआई कार्यक्षमता का समर्थन करता है।


2
@ OleV.V। मुझे पता है कि थ्रीटेन है, कुछ उपयोगकर्ताओं ने कुछ समय का उल्लेख किया होगा। (मैं एक पोस्ट को SEDE क्वेरी से लिंक करने वाला था ThreeTen, जिसमें सभी पोस्ट और उपयोगकर्ता की टिप्पणियां 5772882 थीं, जिसमें टेक्स्ट ;-); लेकिन दुर्भाग्य से यह लेखन के समय ऑफ़लाइन है।) मैं पोस्ट को अपडेट करूंगा।
एम सी सम्राट

2
@ ओएलवीवी यह बुरी बात नहीं है। मुझे लगता है कि ज्यादातर लोग इस बारे में अनभिज्ञ हैं java.time, क्योंकि स्कूल में वे अभी भी पुरानी कक्षाओं का उपयोग करते हैं। लेकिन जावा 8 दिनांक और समय एपीआई बहुत अच्छी तरह से डिज़ाइन किया गया है - इसका उपयोग करने से नुकसान होगा।
एमसी सम्राट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.