हम लीप ईयर बग्स से बचाने के लिए कैसे कोडिंग प्रथाओं को विकसित कर सकते हैं? [बन्द है]


80

माइक्रोसॉफ्ट ने अभी घोषणा की है कि पिछले सप्ताह विंडोज एज़्योर में तारीखों (लीप वर्ष से अधिक) की गणना में एक सॉफ्टवेयर त्रुटि का कारण बना

क्या यह वास्तव में DateTime.Now.AddYears(1)एक लीप वर्ष पर काम करने वाले निर्णय में एक साधारण त्रुटि थी?

क्या कोडिंग प्रथाओं को रोका जा सकता था?

EDIT जैसा कि dcstraw ने DateTime.Now.AddYears(1)लीप ईयर पर बताया था कि वास्तव में .NET में सही तारीख है। तो यह एक ढांचा बग नहीं है, लेकिन स्पष्ट रूप से तिथि गणना में एक बग है।


7
चूंकि कोई 'एक' उत्तर नहीं है, और यह एक चर्चा-वाई प्रश्न का अधिक है, मुझे लगता है कि इसे प्रोग्रामर के लिए माइग्रेट किया जाना चाहिए। इसके अलावा: हमेशा यूनिट अपने कोड का परीक्षण करें। हमेशा।
जॉर्ज स्टॉकर

2
दिनांक समय समस्याएँ एक जटिल और जटिल समस्या हैं। कोई कह सकता है कि यूटीसी में सब कुछ होता है, लेकिन अनुवाद के कुछ बिंदु हमेशा होंगे ... और जब ऐसा होता है तो सभी बग से बचने के लिए आपको कितने क्रमोन्नति की आवश्यकता होगी । हममें से ज्यादातर लोग कभी ऐसी प्रणाली पर काम नहीं करेंगे जिसकी देखभाल करनी हो।
जोश

9
मुझे लगता है कि यह प्रश्न भी बंद होने के लिए बहुत दिलचस्प है :-)
स्टीवन

11
बंद करने के लिए वोट? मुझे आशा है कि यह बुरा स्वभाव है, खुशहाल बात को ट्रिगर करना एसओ विकास में एक चरण है। यह सब थोड़ा-बहुत होली-टू-तू है।
इलन होल्डर

7
@IMMH को आपसे विशेष रूप से सहमत होना है, क्योंकि इसे बंद करने वाले लगभग सभी लोगों ने कभी न कभी कुछ मतों से अधिक प्रश्न पूछे हैं।
लॉयड

जवाबों:


95

बेशर्म प्लग:

बेहतर दिनांक और समय API का उपयोग करें

बिल्ट-इन .NET दिनांक और समय पुस्तकालयों को ठीक से उपयोग करने के लिए बहुत कठिन हैं। वे आपको वह सब कुछ करने देते हैं जिसकी आपको ज़रूरत है, लेकिन आप अपने आप को स्पष्ट रूप से टाइप सिस्टम के माध्यम से व्यक्त नहीं कर सकते हैं । DateTimeएक गड़बड़ है , DateTimeOffsetआपको यह सोचने में सुस्त कर सकता है कि आप वास्तव में उस समय क्षेत्र की जानकारी को संरक्षित कर रहे हैं जब आप नहीं हैं, और TimeZoneInfoआपको वह सब कुछ सोचने के लिए मजबूर नहीं करता है जिसे आप विचार करना चाहते हैं।

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

इस सब के कारण मैं Noda Time का निर्माण कर रहा हूं - जोडा टाइम "इंजन" के एक पोर्ट पर निर्मित वैकल्पिक तिथि और टाइम लाइब्रेरी लेकिन शीर्ष पर एक नया (और लीनर) API के साथ।

कुछ बिंदु जिनके बारे में आप सोचना चाहते हैं, जिन्हें याद रखना आसान है यदि आप उनके बारे में नहीं जानते हैं:

  • किसी विशेष समय क्षेत्र में किसी स्थानीय दिनांक / समय को मैप करना उतना सरल नहीं है जितना आप सोच सकते हैं। दिन के उजाले की बचत के कारण एक विशिष्ट स्थानीय तिथि / समय एक बार, दो बार (अस्पष्टता) या शून्य समय (इसे छोड़ दिया गया) हो सकता है
  • समय क्षेत्र ऐतिहासिक रूप से भिन्न होते हैं - TimeZoneInfoआम तौर पर प्रकट करने के लिए तैयार से अधिक है , स्पष्ट रूप से। (यह एक समय क्षेत्र का समर्थन नहीं करता है जिसका विचार "मानक समय" समय के साथ बदलता है, या जो स्थायी डेलाइट सेविंग टाइम में चला जाता है)।
  • ज़ोनइनफो डेटाबेस के साथ भी, टाइम ज़ोन आईडी जरूरी स्थिर नहीं हैं। (सीएलडीआर इसे संबोधित करता है; मैं अंत में नोदा समय में समर्थन की उम्मीद कर रहा हूं।)
  • दिनांक और समय का शाब्दिक निरूपण एक बुरा सपना है, न केवल आदेश देने के संदर्भ में, बल्कि तिथि विभाजक, समय विभाजक, और अजीब बातें जैसे कि मूल महीने के नाम
  • दिन की शुरुआत हमेशा आधी रात को नहीं होती है - ब्राजील में, उदाहरण के लिए, स्प्रिंग डेलाइट सेविंग ट्रांजिशन दीवार घड़ी को रात 11:59:59 बजे से दोपहर 1 बजे तक चलती है
  • कुछ मामलों में (अच्छी तरह से, जिसके बारे में मुझे पता है) एक समय क्षेत्र को पूरा दिन छोड़ देने के लिए मजबूर कर सकता है - दिसंबर 30 2011 2011 समोआ में नहीं हुआ था! मुझे संदेह है कि अधिकांश डेवलपर्स शायद इसे अनदेखा कर सकते हैं, लेकिन ...
  • यदि आप ग्रेगोरियन के अलावा एक कैलेंडर का उपयोग करने जा रहे हैं, तो सावधान रहें और सुनिश्चित करें कि आप वास्तव में जानते हैं कि आप इसे कैसे व्यवहार करने की उम्मीद करते हैं।

जहाँ तक विशिष्ट विकास पद्धतियाँ हैं:

  • इस बारे में सोचें कि आप वास्तव में क्या प्रतिनिधित्व करने की कोशिश कर रहे हैं। मुझे उम्मीद है कि डेवलपर्स को अपने डेटा का प्रतिनिधित्व करने के लिए विभिन्न प्रकारों के बीच चयन करने के लिए मजबूर करने के लिए Noda Time का मुख्य लाभ होगा। उस अधिकार को प्राप्त करें, और बाकी सब कुछ सरल है।
  • यूनिट परीक्षण सब कुछ आप के बारे में सोच सकते हैं। यह इस बात पर निर्भर करेगा कि आपका सिस्टम निश्चित रूप से क्या करता है, लेकिन विशेष रूप से अलग-अलग समय क्षेत्रों पर विचार करें, दिन के उजाले की बचत में क्या होता है, और निश्चित रूप से लीप वर्ष।
  • मैं "क्लॉक-लाइक इंटरफ़ेस" इंजेक्ट करने की सलाह दूंगा - जो वर्तमान समय को बताने के लिए एक सेवा है - बजाय स्पष्ट रूप से कॉल करने के DateTime.Nowया DateTime.UtcNow; यह इकाई परीक्षण के लिए आसान (व्यवहार्य!) बनाता है
  • यदि आप "अब" के साथ कई ऑपरेशन कर रहे हैं, तो उस तारीख / समय को एक बार प्राप्त करें और इसे याद रखें, बजाय "अब" का अनुरोध करने के - अन्यथा मूल्य कॉल के बीच दुर्भाग्यपूर्ण तरीके से बदल सकता है।
  • "क्या सब कुछ UTC में है" हमेशा इसका उत्तर नहीं होता है - अगर मैं जानना चाहता हूँ "जब मेरे स्थानीय समय क्षेत्र में 'अभी से दो सप्ताह बाद' होता है?" फिर मुझे स्थानीय दिनांक / समय के साथ-साथ समय क्षेत्र को संग्रहीत करने की आवश्यकता है ।

2
@flq: फिर से, आपको "लीप-ईयर सेफ" से ठीक उसी तरह परिभाषित करने की आवश्यकता है, जिसका आप मतलब रखते हैं। मुझे संदेह है कि यह एक फ्रेमवर्क बग था, जो एज़्योर में समस्या का कारण था - मुझे उम्मीद है कि यह फ्रेमवर्क का खराब उपयोग था ।
जॉन स्कीट

10
लीप वर्ष के विषय (अर्थात विषय) पर एक भी विज्ञापन के बिना उमाप्टीन बुलेट विज्ञापन। और फिर ट्विटर पर पफैसला किया। मुझे लगता है कि आपके पास बेहतर क्षण थे, जॉन।
विल डीन

8
@WillDean: यह भी ध्यान दें कि प्रश्न को जॉर्ज स्टॉकर द्वारा संपादित किया गया था। जो मामले में मुझे लगता है कि आप इस बात से सहमत हूँ मेरी पोस्ट - मूल शीर्षक "दिनांक समय कीड़े के खिलाफ रक्षात्मक प्रोग्रामिंग" था है पूरी तरह से प्रासंगिक है। (मैंने केवल यह देखा कि शीर्षक बदल दिया गया था। जब मैंने उत्तर देना शुरू किया तो डेटटाइम कहा ...)
जॉन स्कीट

2
जॉन, क्षमा करें, मैंने पिछला शीर्षक नहीं देखा था! हो सकता है कि यह सभी उत्तरों को संपादित करने के लिए किसी शीर्षक को बदलने वाले पर अवलंबी होना चाहिए ...
डीन

3
@WillDean: हां ... मैं या तो शीर्षक परिवर्तन को वापस लेने के लिए लुभा रहा हूं या इसे "डेटाइम बग्स (जैसे लीप ईयर्स)" के साथ समाप्त करना चाहता हूं
जॉन स्कीट

25

यह ध्यान देने योग्य है कि बग शायद आपके द्वारा पोस्ट की गई रेखा के कारण नहीं था:

DateTime.Now.AddYears(1)

वह अमान्य दिनांक नहीं बनाता है। यदि आप चलाते हैं:

(new DateTime(2012, 2, 29)).AddYears(1)

आप 28 फरवरी, 2013 को प्राप्त कर रहे हैं। मुझे नहीं पता कि एज़्योर का अतिथि एजेंट क्या लिखा है, लेकिन यह एक अलग कॉल रहा होगा जो विफल रहा। .NET में ऐसा करने का एक बुरा तरीका है:

new DateTime(today.Year + 1, today.Month, today.Day)

यदि todayलीप दिन है तो यह एक अपवाद फेंकता है। हालाँकि Azure समस्या के बारे में Microsoft ब्लॉग ने कहा कि उन्होंने 29 फरवरी, 2013 को एक अमान्य तारीख बनाई, जो मुझे यकीन नहीं है कि DateTime.NET में संभव है ।

मैं यह नहीं कह रहा हूं DateTimeऔर DateTimeOffsetत्रुटि-रहित नहीं हैं, बस मुझे नहीं लगता कि वे इस विशेष मुद्दे का कारण बनेंगे।


मुझे लगता है कि यह C ++ में किया गया था
PhilPursglove

2
@PhilPursglove: आपको क्या लगता है? विंडोज ओएस को ज्यादातर C और C ++ में लिखा गया था और लीप दिनों को ठीक से हैंडल करता है। स्थानांतरण प्रमाणपत्र निर्माण प्रक्रिया में तारीख से संबंधित विफलता के साथ ऐसा करना शायद अधिक था।
सिलिको

क्या यह एक तार से एक तारीख को पार्स कर सकता है?
फिक्सर

और हाँ आप AddYears (1) के बारे में सही हैं जैसा आपने बताया। मुझे यकीन नहीं है कि आंतरिक रूप से क्या हुआ। ब्लॉग पोस्ट में बहुत गहराई तक जाने के बिना यह प्रश्न को थोड़ा परिप्रेक्ष्य देने का प्रयास था।
फिक्सर

यह समझ में आता है। मैं ईमानदारी से नहीं जानता कि क्या यह मामला था, लेकिन विश्वसनीय है। मैंने बड़ी कंपनियों से गंदा कोड देखा है, जिसमें एमएस भी शामिल है। लेकिन फिर, हम वास्तव में बहुत कुछ नहीं कर सकते, लेकिन इस बिंदु पर अटकलें लगा सकते हैं।
अल्फा

2

हम लीप ईयर बग्स से बचाने के लिए कैसे कोडिंग प्रथाओं को विकसित कर सकते हैं? क्या कोडिंग प्रथाओं को रोका जा सकता था?

जॉन द्वारा बताई गई यूनिट की विशिष्ट तिथियों का परीक्षण एक कोड अभ्यास है जो कि किसी भी चीज की सहायता नहीं करेगा, जिसे मैं 'मैनुअल एकीकरण परीक्षण' के रूप में परिभाषित करता हूं।

अपने विकास / परीक्षण किए गए सर्वर पर घड़ी बदलें और देखें कि जब समय टिक जाता है तो क्या होता है।

चाहे वह 'कोडिंग प्रैक्टिस' हो या न हो, इस बारे में बताएं - जाहिर तौर पर आप कैलेंडर पर हर तारीख के लिए ऐसा नहीं कर सकते - उन तारीखों को चुनें जिनसे आप चिंतित हैं, 29 वें फरवरी को, महीने के अंत में तारीख या दिन के उजाले बचत बदलाव की तारीखें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.