COBOL Y2K रिडक्स


36

1990 के दशक में, COBOL कंप्यूटर इंजीनियरों ने छह अंकों की तारीख वाले क्षेत्रों का विस्तार करने के लिए एक तरीके से काम किया और उन्हें यह निर्धारित किया कि वर्ष का दिन YYYDDDकहां YYYहै । यह योजना अधिकतम तिथि बढ़ा सकती है ।year - 1900DDD[001 to 366]2899-12-31

2898 में, इंजीनियरों ने घबराहट शुरू कर दी क्योंकि उनके 900 साल पुराने कोड आधार विफल हो रहे थे। वर्ष 2898 से होने के नाते, उन्होंने इस एल्गोरिथम के साथ वर्ष 1998 में एक अकेला कोडिनेटर भेजने के लिए अपनी समय मशीन का उपयोग किया और इसे यथासंभव व्यापक रूप से कार्यान्वित करने का कार्य किया:

एक योजना का उपयोग PPQQRRकरता है, तो जहां 01 ≤ QQ ≤ 12तो यह एक मानक है YYMMDD1900 के दशक में की तारीख है, लेकिन अगर QQ > 12फिर इसे बाद दिन का प्रतिनिधित्व करता है 2000-01-01के लिए आधार 100 में PPऔर RRलेकिन के लिए आधार 87 QQ - 13

यह योजना वर्ष 2899 से आगे तक फैली हुई है और मानक तिथियों के साथ भी पीछे है, इसलिए मौजूदा अभिलेखागार के किसी भी संशोधन की आवश्यकता नहीं है।

कुछ उदाहरण:

PPQQRR  YYYY-MM-DD
000101  1900-01-01  -- minimum conventional date suggested by J. Allen
010101  1901-01-01  -- edge case suggested by J. Allen
681231  1968-12-31  -- as above
991231  1999-12-31  -- maximum conventional date
001300  2000-01-01  -- zero days after 2000-01-01
008059  2018-07-04  -- current date
378118  2899-12-31  -- maximum date using YYYDDD scheme
999999  4381-12-23  -- maximum date using PPQQRR scheme

आपकी चुनौती PPQQRRआईएसओ तिथि के रूप में इनपुट और आउटपुट को स्वीकार करने के लिए एक कार्यक्रम या फ़ंक्शन लिखना है YYYY-MM-DD। इनपुट विधि पैरामीटर, कंसोल या कमांड लाइन हो सकती है, जो कि सबसे आसान है।

आपके मनोरंजन के लिए, यहाँ COBOL-85 में एक नॉनकमेटिंग समाधान है:

IDENTIFICATION DIVISION.
    PROGRAM-ID. DATE-CONVERSION.
DATA DIVISION.
    WORKING-STORAGE SECTION.
    01 T PIC 9(8).
    01 U PIC 9(8).
    01 D VALUE '999999'. 
        05 P PIC 9(2).
        05 Q PIC 9(2).
        05 R PIC 9(2).
    01 F.
        05 Y PIC 9(4).
        05 M PIC 9(2).
        05 D PIC 9(2).
PROCEDURE DIVISION.
    IF Q OF D > 12 THEN
        MOVE FUNCTION INTEGER-OF-DATE(20000101) TO T
        COMPUTE U = R OF D + 100 * ((Q OF D - 13) + 87 * P OF D) + T
        MOVE FUNCTION DATE-OF-INTEGER(U) TO F
        DISPLAY "Date: " Y OF F "-" M OF F "-" D OF F
    ELSE
        DISPLAY "Date: 19" P OF D "-" Q OF D "-" R OF D 
    END-IF.
STOP RUN.

4
"लेकिन COBOL में प्रोग्राम न करें अगर आप इससे बच सकते हैं।" - की प्रोग्रामिंग ताओ
TSH


1
@ user202729 क्योंकि सालों से yymmddकाम नहीं करता है >=2000, यह Y2K पराजय का पूरा बिंदु है।
JAD

2
@ Adám - COBOL की भावना में जो बहुत उधम मचाता है I / O, मुझे यह कहना होगा कि इसे आईएसओ yyyy-mm-ddप्रारूप में होना चाहिए ।

4
@Giuseppe - COBOL की भावना में जो वास्तव में तार और संख्याओं में अंतर नहीं करता है, हाँ! बशर्ते आप प्रमुख शून्य, जैसे इनपुट कर सकते हैं 001300

जवाबों:


5

टी-एसक्यूएल, 99 98 बाइट्स

SELECT CONVERT(DATE,IIF(ISDATE(i)=1,'19'+i,
       DATEADD(d,8700*LEFT(i,2)+RIGHT(i,4)-935,'1999')))FROM t

लाइन ब्रेक केवल पठनीयता के लिए है। निहित कास्टिंग के लिए धन्यवाद।

इनपुट एक पूर्व मौजूदा तालिका के माध्यम से है टी के साथ CHARस्तंभ मैं , हमारे आईओ नियमों के अनुसार

निम्नलिखित चरणों के माध्यम से जाता है:

  1. प्रारंभिक जाँच SQL फ़ंक्शन के माध्यम से होती है ISDATE()। (भाषा फ़ंक्शन के आधार पर इस फ़ंक्शन का व्यवहार बदलता है, यह मेरे english-usसर्वर पर अपेक्षित रूप से काम करता है)। ध्यान दें कि यह वैधता के लिए एक चेक है, अगर हमने इसे सीधे पार्स करने की कोशिश की, तो यह 2501012025-01-01 के रूप में मैप करेगा, न कि 1925-01-01।
  2. यदि स्ट्रिंग एक तिथि के रूप में सही ढंग से पार्स करती है, 19तो मोर्चे पर व्यवहार करें (बजाय सर्वर-स्तरीय वर्ष कटऑफ़ सेटिंग को बदलने के)। अंतिम तिथि रूपांतरण अंत में आएगा।
  3. यदि स्ट्रिंग दिनांक के रूप में पार्स नहीं करती है , तो इसके बजाय इसे संख्या में परिवर्तित करें। सबसे छोटा गणित मैं पा सकता था 8700*PP + QQRR - 1300, जो (बहुत लंबा) SQL SUBSTRING()फ़ंक्शन से बचा जाता है । यह गणित प्रदान किए गए नमूनों की जाँच करता है, मुझे पूरा यकीन है कि यह सही है।
  4. DATEADDकई दिनों तक इसे जोड़ने के लिए उपयोग करें 2000-01-01, जिसे छोटा किया जा सकता है 2000
  5. उस अंतिम परिणाम (या तो चरण 2 से एक स्ट्रिंग, या चरण 4 से एक DATETIME), और CONVERT()इसे एक शुद्ध में ले जाएं DATE

मैं एक बिंदु पर सोचा कि मैं एक समस्याग्रस्त तारीख पाया: 000229। यह एकमात्र तारीख है जो 19xx बनाम 20xx के लिए अलग-अलग तरीके से पार्स करती है (2000 से एक लीप वर्ष था, लेकिन 1900 अजीब लीप-ईयर अपवादों के कारण नहीं था )। इस कारण, हालांकि, 000229एक वैध इनपुट भी नहीं है (चूंकि, जैसा कि उल्लेख किया गया है, 1900 एक लीप वर्ष नहीं था), इसलिए इसका कोई हिसाब नहीं है।


अच्छी चीज़। यह बहुत बुरा ISDATEहै कि एक बूलियन वापस नहीं करता है, या कि पूर्णांक को बूलियन में परिवर्तित नहीं किया जा सकता है IIFअन्यथा आप दो बाइट बचा सकते हैं।

@ YiminRong हां, SQL में निहित कास्टिंग बहुत परीक्षण और त्रुटि है, और कुछ कार्यों में अलग-अलग काम करता है जो अन्यथा समान हैं। मैं भाग्यशाली हूं कि मुझे स्पष्ट रूप से अपने परिणामों को गुणा करने से पहले पूर्णांक बनाने के लिए अपने परिणाम LEFT()और RIGHT()फ़ंक्शन कास्ट नहीं करना
पड़ा

1
मुझे लगता है कि आप की जगह एक अतिरिक्त चरित्र को हटा सकते हैं -1300,'2000'के साथ -935,'1999'
रज़वान सोकोल

कूल आइडिया, @RazvanSocol मैंने 365 दिनों के और अधिक गुणकों को वापस लेने की कोशिश की, लेकिन दुर्भाग्य से इससे कम कुछ भी नहीं मिला।
ब्रैडेक

5

आर , 126 बाइट्स

function(x,a=x%/%100^(2:0)%%100,d=as.Date)'if'(a[2]<13,d(paste(19e6+x),'%Y%m%d'),d(a[3]+100*((a[2]-13)+87*a[1]),'2000-01-01'))

इसे ऑनलाइन आज़माएं!

  • -5 बाइट्स धन्यवाद @Giuseppe सुझाव स्ट्रिंग के बजाय एक संख्यात्मक इनपुट लेने के लिए

4
पहले 1969 से पहले की तारीखों का प्रतिनिधित्व करने वाले इनपुट के लिए असफल (जैसे 000101या 681231)
जोनाथन एलन

2
@ जोनाथनअलन: अच्छी तरह से देखा, धन्यवाद। अब इसे ठीक किया जाना चाहिए (दुर्भाग्य से 5 और बाइट्स की आवश्यकता होती है ...)
डाइजेक्सिल

4

जावास्क्रिप्ट (स्पाइडरमोनी) , 103 बाइट्स

s=>new Date(...([a,b,c]=s.match(/../g),b>12?[2e3,0,(b-13+a*87)*100-~c]:[a,b-1,c])).toJSON().split`T`[0]

इसे ऑनलाइन आज़माएं!


.toJSONUTC + X टाइमज़ोन पर विफल हो जाएगा। यह कोड काम करता है, लेकिन अब (+ 11bytes):

s=>Intl.DateTimeFormat`ii`.format(new Date(...([a,b,c]=s.match(/../g),b>12?[2e3,0,(b-13+a*87)*100-~c]:[a,b-1,c])))

आप के साथ 13 बाइट्स बचा सकते हैं .toJSON()
अरनुलद

और आप इनपुट स्ट्रिंग को तीन 2-चार सब्सट्रिंग्स में विभाजित करके 9 और बाइट्स बचा सकते हैं ।
अरनुलद

@ अर्नूल मैं मूल रूप से अपनी मशीन पर यह कोशिश कर रहा था। लेकिन यह तब तक काम नहीं करता है जब से मेरा टाइमज़ोन UTC + 8 है। लेकिन यह कम से कम TIO पर काम करता है।
tsh

चूंकि हम भाषाओं को उनके कार्यान्वयन से परिभाषित करते हैं (यहाँ 'Node.js TIO पर चल रहे हैं'), क्या यह वास्तव में अमान्य है?
अरनुलद

बुलेट-प्रूफ संस्करण के लिए, आप इसे 1 बाइट बचाने के लिए कर सकते हैं
अरनुलद


2

एबीएपी, 173 171 बाइट्स

आउटपुट को और अधिक अनुकूलित करके 2 बाइट्स सहेजे गए

किंवदंतियों के अनुसार, 21 वीं सदी की शुरुआत में एक SAP ग्राहक ने एक बार कहा था:

कुल विनाश के परमाणु युद्ध के बाद, शेष एक चीज SAPGUI होगी।

वह सही था। आज, 2980 में, कोई और अधिक C ++ नहीं है, कोई और COBOL नहीं है। युद्ध के बाद सभी को SAP ABAP में अपना कोड फिर से लिखना पड़ा। 2800 के COBOL कार्यक्रमों के बचे हुए हिस्से को पश्चगामी अनुकूलता प्रदान करने के लिए, हमारे वैज्ञानिकों ने इसे ABAP में सबरूटीन के रूप में फिर से बनाया।

FORM x USING s.DATA d TYPE d.IF s+2 < 1300.d ='19'&& s.ELSE.d ='20000101'.d = d + s+4 + 100 * ( ( s+2(2) - 13 ) + 87 * s(2) ).ENDIF.WRITE:d(4),d+4,9 d+6,8'-',5'-'.ENDFORM.

इसे इस तरह से एक कार्यक्रम द्वारा बुलाया जा सकता है:

REPORT z.
  PARAMETERS date(6) TYPE c. "Text input parameter
  PERFORM x USING date.      "Calls the subroutine

मेरे कोड की व्याख्या:

FORM x USING s.     "Subroutine with input s
  DATA d TYPE d.    "Declare a date variable (internal format: YYYYMMDD)
  IF s+2 < 1300.    "If substring s from index 2 to end is less than 1300
    d ='19'&& s.    "the date is 19YYMMDD
  ELSE.             "a date past 2000
    d ='20000101'.  "Initial d = 2000 01 01 (yyyy mm dd)

    "The true magic. Uses ABAPs implicit chars to number cast
    "and the ability to add days to a date by simple addition.
    "Using PPQQRR as input:
    " s+4 = RR, s+2(2) = QQ, s(2) = PP
    d = d + s+4 + 100 * ( ( s+2(2) - 13 ) + 87 * s(2) ).
  ENDIF.
    "Make it an ISO date by splitting, concatenating and positioning the substrings of our date.
    WRITE:             "Explanation:
      d(4),            "d(4) = YYYY portion. WRITE adds a space after each parameter, so...
      5 '-' && d+4,    "place dash at absolute position 5. Concatenate '-' with MMDD...
      8 '-' && d+6.    "place dash at absolute position 8, overwriting DD. Concatenate with DD again.
ENDFORM.

ABAP की तिथि प्रकार के पास DDMMYYYY के रूप में स्वरूपित करने के लिए विषम संपत्ति है WRITE- उपयोग करते समय - भले ही आंतरिक प्रारूप YYYYMMDD होने के बावजूद स्थानीय निर्भर हो सकता है। लेकिन जब हम एक विकल्प चयनकर्ता का उपयोग करते हैं जैसे कि d(4)यह आंतरिक प्रारूप के पहले 4 वर्णों का चयन करता है , इसलिए हमें YYYY देता है।

अपडेट : स्पष्टीकरण में आउटपुट स्वरूपण अब पुराना हो गया है, मैंने इसे गोल्फ संस्करण में 2 बाइट्स द्वारा अनुकूलित किया है:

WRITE:  "Write to screen, example for 2000-10-29
 d(4),   "YYYY[space]                =>  2000
 d+4,    "MMDD[space]                =>  2000 1029
 9 d+6,  "Overwrites at position 9   =>  2000 10229
 8'-',   "Place dash at position 8   =>  2000 10-29
 5'-'.   "Place dash at position 5   =>  2000-10-29

बहुत बढ़िया, मुझे यह पसंद है। अब हम सब की जरूरत में एक संस्करण है MUMPSऔर हम कुछ भी बच जाएगा!

1
@YiminRong धन्यवाद! आपका COBOL- आधारित प्रश्न मूल रूप से कुछ इस तरह से पूछा गया था, मेरे पास कोई विकल्प नहीं था।
Maz

1

कोटलिन , 222 बाइट्स

49 बाइट्स को बचाने के लिए हार्ड कोडित कैलेंडर फ़ील्ड नाम का नाम स्थिरांक है।

{d:Int->val p=d/10000
val q=d/100%100
val r=d%100
if(q<13)"19%02d-%02d-%02d".format(p,q,r)
else{val c=Calendar.getInstance()
c.set(2000,0,1)
c.add(5,(p*87+q-13)*100+r)
"%4d-%02d-%02d".format(c.get(1),c.get(2)+1,c.get(5))}}

इसे ऑनलाइन आज़माएं!

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