समय एक समस्या क्यों है (और Kotlin इसे कैसे हल करता है)
\n\nअगर आपने कभी कोई ऐसा ऐप बनाया है जो अलग-अलग टाइम ज़ोन के यूज़र्स को सर्विस करता है, तो आप इस दर्द को जानते हैं। रिक्वेस्ट एक टाइमस्टैम्प के साथ आती है, डेटाबेस में UTC सेव है, न्यूयॉर्क का यूज़र शिकायत करता है कि नोटिफिकेशन रात 3 बजे आया, जबकि डेटाबेस में सुबह 8 बजे है। परिचित लग रहा है?
\n\nटाइम ज़ोन के साथ काम करना प्रोग्रामिंग का वह क्षेत्र है जहाँ सादगी दिखने के बावजूद दर्जनों बग छिपे होते हैं। लेकिन Kotlin, जिसने Java की सर्वश्रेष्ठ प्रथाओं को विरासत में लिया है, हमें इस अराजकता से निपटने के लिए एक शक्तिशाली शस्त्रागार देता है। इस लेख में, हम सीखेंगे कि Kotlin में टाइम ज़ोन के साथ सही तरीके से कैसे काम करें, सामान्य गलतियों से कैसे बचें, और ऐसा कोड कैसे लिखें जो डेलाइट सेविंग टाइम (DST) में बदलाव पर भी न टूटे।
\n\nसंक्षिप्त जानकारी: टाइम ज़ोन क्या है?
\n\nकोड में गोता लगाने से पहले, आइए शब्दों पर सहमत हों। टाइम ज़ोन (time zone) केवल UTC से ऑफसेट नहीं है। यह डेलाइट सेविंग/विंटर टाइम (DST) में बदलाव के नियमों का एक सेट भी है। उदाहरण के लिए, Europe/Moscow केवल +3 घंटे नहीं है, बल्कि इसमें ऐतिहासिक बदलाव भी शामिल हैं (2014 में रूस ने घड़ी बदलना बंद कर दिया था)।
Java/Kotlin की दुनिया में, इसके लिए दो मुख्य अवधारणाएँ जिम्मेदार हैं:
\n\n- \n
- ZoneId — टाइम ज़ोन का पहचानकर्ता (जैसे, "America/New_York")। इसमें DST का पूरा इतिहास होता है। \n
- ZoneOffset — केवल ऑफसेट (जैसे, +05:00)। इसमें बदलाव के कोई नियम नहीं होते। \n
अंतर महत्वपूर्ण है: यदि आप ZoneId के बजाय ZoneOffset का उपयोग करते हैं, तो घड़ी बदलने के दिन आपका कोड टूट जाएगा। इसे याद रखें।
Kotlin में java.time के बेसिक क्लासेज़
\n\nKotlin पूरी तरह से java.time पैकेज (Java 8+) को सपोर्ट करता है। अगर आप Android के लिए लिख रहे हैं, तो desugaring जोड़ना न भूलें या ThreeTenABP का उपयोग करें। सर्वर-साइड Kotlin के लिए कोई समस्या नहीं है।
Instant — समय में एक क्षण
\n\nInstant टाइमलाइन पर एक पूर्ण क्षण है। यह किसी टाइम ज़ोन से बंधा नहीं होता। इसे ही डेटाबेस में स्टोर करना चाहिए।
import java.time.Instant\n\nfun main() {\n val now = Instant.now()\n println(now) // 2025-03-15T10:30:00.123Z\n}\n\nअंत में Z अक्षर पर ध्यान दें — यह Zulu time है, यानी UTC। सब कुछ UTC में स्टोर करें — यह सुनहरा नियम है।
ZonedDateTime — ज़ोन के साथ समय
\n\nजब आपको यूज़र को समय दिखाना हो, तो ZonedDateTime का उपयोग करें। यह तारीख, समय, ऑफसेट और ज़ोन आईडी स्टोर करता है।
import java.time.ZonedDateTime\nimport java.time.ZoneId\n\nfun main() {\n val moscowTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))\n println(moscowTime) // 2025-03-15T13:30:00.123+03:00[Europe/Moscow]\n}\n\nवर्गाकार ब्रैकेट देख रहे हैं? यह ZoneId है, जो सिस्टम को DST को सही ढंग से हैंडल करने में मदद करता है।
OffsetDateTime — ऑफसेट के साथ समय
\n\nअगर आपको ज़ोन की जानकारी की ज़रूरत नहीं है, केवल ऑफसेट चाहिए, तो OffsetDateTime का उपयोग करें। यह हल्का और तेज़ है।
import java.time.OffsetDateTime\nimport java.time.ZoneOffset\n\nfun main() {\n val offsetTime = OffsetDateTime.now(ZoneOffset.ofHours(5))\n println(offsetTime) // 2025-03-15T15:30:00.123+05:00\n}\n\nलेकिन याद रखें: यदि आप न्यूयॉर्क के लिए OffsetDateTime सेव करते हैं, और फिर अमेरिका DST में बदल जाता है, तो आपका ऑफसेट पुराना हो जाएगा।
Kotlin में टाइम ज़ोन के बीच कन्वर्ज़न
\n\nसबसे आम काम है — डेटाबेस (UTC) से समय लेना और उसे यूज़र के टाइम ज़ोन में दिखाना। आइए देखें कि इसे सही तरीके से कैसे करें।
\n\nUTC से लोकल ज़ोन में
\n\nimport java.time.Instant\nimport java.time.ZoneId\nimport java.time.ZonedDateTime\n\nfun convertUtcToLocal(utcInstant: Instant, targetZone: String): ZonedDateTime {\n return utcInstant.atZone(ZoneId.of(targetZone))\n}\n\nfun main() {\n val utcNow =