Go में RFC 3339 / ISO-8601 पार्सिंग: अनुभवी डेवलपर्स भी क्यों फँसते हैं
\n\nक्या आपने कभी Go में time.Parse("2006-01-02T15:04:05Z", input) जैसा कुछ लिखा, त्रुटि मिली, और महसूस किया जैसे भाषा जानबूझकर मज़ाक उड़ा रही है? परिचित लगता है। दिनांक और समय पार्सिंग उन विषयों में से एक है जहाँ सब कुछ सरल लगता है, लेकिन व्यवहार में कई जाल छिपे होते हैं।
Stack Overflow पर प्रश्न "Go में RFC-3339 / ISO-8601 दिनांक-समय स्ट्रिंग पार्स करना" ने हज़ारों बार देखा गया है। लोग फ़ॉर्मेट में भ्रमित होते हैं, नैनोसेकंड भूल जाते हैं, समय क्षेत्रों से परेशान होते हैं, और 'जादुई' संख्या 2006-01-02T15:04:05Z पर गुस्सा करते हैं। इस लेख में हम 5 सबसे सामान्य गलतियों का विश्लेषण करेंगे और दिखाएँगे कि उन्हें हमेशा के लिए कैसे टालें। चलिए शुरू करते हैं!
थोड़ा सिद्धांत: RFC 3339 और ISO 8601 क्या हैं?
\n\nकोड में कूदने से पहले, आइए शब्दों को जल्दी से समझ लें। ISO 8601 दिनांक और समय प्रस्तुत करने का एक अंतरराष्ट्रीय मानक है। RFC 3339 इसका 'छोटा' संस्करण है, जो वेब (जैसे JSON, API, लॉग) में लोकप्रिय है।
\n\nसामान्य RFC 3339 स्ट्रिंग्स इस तरह दिखती हैं:
\n\n2025-01-15T10:30:00Z\n2025-01-15T10:30:00+03:00\n2025-01-15T10:30:00.123456789Z\n\nGo में पार्सिंग के लिए फ़ंक्शन time.Parse(layout, value) का उपयोग किया जाता है। और यहीं से असली मज़ा शुरू होता है।
गलती #1: गलत layout (टेम्पलेट) — सिरदर्द का मुख्य कारण
\n\nGo एक अनोखा दृष्टिकोण अपनाता है: फ़ॉर्मेट YYYY-MM-DD जैसे कोड से नहीं, बल्कि एक विशिष्ट तिथि से निर्धारित होता है: Mon Jan 2 15:04:05 MST 2006। इसे याद रखना आसान है: 01/02 03:04:05PM '06 -0700 (महीना, दिन, घंटा, मिनट, सेकंड, वर्ष, समय क्षेत्र)।
नौसिखिए अक्सर कुछ इस तरह लिखने की कोशिश करते हैं:
\n\n// ❌ गलती!\nt, err := time.Parse("YYYY-MM-DDTHH:MM:SSZ", "2025-01-15T10:30:00Z")\n\nGo ऐसे फ़ॉर्मेट को समझ ही नहीं पाएगा। RFC 3339 के लिए सही layout है time.RFC3339:
// ✅ सही\nt, err := time.Parse(time.RFC3339, "2025-01-15T10:30:00Z")\nif err != nil {\n log.Fatal(err)\n}\nfmt.Println(t) // 2025-01-15 10:30:00 +0000 UTC\n\nस्थिरांक time.RFC3339 स्ट्रिंग "2006-01-02T15:04:05Z07:00" के बराबर है। Z07:00 पर ध्यान दें — यह समय क्षेत्र का संकेत है।
गलती #2: नैनोसेकंड को अनदेखा करना (time.RFC3339 बनाम time.RFC3339Nano)
\n\nमानक time.RFC3339 नैनोसेकंड का समर्थन नहीं करता। यदि आपकी स्ट्रिंग में सेकंड का भिन्नात्मक भाग है:
2025-01-15T10:30:00.123456789Z\n\n…तो time.RFC3339 के साथ पार्सिंग त्रुटि लौटाएगा:
// ❌ त्रुटि: समय "2025-01-15T10:30:00.123456789Z" को "2006-01-02T15:04:05Z07:00" के रूप में पार्स करना: ".123456789Z" को "Z07:00" के रूप में पार्स नहीं कर सकता\nt, err := time.Parse(time.RFC3339, "2025-01-15T10:30:00.123456789Z")\n\nसमाधान — time.RFC3339Nano का उपयोग करें:
// ✅ सही\nt, err := time.Parse(time.RFC3339Nano, "2025-01-15T10:30:00.123456789Z")\nif err != nil {\n log.Fatal(err)\n}\nfmt.Println(t) // 2025-01-15 10:30:00.123456789 +0000 UTC\n\nसुझाव: यदि आप सुनिश्चित नहीं हैं कि नैनोसेकंड होंगे या नहीं, तो time.RFC3339Nano का उपयोग करें — यह पिछड़ा संगत है और दोनों मामलों में काम करेगा।
गलती #3: समय क्षेत्र — Z या +00:00 — क्या ये एक ही नहीं हैं?
\n\nस्ट्रिंग्स 2025-01-15T10:30:00Z और 2025-01-15T10:30:00+00:00 एक ही चीज़ (UTC) दर्शाती हैं, लेकिन Go उन्हें अलग-अलग तरीके से संसाधित कर सकता है यदि layout गलत निर्दिष्ट किया गया हो।
// ✅ दोनों विकल्प time.RFC3339 के साथ काम करते हैं\nt1, _ := time.Parse(time.RFC3339, "2025-01-15T10:30:00Z")\nt2, _ := time.Parse(time.RFC3339, "2025-01-15T10:30:00+00:00")\nfmt.Println(t1.Equal(t2)) // true\n\nलेकिन यदि आप अपना स्वयं का layout लिखते हैं, तो सावधान रहें:
\n\n- \