java - जावा कैलेंडर में जनवरी महीने 0 क्यों है?




calendar (11)

tl; डॉ

Month.FEBRUARY.getValue()  // February → 2.

2

विवरण

जॉन स्कीट द्वारा उत्तर सही है।

अब हमारे पास उन परेशानी पुरानी विरासत दिनांक-समय कक्षाओं के लिए आधुनिक प्रतिस्थापन है: java.time कक्षाएं।

java.time.Month

उन वर्गों में Month enum । एक enum में एक या अधिक पूर्वनिर्धारित वस्तुओं, वस्तुओं को लोड किया जाता है जो वर्ग लोड होने पर स्वचालित रूप से तत्काल होते हैं। Month हमारे पास एक दर्जन ऐसी वस्तुएं होती हैं, प्रत्येक को एक नाम दिया जाता है: JANUARY , FEBRUARY , MARCH , और इसी तरह। उनमें से प्रत्येक एक static final public वर्ग स्थिर है। आप इन ऑब्जेक्ट्स को अपने कोड में कहीं भी इस्तेमाल और पास कर सकते हैं। उदाहरण: कुछ someMethod( Month.AUGUST )

सौभाग्य से, उनके पास सौहार्द संख्या है, 1-12 जहां 1 जनवरी है और 12 दिसंबर है।

एक विशेष महीने संख्या (1-12) के लिए एक Month वस्तु प्राप्त करें।

Month month = Month.of( 2 );  // 2 → February.

दूसरी दिशा में जाकर, Month ऑब्जेक्ट को अपने महीने के नंबर के लिए पूछें।

int monthNumber = Month.FEBRUARY.getValue();  // February → 2.

इस वर्ग पर कई अन्य आसान तरीके, जैसे प्रत्येक माह में दिनों की संख्या जानना। कक्षा महीने का एक स्थानीय नाम भी उत्पन्न कर सकती है।

आप विभिन्न लंबाई या संक्षेप में महीने का स्थानीयकृत नाम प्राप्त कर सकते हैं।

String output = 
    Month.FEBRUARY.getDisplayName( 
        TextStyle.FULL , 
        Locale.CANADA_FRENCH 
    );

Fevrier

साथ ही, आपको केवल पूर्णांक संख्याओं के बजाय अपने कोड बेस के आस-पास इस enum की ऑब्जेक्ट्स को पास करना चाहिए। ऐसा करने से टाइप-सुरक्षा प्रदान होती है, मानों की वैध सीमा सुनिश्चित होती है, और आपके कोड को अधिक आत्म-दस्तावेज बनाता है। जावा में आश्चर्यजनक रूप से शक्तिशाली एनम सुविधा से अपरिचित होने पर ओरेकल ट्यूटोरियल देखें।

आपको Year और YearMonth कक्षा कक्षा भी उपयोगी मिल सकती है।

जावा के बारे में

java.time फ्रेमवर्क जावा 8 और बाद में बनाया गया है। ये कक्षाएं परेशानी पुरानी legacy दिनांक-समय कक्षाओं जैसे java.util.Date , .Calendar , और java.text.SimpleDateFormat

Joda-Time प्रोजेक्ट, अब रखरखाव मोड में , जावा.टाइम में माइग्रेशन की सलाह देता है।

अधिक जानने के लिए, ओरेकल ट्यूटोरियल देखें। और कई उदाहरणों और स्पष्टीकरणों के लिए स्टैक ओवरफ़्लो खोजें। विशिष्टता जेएसआर 310 है

जावा.टाइम कक्षाएं कहां प्राप्त करें?

  • जावा एसई 8 और एसई 9 और बाद में
    • निर्मित।
    • एक बंडल कार्यान्वयन के साथ मानक जावा एपीआई का हिस्सा।
    • जावा 9 कुछ मामूली विशेषताओं और फिक्सेस जोड़ता है।
  • जावा एसई 6 और एसई 7
    • जावाटाइम की अधिकांश कार्यक्षमता को ThreeTen-Backport में जावा 6 और 7 में बैक-पोर्ट किया गया है।
  • Android
    • ThreeTenABP प्रोजेक्ट विशेष रूप से एंड्रॉइड के लिए थ्रीटेन-बैकपोर्ट (ऊपर उल्लिखित) को अनुकूलित करता है।
    • देखें कि कैसे उपयोग करें ...।

ThreeTen-Extra प्रोजेक्ट अतिरिक्त कक्षाओं के साथ जावा.टाइम बढ़ाता है। यह परियोजना java.time के संभावित भविष्य के जोड़ों के लिए एक सिद्ध भूमि है। आपको यहां कुछ उपयोगी कक्षाएं मिल सकती हैं जैसे Interval , YearWeek , YearQuarter , more

java.util.Calendar , जनवरी को महीने 0 के रूप में परिभाषित किया गया है, महीने 1 नहीं। क्या इसका कोई विशिष्ट कारण है?

मैंने देखा है कि बहुत से लोग इस बारे में भ्रमित हो रहे हैं ...


java.util.Month

जावा आपको महीनों के लिए 1 आधारित इंडेक्स का उपयोग करने का एक और तरीका प्रदान करता है। java.time.Month enum का प्रयोग करें। एक वस्तु बारह महीनों में से प्रत्येक के लिए पूर्वनिर्धारित है। जनवरी-दिसंबर के लिए उनके पास प्रत्येक 1-12 को आवंटित संख्याएं हैं; नंबर के लिए कॉल प्राप्त करें।

Calendar.JULY बजाय Month.JULY उपयोग करें। Month.JULY (आपको 7 देता है)। Month.JULY (आपको 6 देता है)।

(import java.time.*;)

इसके बहुत सारे जवाब हैं, लेकिन मैं वैसे भी इस विषय पर अपना विचार दूंगा। जैसा कि पहले बताया गया है, इस अजीब व्यवहार के पीछे कारण POSIX C time.h से आता है, जहां महीनों में 0-11 के साथ एक int में संग्रहीत महीनों। समझाने के लिए, इसे इस तरह देखो; वर्षों और दिन बोली जाने वाली भाषा में संख्या माना जाता है, लेकिन महीनों के अपने नाम हैं। इसलिए क्योंकि जनवरी पहला महीना है, इसे ऑफ़सेट 0, पहला सरणी तत्व के रूप में संग्रहीत किया जाएगा। monthname[JANUARY] "January" । वर्ष में पहला महीना पहला महीना सरणी तत्व है।

दूसरी तरफ दिन की संख्या, क्योंकि उनके पास नाम नहीं हैं, इसलिए उन्हें 0-30 के रूप में एक int में संग्रहीत करना भ्रमित हो जाएगा, आउटपुट के लिए बहुत सारे day+1 निर्देश जोड़ें और, ज़ाहिर है, बग्स के बहुत से प्रवण हो।

ऐसा कहा जा रहा है कि असंगतता भ्रमित है, खासकर जावास्क्रिप्ट में (जिसने इसे "फीचर" भी विरासत में मिला है), एक पटकथा भाषा जहां इसे लैंगग से बहुत दूर समझा जाना चाहिए।

टीएल; डीआर : क्योंकि महीनों में महीने के नाम और दिन नहीं होते हैं।


इसे बिल्कुल शून्य के रूप में परिभाषित नहीं किया गया है, इसे कैलेंडर के रूप में परिभाषित किया गया है। जनवरी। यह इंटम्स के बजाय स्थिरांक के रूप में इन्स का उपयोग करने की समस्या है। कैलेंडर। जनवरी == 0।


क्योंकि महीनों के साथ गणित करना बहुत आसान है।

दिसम्बर के बाद 1 महीने जनवरी है, लेकिन इसे सामान्य रूप से समझने के लिए आपको महीने का नंबर लेना होगा और गणित करना होगा

12 + 1 = 13 // What month is 13?

मुझे पता है! मैं 12 के मॉड्यूलस का उपयोग करके इसे जल्दी से ठीक कर सकता हूं।

(12 + 1) % 12 = 1

यह नवंबर तक 11 महीने के लिए ठीक काम करता है ...

(11 + 1) % 12 = 0 // What month is 0?

महीने में जोड़ने से पहले आप इस सब काम को फिर से घटाकर 1 कर सकते हैं, फिर अपना मॉड्यूलस करें और आखिर में 1 बार फिर से जोड़ें ... उर्फ ​​एक अंतर्निहित समस्या के आसपास काम करता है।

((11 - 1 + 1) % 12) + 1 = 12 // Lots of magical numbers!

अब चलिए 0 - 11 के साथ समस्या के बारे में सोचें।

(0 + 1) % 12 = 1 // February
(1 + 1) % 12 = 2 // March
(2 + 1) % 12 = 3 // April
(3 + 1) % 12 = 4 // May
(4 + 1) % 12 = 5 // June
(5 + 1) % 12 = 6 // July
(6 + 1) % 12 = 7 // August
(7 + 1) % 12 = 8 // September
(8 + 1) % 12 = 9 // October
(9 + 1) % 12 = 10 // November
(10 + 1) % 12 = 11 // December
(11 + 1) % 12 = 0 // January

सभी महीने एक ही काम करते हैं और चारों ओर एक काम जरूरी नहीं है।


क्योंकि सब कुछ 0 से शुरू होता है। यह जावा में प्रोग्रामिंग का मूल तथ्य है। अगर एक चीज उस से विचलित हो जाती है, तो इससे भ्रम की पूरी नींद आती है। आइए उनके गठन और उनके साथ कोड का तर्क न दें।


जावा 8 में, एक नई तिथि / समय एपीआई जेएसआर 310 है जो अधिक सनी है। स्पेस लीड जोडाटाइम के प्राथमिक लेखक के समान है और वे कई समान अवधारणाओं और पैटर्न साझा करते हैं।


निजी तौर पर, मैंने जावा कैलेंडर एपीआई की अजीबता को एक संकेत के रूप में लिया कि मुझे खुद को ग्रेगोरियन-केंद्रित मानसिकता से तलाक लेने की आवश्यकता है और उस सम्मान में अधिक अज्ञात रूप से कार्यक्रम करने की कोशिश की गई है। विशेष रूप से, मैंने महीनों की तरह चीजों के लिए हार्डकोडेड स्थिरांक से बचने के लिए एक बार फिर सीखा।

निम्नलिखित में से कौन सा सही होने की संभावना है?

if (date.getMonth() == 3) out.print("March");

if (date.getMonth() == Calendar.MARCH) out.print("March");

यह एक चीज को दर्शाता है जो मुझे जोदा समय के बारे में थोड़ा परेशान करता है - यह प्रोग्रामर को हार्डकोडेड स्थिरांक के संदर्भ में सोचने के लिए प्रोत्साहित कर सकता है। (केवल थोड़ी सी, हालांकि। ऐसा नहीं है कि जोडा प्रोग्रामर को बुरी तरह प्रोग्राम करने के लिए मजबूर कर रहा है।)


मैं आलस्य कहूंगा। Arrays 0 से शुरू होता है (हर कोई जानता है कि); साल के महीनों में एक सरणी है, जो मुझे विश्वास दिलाती है कि सूर्य के कुछ इंजीनियर ने जावा कोड में इसे एक छोटा सा नुकीला रखने के लिए परेशान नहीं किया।


यह भयानक गड़बड़ी का हिस्सा है जो जावा तिथि / समय एपीआई है। इसमें जो भी गलत है, उसे सूचीबद्ध करना बहुत लंबा समय लगेगा (और मुझे यकीन है कि मुझे समस्याओं का आधा पता नहीं है)। तारीखों और समय के साथ स्वीकार्य रूप से काम करना मुश्किल है, लेकिन वैसे भी aaargh।

अपने आप को एक पक्ष बनाओ और इसके बजाय जोडा समय का उपयोग करें, या संभवतः JSR-310

संपादित करें: कारणों के लिए - जैसा कि अन्य उत्तरों में उल्लेख किया गया है, यह पुराने सी एपीआई के कारण हो सकता है, या 0 से सबकुछ शुरू करने की सामान्य भावना हो सकती है ... सिवाय इसके कि दिन 1 से शुरू होते हैं। मुझे संदेह है कि मूल कार्यान्वयन टीम के बाहर कोई भी वास्तव में कारण बता सकता है - लेकिन फिर से, मैं पाठकों से आग्रह करता हूं कि क्यों बुरा निर्णय नहीं लिया गया, ताकि java.util.Calendar में java.util.Calendar के पूरे मैदान को देखने के लिए। java.util.Calendar और कुछ बेहतर खोजें।

एक बिंदु जो 0-आधारित इंडेक्स का उपयोग करने के पक्ष में है वह यह है कि यह "नामों के सरणी" जैसी चीजें आसान बनाता है:

// I "know" there are 12 months
String[] monthNames = new String[12]; // and populate...
String name = monthNames[calendar.get(Calendar.MONTH)];

बेशक, यह 13 महीनों के साथ कैलेंडर प्राप्त होने पर ही विफल हो जाता है ... लेकिन कम से कम निर्दिष्ट आकार आपके द्वारा अपेक्षित महीनों की संख्या है।

यह एक अच्छा कारण नहीं है, लेकिन यह एक कारण है ...

संपादित करें: एक टिप्पणी के प्रकार के बारे में कुछ विचारों के बारे में कुछ विचार जो मुझे लगता है तिथि / कैलेंडर के साथ गलत है:

  • आश्चर्यजनक आधार (दिनांक में वर्ष आधार के रूप में 1 9 00, स्वीकार्य रूप से बहिष्कृत रचनाकारों के लिए; 0 दोनों में आधार आधार के रूप में)
  • उत्परिवर्तन - अपरिवर्तनीय प्रकारों का उपयोग करना वास्तव में प्रभावी रूप से मूल्यवान कार्यों के साथ काम करना बहुत आसान बनाता है
  • प्रकारों का एक अपर्याप्त सेट: अलग-अलग चीजों के रूप में Date और Calendar होना अच्छा लगता है, लेकिन "स्थानीय" बनाम "ज़ोन" मानों को अलग करना, दिनांक / समय बनाम दिनांक बनाम समय है
  • एक एपीआई जो स्पष्ट रूप से नामित तरीकों के बजाय, जादू स्थिरांक के साथ बदसूरत कोड की ओर जाता है
  • एक एपीआई जो कि कारणों के बारे में तर्क करना बहुत मुश्किल है - चीजों को फिर से तैयार करने के बारे में सभी व्यवसाय आदि
  • "अब" के लिए डिफ़ॉल्ट रूप से पैरामीटर रहित कन्स्ट्रक्टर का उपयोग, जो हार्ड-टू-टेस्ट कोड की ओर जाता है
  • Date.toString() कार्यान्वयन जो हमेशा सिस्टम स्थानीय समय क्षेत्र का उपयोग करता है (जो अब पहले कई स्टैक ओवरफ़्लो उपयोगकर्ताओं को भ्रमित कर रहा है)

सी आधारित भाषाओं को सी डिग्री कुछ डिग्री। tm संरचना ( time.h में परिभाषित) में एक पूर्णांक फ़ील्ड tm_mon जिसमें 0-11 की (टिप्पणी की गई) सीमा है।

सी आधारित भाषाएं इंडेक्स 0 पर सरणी शुरू करती हैं। इसलिए यह इंडेक्स के रूप में tm_mon साथ महीने के नामों की एक सरणी में स्ट्रिंग को आउटपुट करने के लिए सुविधाजनक था।





calendar