आप डेटाबेस में "फ़ज़ी डेट्स" को कैसे स्टोर करते हैं?


125

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

आप दिनांक समय फ़ील्ड का उपयोग नहीं कर सकते, क्योंकि "मई 1978" एक वैध तिथि नहीं है। यदि आप इसे कई कॉलम में विभाजित करते हैं, तो आप क्वेरी करने की क्षमता खो देते हैं। क्या किसी और ने इसमें भाग लिया है, यदि हां तो आपने इसे कैसे संभाला है?

मेरे द्वारा बनाई जा रही प्रणाली को स्पष्ट करने के लिए, यह एक प्रणाली है जो अभिलेखागार को ट्रैक करती है। कुछ सामग्री का उत्पादन बहुत पहले किया गया था, और जो हम जानते हैं वह "मई 1978" है। मैं इसे 1 मई 1978 के रूप में संग्रहीत कर सकता था, लेकिन केवल यह बताने के लिए कि यह तिथि केवल महीने के लिए सही है। इस तरह से कुछ साल बाद जब मैं उस संग्रह को पुनः प्राप्त कर रहा हूँ, तो मैं भ्रमित नहीं होता जब तारीखें मेल नहीं खातीं।

मेरे उद्देश्यों के लिए, "मई 1978 में अज्ञात दिन", "1 मई, 1978" के साथ अंतर करना महत्वपूर्ण है। इसके अलावा, मैं "0 मई, 1978" की तरह अज्ञात को संग्रहीत नहीं करना चाहता, क्योंकि अधिकांश डेटाबेस सिस्टम इसे अमान्य दिनांक मान के रूप में अस्वीकार कर देंगे।


14
क्या "1 मई, 1978" के साथ "अज्ञात दिन मई 1978 में" अंतर करना महत्वपूर्ण है?

5
@ मिचेल्ट: हां, अंतर करना महत्वपूर्ण है।
nbv4


6
@aslum: अधिकांश डेटाबेस सिस्टम अस्वीकार कर देंगे कि अमान्य दिनांक मान के रूप में
nbv4

9
@ जिमीहॉफ़ा - आप कभी भी फ़ज़ी तिथियों के परिदृश्य में नहीं चले हैं, या जहाँ आपको तारीखों की तुलना करने की आवश्यकता है? किसी भी मामले में, एक आम एक चिकित्सा इतिहास है: आपको याद है कि एपेन्डेक्टॉमी पिछले साल 1 अप्रैल को थी, लेकिन टॉन्सिलैक्टोमी 1975 में कभी-कभी हुई थी, और कुछ अन्य वर्ष के मई और जून के दौरान कुछ और हुआ। क्या होगा यदि आप जानना चाहते हैं कि कुछ चिकित्सा घटना कुछ अन्य चिकित्सा सफलता से पहले या बाद में थी? क्या इससे पहले या बाद में वे एचआईवी के लिए रक्त की आपूर्ति की जांच कर रहे थे?
थर्सडेजेक

जवाबों:


148

डेटाबेस में सभी तिथियों को सामान्य DATE फ़ील्ड में संग्रहीत करें और अतिरिक्त सटीकता फ़ील्ड है कि वास्तव में DATE फ़ील्ड कितनी सटीक है।

date_created DATE,
date_created_accuracy INTEGER, 

date_created_accuracy: 1 = सटीक दिनांक, 2 = महीना, 3 = वर्ष।

यदि आपकी तारीख फ़र्ज़ी है (उदाहरण के लिए मई 1980) तो इसे अवधि की शुरुआत में स्टोर करें (उदाहरण 1 मई 1980)। या यदि आपकी तिथि वर्ष के लिए सटीक है (उदाहरण के लिए 1980) तो इसे 1 जनवरी को संग्रहीत करें। 1980 इसी सटीकता मूल्य के साथ।

यह तरीका कुछ हद तक स्वाभाविक तरीके से आसानी से क्वेरी कर सकता है और अभी भी धारणा है कि तारीखें कितनी सटीक हैं। उदाहरण के लिए यह आप के बीच तारीखों क्वेरी करने के लिए अनुमति देता है Jan 1st 1980और Feb 28th 1981, और फजी दिनांकों पाने 1980और May 1980


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

8
अच्छा जवाब, वास्तव में स्मार्ट। select * from mytable where date_created between "1980/1/1" and "1981/2/28" and date_created_accuracy <= 2;। प्रतिभा।
नातुल्ली काई

58
मैं आपको तारीख की सटीकता पर विचार करने के लिए प्रोत्साहित करूंगा। जहां एक सटीक दिन 0. है। इस तरह से एक और अधिक लचीली तिथियों का उपयोग "गर्मियों में कभी-कभी" कर सकते हैं, जिसमें हार्ड एन्कोडेड विशिष्ट तिथि सीमाओं के बजाय 1 जून से 90 दिनों की तारीख सटीकता है। यह बहु-वर्षीय सटीकता को भी संभाल सकता है।

1
आपको शायद एक जवाब के रूप में प्रस्तुत करना चाहिए, MichaelT
Supr

1
+1: इस समाधान के बारे में एक और अच्छी बात यह है कि आप date_created_accuracyक्षेत्र के मूल्य के आधार पर प्रदर्शन तर्क जोड़ सकते हैं । आप "मई 1980" या सिर्फ "1980" परिणाम या यूआई में दिखा सकते हैं यदि यह उतना ही सटीक है जितना क्षेत्र इंगित करता है।
Kyralessa

27

यदि आपको इस तरह के डेटा को नियमित तिथि-समय की जानकारी के रूप में उपयोग करने की आवश्यकता नहीं है, तो कोई भी सरल स्ट्रिंग प्रारूप होगा।

लेकिन अगर आपको सभी कार्यक्षमता रखने की आवश्यकता है, तो दो वर्कअराउंड हैं जो मैं सोच सकता हूं, दोनों को डेटाबेस में संग्रहीत अतिरिक्त जानकारी की आवश्यकता है:

  1. "अपूर्ण" डेटा के लिए भिन्न मान बनाएं min dateऔर max dateफ़ील्ड बनाएं , लेकिन सटीक तिथियों के लिए मेल खाएंगे।
  2. प्रत्येक प्रकार की त्रुटिपूर्ण तारीख के लिए प्रकार बनाएं (कोई नहीं 0, दिनांक_missing _ 1, month_missing _ 2, year_missing_4, आदि _ ताकि आप उन्हें जोड़ सकें)। typeअभिलेखों में एक फ़ील्ड जोड़ें और कौन सी जानकारी गायब है।

न्यूनतम और अधिकतम दिनांक फ़ील्ड मेरे पहले विचार थे।
माइकल इट्ज़ो

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

4
+1 के लिए min dateऔर max dateक्षेत्रों। मुझे लगता है कि यह सबसे लचीला है, फिर भी समाधान का उपयोग करने के लिए सटीक और आसान है।
सुप्रीत 9'13

1
मैं पहले इस विचार के विरोधी था। लेकिन इसे साकार करना सबसे लचीला दृष्टिकोण है, मैं इसके लिए वोट करता हूं।
अनुराग कालिया

यह केवल प्राकृतिक है। आप इतनी फ़र्ज़ी तारीख नहीं बल्कि एक टाइमफ़्रेम का वर्णन कर रहे हैं ..... जिसमें एक शुरुआत और एक अंत है।
पीटर बी

20

यह वास्तव में तकनीकी समस्या की तुलना में आवश्यकताओं की अधिक परिभाषा है - जिस पर आपको ध्यान देने की आवश्यकता है वह यह है कि "हम अतीत में तारीखों को कैसे परिभाषित कर सकते हैं" और तकनीकी समाधान बह जाएगा।

समय के लिए मुझे कुछ इस तरह से दृष्टिकोण करना पड़ा है:

  • चीजों को मैप करने के तरीके को परिभाषित करें - जैसे माइकलटी सुझाव देते हैं , यह तय करें कि जो कुछ भी महीना / दिन के रूप में परिभाषित किया गया है वह उक्त महीने की 1 तारीख को आधी रात के रूप में परिभाषित हो। यह आम तौर पर अधिकांश उद्देश्यों के लिए पर्याप्त है - यदि सही तारीख महत्वपूर्ण थी तो संभवतः आपके पास 35 साल बाद इसका रिकॉर्ड होगा, है ना?
  • यह पता लगाने के लिए कि क्या आपको यह ट्रैक करने की आवश्यकता है - IE, थोड़ा बनाए गए तारीखों के साथ रिकॉर्ड करते हैं क्या ऐसा कहने के लिए ध्वज की आवश्यकता है? या यह है कि सिर्फ एक उपयोगकर्ता प्रशिक्षण मुद्दा है ताकि लोगों को पता है और तदनुसार कार्य कर सकते हैं।

कभी-कभी किसी को कुछ करने की ज़रूरत होती है जैसे तारीखों को फ़र्ज़ी बनाना - उदाहरण के लिए, मई 1978 में किसी भी चीज़ के लिए एक तारीख का जवाब देना पड़ सकता है। यह उल्लेखनीय है - बस अपने create_date को 2 फ़ील्ड बनाएं, पुराने रिकॉर्ड को 30 प्राप्त करें दिन उपयुक्त के रूप में फैल गए, नए लोगों को 2 समान मूल्य मिलते हैं।


1
+1 - मैं दोहरी तिथि दृष्टिकोण के साथ उत्तर तैयार करने पर काम कर रहा था। आपका जवाब पहले यहाँ मिल गया।

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

3
@ इज़कट - फेयर पॉइंट, लेकिन जब आप कुछ ऐसा करने की ज़रूरत होती है, तो आप कितने खूबसूरत हो सकते हैं, जो एक महीने में एक ही बार होना चाहिए। निश्चित रूप से कहीं न कहीं मक्खी पर प्रश्नों के लिए शुरुआत और अंत की गणना करने की तुलना में पूर्ववर्ती है।
व्याट बार्नेट

1
+1 ईनम मानों के विस्फोट के बिना मनमानी ग्रैन्युलैरिटी को निरूपित करने में सक्षम होने के लिए।
डैन नीली

18

यदि तिथि सही है, तो निरूपित करने का सबसे सरल तरीका एक सटीकता फ़ील्ड INT (1) डिफ़ॉल्ट NULL बनाना है

यदि दिनांक "date_created" में सटीक स्टोर दिनांक-समय है और सटीकता NULL को छोड़ दें

यदि दिनांक 1 महीने की सटीकता के साथ 1 माह के रूप में माह-समय स्टोर करने के लिए सटीक है

यदि दिनांक सटीकता के मान 2 के साथ दिनांक 1 जनवरी के वर्ष के स्टोर-टाइम के लिए केवल सटीक है

आप अलग-अलग संख्याओं का उपयोग विभिन्न मूल्यों जैसे कि पहली तिमाही आदि के लिए कर सकते हैं


जब आप ऐसा करते हैं तो क्वेरी वास्तव में बालों वाली हो जाती है।
ब्लरफ्ल

3
इससे ऐसे डेटा की कठिनाई होती है जो "Q2 1991" और "विंटर 1978-1979" जैसी साफ महीने की सीमा पर नहीं है।

1
ओपी यह बताना चाहता है कि यह तारीख केवल महीने के लिए सही है।
दाविद स्ट्रकैन

7
आप यहाँ NULL का अर्थ गाली दे रहे हैं। NULL का अर्थ है "अज्ञात", इसलिए यदि तिथि सटीक है, तो सटीकता NULL नहीं हो सकती है। यह '1' हो सकता है।
कोनरक

@Konerak शब्दार्थ हाँ। लेकिन अधिकांश तिथियां सटीक होती हैं, केवल विशेष मामलों को पहचानने की आवश्यकता होती है और NULL का उपयोग डिफ़ॉल्ट रूप से किया जाता है।
दाविद स्ट्रकैन

17

अतीत में मैंने तारीखों-सटीकता को एक आरंभ तिथि और अंतिम तिथि के रूप में संग्रहीत किया है। दिन मई 21,2012 को प्रारंभ = 12 am,2121,2012 और अंत = 12 am,may22,2012 के रूप में दर्शाया जाएगा। वर्ष २०१२ को शुरुआत के रूप में दर्शाया जाएगा = १२ बजे १,२०१२ अंत = १२ जज १,२०१३।

मुझे यकीन नहीं है कि मैं इस दृष्टिकोण की सिफारिश करूंगा। उपयोगकर्ता को जानकारी प्रदर्शित करते समय आपको ठीक से पता लगाने की आवश्यकता होती है कि दो ओवर-विशिष्ट एंडपॉइंट्स (जिसका अर्थ है दिन की बचत और इसके बाद से निपटने का मतलब है) के बजाय "25 मई" दिखाने के लिए एक तिथि सीमा वास्तव में एक दिन को कवर करती है।

हालाँकि, जब आप मानव अनुवाद करने की कोशिश नहीं कर रहे हैं, तो केंद्र + सटीकता के साथ समापन बिंदु के साथ प्रोग्रामिंग बहुत आसान है। आप बहुत सारे मामलों को समाप्त नहीं करते हैं। यह बहुत अच्छा है।


वास्तव में, यह निर्धारित करने के लिए इतना पेचीदा होने की आवश्यकता नहीं है कि किसी श्रेणी को कैसे प्रस्तुत किया जाए यदि रेंज हमेशा यूटीसी के रूप में संग्रहीत हो। यूटीसी टाइमस्टैम्प के रूप में, हर दिन, सप्ताह, महीने, वर्ष - यहां तक ​​कि मौसम और तिमाहियों - अवधि की शुरुआत और अंत का प्रतिनिधित्व करने वाले दो स्थिर, वैश्विक, अलग और आसानी से निर्धारक संख्याएं होंगी। तर्क बस कुछ ही अगर बयानों को देखने के लिए बन जाता है कि दोनों तारीखें किसी प्रकार की अवधि की शुरुआत और अंत में हैं या नहीं। कोई जटिल गणित या टाइम ज़ोन सामान की आवश्यकता नहीं है :)
Supr

@Srr यह निर्धारित करना कि किसी विशेष मानव काल की सीमा पर कोई विशेष दूसरा है, अपने आप में, एक कठिन समस्या है। विशेष रूप से दीर्घावधि में, पृथ्वी के घूमने की गति धीमी हो जाती है और स्थानीय समय की मानव परिभाषा में छोटे परिवर्तन हो जाते हैं।
क्रेग गिदनी

14

दो खजूर क्यों नहीं स्टोर किए।

बनाया गया। इसके बाद और बनाया गया। "या बाद में" और "पर या पहले बनाया गया" वास्तविक शब्दार्थ

इसलिए अगर आपको सही तारीख पता है तो Created_After और Created_Before एक ही तारीख होगी।

यदि आप जानते हैं कि यह मई 2000 में पहला सप्ताह था तो Created_After = '2000-05-01' और Created_Before = '2000-05-07'।

यदि आप सिर्फ मई 1999 जानते हैं तो मान '1999-05-01' और '1999-05-30' होंगे।

यदि यह "'42 की समर" है तो मान '1942-06-01' और '1942-08-31' होंगे।

यह स्कीमा सामान्य एसक्यूएल के साथ क्वेरी करने के लिए सरल है, और गैर तकनीकी उपयोगकर्ता के लिए काफी आसान है।

उदाहरण के लिए सभी दस्तावेजों को खोजने के लिए हो सकता है मई 2001 में बनाया गया है:

SELECT * FROM DOCTAB WHERE Created_After < '2001-05-31' And Created_Before > 2001-05-01;

मई 2001 में निश्चित रूप से बनाए गए सभी दस्तावेजों को खोजने के लिए इसके विपरीत :

SELECT * FROM DOCTAB WHERE Created_After > '2001-05-01' And Created_Before < 2001-05-31;

1
मुझे लगता है कि यह सबसे सुंदर समाधान है।
Pieter B

यह सुपरएम और स्ट्रिलैंक के उत्तरों के समान है। +1 हालांकि अधिक स्पष्ट रूप से समझाने और यह बताने के लिए कि यह क्वेरी के लिए कितना सरल होगा।
सुप्रीत

9

आईएसओ 8601 दिनांक समय प्रारूप अवधि परिभाषा के साथ आता है, उदाहरण के लिए

2012-01-01P1M (पढ़ें: 2012, पहली जनवरी, अवधि: 1 महीना) "जनवरी 2012 में" क्या होना चाहिए।

मैं इसका उपयोग डेटा को स्टोर करने के लिए करूंगा । ऐसा करने के लिए आपको स्ट्रिंग के डेटाबेस फ़ील्ड की आवश्यकता हो सकती है। यह एक अलग विषय है कि उस पर एक समझदार खोज कैसे की जाए।


विचार के लिए +1 लेकिन खोज और / या खोजने के लिए कारण के लिए दिनांक फ़ील्ड का उपयोग न करने के लिए -1
user151019

डेटाबेस पर निर्भर करता है। हालांकि यह विस्तार का आधार हो सकता है, लेकिन सवाल यह है कि क्या परिणाम में दस्तावेज़ सेट है यदि आप खोजते हैं, तो इस मामले में, सभी दस्तावेज 12 जनवरी की तुलना में नए हैं, या यह नहीं है? यह तुच्छ नहीं है। यहाँ, यह सवाल था कि फ़ज़ी तारीखों को कैसे संग्रहीत किया जाए
मथायस रेन्ज

3

आम तौर पर, मैं अभी भी उन्हें सामान्य क्वेरी बिसनेस की तारीखों के रूप में संग्रहीत करता हूं, भले ही थोड़ा कम सटीक हो।

यदि यह जानना महत्वपूर्ण है कि मेरे पास अतीत में या तो सटीकता "विंडो" संग्रहीत है या तो +/- दशमलव के रूप में या एक लुकअप (दिन, महीने, वर्ष, आदि) के रूप में। खिड़की के बजाय अन्य मामलों में मैं सिर्फ मूल तिथि मान को एक स्ट्रिंग के रूप में संग्रहीत करता हूं और जो मैं कर सकता हूं उसे एक डेटाइम में परिवर्तित कर सकता हूं, संभवतः 1978-05-01 00:00:00 और "मई 1978" आपके दिए गए उदाहरण के लिए।


3

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

कौन कहता है? यहाँ आप क्या करते हैं:

  1. 3 कॉलम, दिन, महीना, वर्ष, प्रत्येक इंट प्रकार, और एक चौथा कॉलम TheDate of DateTime प्रकार का है।
  2. एक ट्रिगर है जो थ्रेड बनाने के लिए 3 कॉलम डे, मंथ, ईयर का उपयोग करता है यदि TheDate को शून्य छोड़ दिया जाता है, लेकिन डे, मंथ, ईयर फील्ड्स में से एक या एक से अधिक है।
  3. एक ट्रिगर है जो दिन, महीने, वर्ष फ़ील्ड्स को आबाद करता है जब TheDate की आपूर्ति की जाती है लेकिन ये फ़ील्ड नहीं हैं।

इसलिए अगर मैं एक प्रविष्टि करता हूं: insert into thistable (Day, Month, Year) values (-1, 2, 2012);तो TheDate 2/1/2013 हो जाएगा, लेकिन मुझे डे फील्ड में -1 की वजह से 2/2012 में वास्तव में एक अनिश्चित तिथि पता चल जाएगी।

अगर मैं insert into thistable (TheDate) values ('2/5/2012');दिन ५ होगा, महीना २ होगा, और वर्ष २०१२ होगा और क्योंकि उनमें से कोई भी नहीं है -१ मुझे पता है कि यह सटीक तारीख है।

मैं क्वेरी करने की क्षमता नहीं खोता क्योंकि इन्सर्ट / अपडेट ट्रिगर से मेरे 3 क्षेत्र (दिन, महीने, वर्ष) हमेशा TheDate में एक डेटटाइम मान उत्पन्न करते हैं, जिसे क्वेर किया जा सकता है।


3

एक अन्य विकल्प यह होगा कि फॉर्म के पूर्णांक के रूप में तारीखों को संग्रहीत किया जाए YYYYMMDD

  • आप केवल वर्ष 1951: स्टोर के रूप में जानते हैं 19510000
  • आप जानते हैं कि महीना और वर्ष मार्च 1951 है: स्टोर के रूप में 19510300
  • आप जानते हैं कि पूरी तारीख 14 मार्च, 1951: स्टोर है 19510314
  • एक पूरी तरह से अज्ञात तारीख: स्टोर के रूप में 0

लाभ

आप अपनी फ़ज़ी तारीख को दो फ़ील्ड फ़ील्ड या किसी दिनांक के बजाय एक फ़ील्ड में संग्रहीत कर सकते हैं और अन्य उत्तर सुझा सकते हैं।

प्रश्न अभी भी आसान हैं:

  • वर्ष 1951 के सभी रिकॉर्ड - SELECT * FROM table WHERE thedate>=19510000 and thedate<19520000
  • मार्च 1951 के सभी रिकॉर्ड - SELECT * FROM table where thedate>=19510300 and thedate<19510400
  • 14 मार्च, 1951 के सभी रिकॉर्ड - SELECT * FROM table where thedate=19510314

टिप्पणियाँ

  • आपके जीयूआई GetDateString(int fuzzyDate)को लागू करने के लिए बहुत आसान है।
  • इंट फॉर्मेट के साथ छंटनी आसान है। आपको पता होना चाहिए कि अज्ञात तिथियां पहले आएंगी। आप महीने या दिन के 99बजाय 'पैडिंग' के लिए उपयोग करके इसे उलट सकते 00हैं।

आप "1941-1942 की सर्दियों" की फजी तारीख का प्रतिनिधित्व कैसे करते हैं? यह दिसंबर 1941 या जनवरी 1942 हो सकता है।

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

1

आईएसओ 8601 भी "फजी तारीखों" के लिए एक वाक्यविन्यास निर्दिष्ट करता है। 12 फरवरी, 2012 को दोपहर 3 बजे "2012-02-12T15" होगा और फरवरी 2012 बस "2012-02" हो सकता है। यह मानक लेक्सोग्राफिक छँटाई का उपयोग करते हुए अच्छी तरह से फैली हुई है:

$ (echo "2013-03"; echo "2013-03"; echo "2012-02-12T15"; echo "2012-02"; echo "2011") | sort
2011
2012
2012-02
2012-02-12T15
2013-03

0

यहाँ मेरा इस पर ले रहा है:

फ़ज़ी डेट से डेटाइम ऑब्जेक्ट पर जाएं (जो डेटाबेस में फिट होगा)

import datetime
import iso8601

def fuzzy_to_datetime(fuzzy):
    flen = len(fuzzy)
    if flen == 4 and fuzzy.isdigit():
        dt = datetime.datetime(year=int(fuzzy), month=1, day=1, microsecond=111111)

    elif flen == 7:
        y, m = fuzzy.split('-')
        dt = datetime.datetime(year=int(y), month=int(m), day=1, microsecond=222222)

    elif flen == 10:
        y, m, d = fuzzy.split('-')
        dt = datetime.datetime(year=int(y), month=int(m), day=int(d), microsecond=333333)

    elif flen >= 19:
        dt = iso8601.parse_date(fuzzy)

    else:
        raise ValueError("Unable to parse fuzzy date: %s" % fuzzy)

    return dt

और फिर एक फ़ंक्शन जो डेटाइम ऑब्जेक्ट लेता है, और इसे फ़ज़ी दिनांक में वापस ले जाता है।

def datetime_to_fuzzy(dt):
    ms = str(dt.microsecond)
    flag1 = ms == '111111'
    flag2 = ms == '222222'
    flag3 = ms == '333333'

    is_first = dt.day == 1
    is_jan1 = dt.month == 1 and is_first

    if flag1 and is_jan1:
        return str(dt.year)

    if flag2 and is_first:
        return dt.strftime("%Y-%m")

    if flag3:
        return dt.strftime("%Y-%m-%d")

    return dt.isoformat()

और फिर एक इकाई परीक्षण। क्या मुझे कोई केस याद आया?

if __name__ == '__main__':
    assert fuzzy_to_datetime('2001').isoformat() == '2001-01-01T00:00:00.111111'
    assert fuzzy_to_datetime('1981-05').isoformat() == '1981-05-01T00:00:00.222222'
    assert fuzzy_to_datetime('2012-02-04').isoformat() == '2012-02-04T00:00:00.333333'
    assert fuzzy_to_datetime('2010-11-11T03:12:03Z').isoformat() == '2010-11-11T03:12:03+00:00'

    exact = datetime.datetime(year=2001, month=1, day=1, microsecond=231)
    assert datetime_to_fuzzy(exact) == exact.isoformat()

    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=1, day=1, microsecond=111111)) == '2001'
    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=3, day=1, microsecond=222222)) == '2001-03'
    assert datetime_to_fuzzy(datetime.datetime(year=2001, month=6, day=6, microsecond=333333)) == '2001-06-06'

    assert datetime_to_fuzzy(fuzzy_to_datetime('2002')) == '2002'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2002-05')) == '2002-05'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2002-02-13')) == '2002-02-13'
    assert datetime_to_fuzzy(fuzzy_to_datetime('2010-11-11T03:12:03.293856+00:00')) == '2010-11-11T03:12:03.293856+00:00'

एक कोने का मामला है जहां एक घटना जो ठीक से हुई, 2001-01-01T00:00:00.333333लेकिन सिस्टम सिर्फ "2001" होने के रूप में व्याख्या करेगा, लेकिन यह बहुत संभावना नहीं है।


0

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

date date
dateCirca enum('Y', 'N')

हम किसी घटना की तारीख या उस तारीख को इंगित करने के लिए दिनांक फ़ील्ड का उपयोग करते हैं जो उस स्थिति में "पर्याप्त रूप से बंद" होती है, जहां हमें सही तिथि नहीं पता होती है। इस घटना में कि हमें सही तारीख का पता नहीं है, हम इस dateCircaक्षेत्र को चिह्नित करते हैं Yऔर एक पर्याप्त तारीख देते हैं, जिसे "1" के रूप में चिह्नित किया जाता है, जैसे कि

1st March, 2013  // We don't know the day of the month
1st January, 2013  // We don't know the month/day of the year
1st January, 2000  // We don't know the month/day/year, we only know the century

0

अवलोकन

कई संभावित निरूपण हैं, और इस प्रकार डेटाबेस स्कीमा, फजी तारीख-समय (या यहां तक ​​कि सिर्फ फजी तिथियां) के भंडारण के लिए हैं:

  1. दिनांक-समय और कोड इसकी सटीकता या सटीकता का संकेत देते हैं
  2. दिनांक-समय और अंतराल जहां एक अंतराल का प्रतिनिधित्व करने के लिए कई संभावनाएं हैं:
    1. किसी निश्चित इकाई के पूर्णांक (या अन्य संख्यात्मक) मात्रा के रूप में सभी अंतरालों का प्रतिनिधित्व करते हैं, जैसे दिन, मिनट, नैनोसेकंड।
    2. एक पूर्णांक (या अन्य संख्यात्मक) मात्रा और इसकी इकाइयों को इंगित करने वाले कोड के रूप में एक अंतराल का प्रतिनिधित्व करते हैं।
  3. प्रारंभ और समाप्ति तिथि बार
  4. तार
  5. संभावना वितरण:
    1. उन मापदंडों के लिए दशमलव या फ्लोटिंग-पॉइंट मात्राएं जो किसी विशेष परिवार में एक विशिष्ट वितरण को निर्दिष्ट करती हैं, उदाहरण के लिए सामान्य वितरण का औसत और मानक विचलन।
    2. संभाव्यता वितरण फ़ंक्शन, उदाहरण के लिए एक (लुकअप) कोड (विशिष्ट मान के मापदंडों के साथ), या एक पर्याप्त रूप से अभिव्यंजक भाषा, प्रारूप या प्रतिनिधित्व में एक अभिव्यक्ति के रूप में।

[१], [२], और [३] सभी (अव्यवस्थित रूप से) समान अंतराल यानी समय में (समान रूप से) संभव बिंदुओं का एक सेट है।

[४] सबसे अधिक अभिव्यंजक है, यानी किसी भी संभव (या कम से कम मनमाने ढंग से) लिखित भाषा के वाक्यों या वाक्यांशों की अनुमति देते समय। लेकिन इसके साथ काम करना सबसे कठिन है। सीमा में, मानव-स्तरीय AI को मनमाने मूल्यों को संभालने के लिए आवश्यक होगा। व्यावहारिक रूप से, संभावित मूल्यों की सीमा को गंभीर रूप से प्रतिबंधित करने की आवश्यकता होगी, और वैकल्पिक 'संरचित' मूल्यों को संभवतः कई कार्यों के लिए पसंद किया जाएगा, जैसे छँटाई, खोज।

[५] संभवत: सबसे सामान्य कॉम्पैक्ट प्रतिनिधित्व है (कुछ हद तक) व्यावहारिक।

वर्दी का अंतराल

यूनिफ़ॉर्म अंतराल (संभव) दिनांक-समय मानों के एक सेट का प्रतिनिधित्व करने का सबसे सरल कॉम्पैक्ट तरीका है।

[1] के लिए, दिनांक-समय मान के भागों को अनदेखा किया जाता है, अर्थात संकेतित सटीकता या सटीकता की तुलना में इकाइयों के अनुरूप भाग; अन्यथा यह [2] के बराबर है और सटीक / सटीकता कोड समान इकाइयों (और 1 की अनुमानित मात्रा) के साथ अंतराल के बराबर है।

[२] और [३] स्पष्ट रूप से समतुल्य हैं। [1] कड़ाई से कम अभिव्यंजक है या तो प्रभावी अंतराल हैं जिन्हें [1], पूर्व द्वारा प्रतिनिधित्व नहीं किया जा सकता है। एक 12 घंटे के अंतराल के बराबर एक फज़ी तारीख-समय जो एक तारीख सीमा तक फैला है।

[1] उपयोगकर्ताओं के लिए किसी अन्य प्रतिनिधित्व की तुलना में इनपुट करना आसान है और आम तौर पर कम से कम टाइपिंग की आवश्यकता होती है। यदि दिनांक-बार विभिन्न पाठ अभ्यावेदन में इनपुट किया जा सकता है, जैसे "2013", "2014-3", "2015-5-2", "7/30/2016 11 पी", "2016-07-31 18:15" सटीक या सटीकता भी इनपुट से स्वचालित रूप से अनुमान लगाया जा सकता है।

[1] की सटीकता या सटीकता भी उपयोगकर्ताओं को अवगत कराने के लिए एक रूप में परिवर्तित करना सबसे आसान है, उदाहरण के लिए "माह सटीकता के साथ 2015-5" को "मई 2015", बनाम "13 मई 2015 2 पी, प्लस या माइनस 13.5 दिन" (ध्यान दें कि बाद को [1] वैसे भी प्रतिनिधित्व नहीं किया जा सकता है)।

स्ट्रिंग्स

व्यावहारिक रूप से, स्ट्रिंग मानों को क्वेरीज़, सॉर्टिंग या अन्यथा कई मानों की तुलना करने के लिए अन्य अभ्यावेदन में परिवर्तित करना होगा। इसलिए जबकि किसी भी लिखित प्राकृतिक (मानव) भाषा कड़ाई से अधिक अभिव्यंजक है [1], [2], [3], या [5], हमारे पास अभी तक मानक पाठ अभ्यावेदन या स्वरूपों से परे निपटने के साधन नहीं हैं। यह देखते हुए कि, यह संभवतः अपने आप में सबसे कम उपयोगी प्रतिनिधित्व है

इस प्रतिनिधित्व के एक लाभ यह है कि मूल्यों को व्यवहार में होना चाहिए, जैसा कि उपयोगकर्ताओं के लिए प्रस्तुत करने योग्य है और इसे आसानी से समझने के लिए परिवर्तन की आवश्यकता नहीं है।

संभाव्यता वितरण

संभाव्यता वितरण समान अंतराल अभ्यावेदन का सामान्यीकरण करते हैं [1], [२], [३], और (यकीनन) (सामान्य) स्ट्रिंग प्रतिनिधित्व [४] के बराबर हैं।

तार पर संभावना वितरण का एक लाभ यह है कि पूर्व अस्पष्ट है।

[५-१] उन मूल्यों के लिए उपयुक्त होगा जो (अधिकतर) किसी मौजूदा वितरण के अनुरूप हों, उदाहरण के लिए किसी डिवाइस से डेट-टाइम वैल्यू आउटपुट जिसके लिए माप (या सोचा) एक विशिष्ट वितरण के अनुरूप हो।

[5-2] शायद सबसे अच्छा (कुछ) व्यावहारिक तरीका है दृढ़तापूर्वक मनमाना 'फजी datetime' मूल्यों का प्रतिनिधित्व। निश्चित रूप से विशिष्ट संभाव्यता वितरणों की संगणना के मामलों का उपयोग किया जाता है और विभिन्न मूल्यों को क्वेरी करते, छांटते या तुलना करते समय निश्चित रूप से दिलचस्प (और शायद असंभव) समस्याओं को हल किया जाता है, लेकिन इनमें से बहुत संभवत: पहले से ही ज्ञात या मौजूदा में कहीं हल है। गणितीय और सांख्यिकीय साहित्य इसलिए यह निश्चित रूप से एक अत्यंत सामान्य और गैर-अस्पष्ट प्रतिनिधित्व के रूप में खड़ा है।


-1

मुझे वास्तव में जेम्स एंडरसन का समाधान पसंद है - तिथियों को सटीक रूप से बांधना सबसे लचीली क्वेरी संरचना प्राप्त करने का तरीका है। इसे प्राप्त करने का दूसरा तरीका स्टार्ट, एंड या यहां तक ​​कि केंद्र dateप्लस interval(कम से कम पोस्टग्रेक्यूएल , ओरेकल और SQLAlchemy में उपलब्ध ) का उपयोग करना है।


-2

आपके मामले में आपको केवल वर्ष, महीना और दिन चाहिए। वर्ष और माह आवश्यक हैं, दिन वैकल्पिक है। मैं कुछ इस तरह का उपयोग करेंगे:

year smallint not null,
month smallint not null,
day smallint

इसके अलावा, आप अभी भी बहुत प्रभावी ढंग से अनुक्रमित का उपयोग कर सकते हैं। (छोटे = माइनस, कतारें थोड़ी अधिक "जटिल" (लंबी) हो जाती हैं।


1
लेकिन इसका मतलब यह है कि अगर फिज़नेस महीने के हिस्से को भी बढ़ा देता है, तो यह दृष्टिकोण विफल हो जाता है।
अनुराग कालिया

1
@AnuragKalia - तो महीने क्षेत्र को अशक्त बना देते हैं। कोई कारण नहीं कि इसे बाद की तारीख में फिर से जोड़ा जा सके।
जेएफओ

वह सिर्फ एक उदाहरण था। भविष्य की समस्याओं को समायोजित करने के लिए समाधान पर्याप्त सामान्य होना चाहिए। यदि आपके द्वारा निर्दिष्ट सीमा 15 मार्च 2013 से 22 मार्च 2013 तक है, तो यह दृष्टिकोण काम नहीं करता है। ऊपर दिया गया मिन-मैक्स उत्तर अभी तक सबसे सामान्य है।
अनुराग कालिया

1
क्या आपको ओपीएस पोस्ट में ऐसी आवश्यकता मिली है या यह सिर्फ आपका फैंटसी है?
दानूबियन नाविक

महीने को अशक्त बनाना आपको एक दिन निर्दिष्ट करने की अनुमति देता है लेकिन कोई महीना नहीं। कोई मतलब नहीं है। जब था 1978-??-31?
MSalters

-2

मैं बस सामान्य तारीखों के लिए सही समय स्टोर करूंगा और 00:00:00 की तरह फजी तारीख के समय का हिस्सा बनाऊंगा। फिर मैं महीने की 1 तारीख को सभी फजी तारीखें बनाऊंगा।

जब आप प्रश्न करते हैं, तो आप

  1. दिनांक सीमाओं की जाँच करें जहां समय 00:00:00 (फ़ज़ी) के बराबर हो
  2. दिनांक सीमाओं की जाँच करें जहां समय 00:00:00 (वास्तविक) के बराबर नहीं है
  3. दिनांक सीमाओं के लिए जाँच करें लेकिन समय भाग (संयुक्त) को अनदेखा करें

इससे बेहतर समाधान हैं, लेकिन मैं व्यक्तिगत रूप से मेटाडेटा (मेरे डेटा के बारे में डेटा) से नफरत करता हूं। बस थोड़ी देर बाद हाथ से निकलने की आदत है।


2
यह वास्तविक समय 00:00:00 होने की तारीख से कैसे निपटेगा?
gnat

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