ZonedDateTime — यह क्या है, टाइम ज़ोन और समय के साथ काम करना

लेखक: IT Sectr प्रकाशित: 2026-07-13 पढ़ने का समय: 10 मिनट

ZonedDateTime java.time पैकेज से एक अपरिवर्तनीय (immutable) वर्ग है जो दिनांक और समय को टाइम ज़ोन जानकारी (ZoneId) के साथ संग्रहीत करता है। LocalDateTime के विपरीत, ZonedDateTime समयरेखा पर एक क्षण की असंदिग्ध रूप से पहचान करता है। Oracle Java 17 (2024) विनिर्देश के अनुसार, यह वर्ग IANA Time Zone Database के ज़ोन नियमों के माध्यम से डेलाइट सेविंग टाइम (DST) संक्रमण को सही ढंग से संभालता है।

मुख्य बिंदु

  • ZonedDateTime एक अपरिवर्तनीय वर्ग है जो दिनांक, समय और टाइम ज़ोन (ZoneId) को एक ऑब्जेक्ट में जोड़ता है।
  • LocalDateTime के विपरीत, ZonedDateTime समयरेखा पर एक क्षण को असंदिग्ध रूप से परिभाषित करता है और वैश्विक प्रणालियों के लिए उपयुक्त है।
  • यह वर्ग IANA Time Zone Database नियमों के अनुसार डेलाइट सेविंग टाइम (DST) संक्रमण को स्वचालित रूप से संभालता है।
  • टाइम ज़ोन के बीच रूपांतरण के लिए withZoneSameInstant(ZoneId) विधि का उपयोग किया जाता है।
  • डेटाबेस में ZonedDateTime को OffsetDateTime या TIMESTAMP WITH TIME ZONE के माध्यम से संग्रहीत करने की अनुशंसा की जाती है।

ZonedDateTime क्या है?

ZonedDateTime java.time पैकेज की प्रमुख कक्षाओं में से एक है, जो पूर्ण टाइम ज़ोन जानकारी के साथ दिनांक और समय का प्रतिनिधित्व करता है। यह तीन घटकों को जोड़ता है: LocalDateTime (दिनांक और समय), ZoneId (ज़ोन पहचानकर्ता), और ZoneOffset (UTC के सापेक्ष ऑफ़सेट)।

LocalDateTime के विपरीत, जो बिना टाइम ज़ोन बाइंडिंग के केवल वॉल-क्लॉक टाइम संग्रहीत करता है, ZonedDateTime एक क्षण की असंदिग्ध रूप से पहचान करता है। विभिन्न टाइम ज़ोन में दो समान LocalDateTime इंस्टेंस समय में अलग-अलग क्षणों का प्रतिनिधित्व करते हैं। दो समान ZonedDateTime इंस्टेंस — एक ही क्षण।

यह वर्ग पूरी तरह से अपरिवर्तनीय और थ्रेड-सेफ है। सभी अंकगणितीय संक्रियाएँ एक नया ऑब्जेक्ट लौटाती हैं। ZonedDateTime ChronoZonedDateTime इंटरफ़ेस को लागू करता है और इसका उपयोग वहाँ किया जा सकता है जहाँ Java में ज़ोनल समय कार्य की आवश्यकता होती है।

Oracle Java 17 विनिर्देशों के अनुसार, ZonedDateTime IANA Time Zone Database के किसी भी ज़ोन के साथ काम करने का समर्थन करता है, जिसमें 600 से अधिक टाइम ज़ोन शामिल हैं।

ZonedDateTime vs LocalDateTime: क्या अंतर है?

मुख्य अंतर — ZonedDateTime में टाइम ज़ोन होता है, जबकि LocalDateTime में नहीं होता। यह मूलभूत अंतर प्रत्येक वर्ग के उपयोग के दायरे को निर्धारित करता है।

LocalDateTime का उपयोग स्थानीय घटनाओं के लिए किया जाता है: संगीत कार्यक्रम का समय, कक्षा अनुसूची, जन्म तिथि। यदि कोई घटना मास्को में 15:00 बजे होती है, तो LocalDateTime बिना किसी बाइंडिंग के 15:00 रिकॉर्ड करेगा। यदि आप सर्वर को न्यूयॉर्क में स्थानांतरित करते हैं, तो समय 15:00 ही रहेगा — लेकिन यह एक अलग भौतिक क्षण होगा।

ZonedDateTime का उपयोग वैश्विक डेटा के लिए किया जाता है: सर्वर लॉग, API में टाइमस्टैम्प, अंतर्राष्ट्रीय बैठकें। यदि कोई बैठक 15:00 MSK पर निर्धारित है, तो ZonedDateTime समय और ज़ोन दोनों को संरक्षित करेगा। न्यूयॉर्क में, यह 8:00 EST के रूप में सही ढंग से प्रदर्शित होगा। Baeldung (2024) के अनुसार, LocalDateTime और ZonedDateTime के बीच चुनाव तिथियों के साथ काम करते समय सबसे आम वास्तु निर्णय है।

व्यावहारिक नियम: यदि डेटा एक क्षेत्र के लिए संग्रहीत किया जाता है — LocalDateTime का उपयोग करें। यदि डेटा टाइम ज़ोन सीमाओं को पार करता है — ZonedDateTime का उपयोग करें। यदि आपको एक पूर्ण क्षण का प्रतिनिधित्व करने की आवश्यकता है — Instant का उपयोग करें।

java.time में टाइम ज़ोन कैसे काम करता है?

java.time में टाइम ज़ोन ZoneId वर्ग द्वारा दर्शाया जाता है। ZoneId “महाद्वीप/क्षेत्र” प्रारूप में एक ज़ोन पहचानकर्ता है, उदाहरण के लिए “Europe/Moscow”, “America/New_York”, “Asia/Tokyo”। ZoneId को स्थैतिक विधि of(String zoneId) के माध्यम से या सिस्टम डिफ़ॉल्ट टाइम ज़ोन के माध्यम से प्राप्त किया जाता है।

ZoneId दो प्रकारों में विभाजित है: fixed offset (निश्चित ऑफ़सेट, जैसे “+03:00”) और region-based (क्षेत्रीय ज़ोन, जैसे “Europe/London”)। क्षेत्रीय ज़ोन में डेलाइट सेविंग टाइम संक्रमण नियम और ऐतिहासिक परिवर्तन होते हैं। Fixed offset केवल एक निश्चित ऑफ़सेट है।

किसी विशिष्ट क्षण में ZoneId का वर्तमान ऑफ़सेट प्राप्त करने के लिए, getRules() विधि का उपयोग किया जाता है, जो ZoneRules लौटाता है। ZoneRules में किसी दिए गए ज़ोन के लिए सभी संक्रमण और ऑफ़सेट होते हैं। यह सही DST हैंडलिंग के लिए प्रमुख तंत्र है।

सभी टाइम ज़ोन tzdata फ़ाइलों (IANA Time Zone Database) के माध्यम से JDK के साथ शामिल किए जाते हैं और नियमित रूप से अपडेट किए जाते हैं। Android पर, tzdata संस्करण Google Play Services के माध्यम से सिस्टम अपडेट पर निर्भर करता है।

ZonedDateTime बनाना

ZonedDateTime को कई तरीकों से बनाया जा सकता है। सबसे सरल now() है, जो सिस्टम टाइम ज़ोन में वर्तमान समय लौटाता है। now(ZoneId) वैरिएंट आपको निर्दिष्ट ज़ोन में वर्तमान समय प्राप्त करने की अनुमति देता है।

of(LocalDateTime, ZoneId) विधि स्थानीय समय और ज़ोन से ZonedDateTime बनाती है। of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond, ZoneId zone) वैरिएंट घटकों से बनाता है।

LocalDateTime को atZone(ZoneId) विधि के माध्यम से ZonedDateTime में परिवर्तित किया जा सकता है। Instant — Instant.atZone(ZoneId) के माध्यम से। Date — Date.toInstant().atZone(ZoneId) के माध्यम से।

kotlin
val moscowZone = ZoneId.of("Europe/Moscow")

val nowInMoscow = ZonedDateTime.now(moscowZone)

val fromComponents = ZonedDateTime.of(
    2026, 7, 21, 15, 30, 0, 0, moscowZone
)

val fromLocal = LocalDateTime.now().atZone(moscowZone)

val fromInstant = Instant.now().atZone(moscowZone)

टाइम ज़ोन के बीच रूपांतरण

मुख्य रूपांतरण विधि withZoneSameInstant(ZoneId) है। यह ZonedDateTime को उसी क्षण को बनाए रखते हुए दूसरे टाइम ज़ोन में परिवर्तित करती है। उदाहरण के लिए, 15:00 MSK → 8:00 EST। withZoneSameLocal(ZoneId) विधि स्थानीय समय को बनाए रखते हुए ज़ोन बदलती है — यह एक अलग क्षण देती है।

UTC के सापेक्ष ऑफ़सेट प्राप्त करने के लिए, getOffset() विधि का उपयोग किया जाता है, जो ZoneOffset लौटाती है। ZoneOffset ZoneId का एक उपवर्ग है जो “+HH:mm” या “-HH:mm” प्रारूप में एक निश्चित ऑफ़सेट दर्शाता है।

Instant में रूपांतरण toInstant() विधि के माध्यम से किया जाता है। Instant समय में एक पूर्ण क्षण है, जो टाइम ज़ोन से स्वतंत्र है। विपरीत रूपांतरण Instant.atZone(ZoneId) है।

kotlin
val moscow = ZonedDateTime.of(
    2026, 7, 21, 15, 0, 0, 0,
    ZoneId.of("Europe/Moscow")
)

val newYork = moscow.withZoneSameInstant(
    ZoneId.of("America/New_York")
)

val utcInstant = moscow.toInstant()
val backToMoscow = utcInstant.atZone(ZoneId.of("Europe/Moscow"))

डेलाइट सेविंग टाइम (DST) के साथ काम करना

डेलाइट सेविंग टाइम संक्रमण दो समस्याएँ पैदा करते हैं: अंतराल (gaps) और अतिव्यापन (overlaps)। अंतराल वसंत में होता है जब घड़ियाँ आगे बढ़ाई जाती हैं — एक निश्चित समय मौजूद नहीं होता। अतिव्यापन शरद ऋतु में होता है जब घड़ियाँ पीछे हटाई जाती हैं — एक ही समय दो बार होता है।

ZonedDateTime समाधान (resolve) रणनीति के माध्यम से इन स्थितियों को संभालता है। अंतराल के दौरान कोई ऑब्जेक्ट बनाते समय, java.time स्वचालित रूप से समय को ऑफ़सेट राशि से स्थानांतरित करता है। अतिव्यापन के दौरान बनाते समय, पहला विकल्प (संक्रमण से पहले) चुना जाता है। इस व्यवहार को withZoneSameInstant के माध्यम से बदला जा सकता है।

आप zone.getRules().isDaylightSavings(instant) के माध्यम से जाँच सकते हैं कि कोई समय DST में है या नहीं। getOffset() विधि किसी दिए गए क्षण के लिए वास्तविक ऑफ़सेट दिखाती है, और getRules().getDaylightSavings(instant) मिलीसेकंड में DST समायोजन राशि दिखाती है।

kotlin
fun checkDST(zdt: ZonedDateTime) {
    val rules = zdt.getZone().getRules()
    val instant = zdt.toInstant()

    if (rules.isDaylightSavings(instant)) {
        val dstAmount = rules.getDaylightSavings(instant)
        Log.d("डेलाइट सेविंग टाइम", "DST ऑफ़सेट: $dstAmount")
    }
}

ZonedDateTime को फ़ॉर्मेट करना

ZonedDateTime को फ़ॉर्मेट करने के लिए DateTimeFormatter का उपयोग किया जाता है। मानक ISO प्रारूप में दिनांक, समय और ऑफ़सेट शामिल है: “2026-07-21T15:30:00+03:00[Europe/Moscow]”। पूर्वनिर्धारित प्रारूप: ISO_ZONED_DATE_TIME, ISO_OFFSET_DATE_TIME, ISO_INSTANT।

स्थानीयकृत आउटपुट के लिए, DateTimeFormatter.ofLocalizedDateTime(FormatStyle) का उपयोग करें। FormatStyle SHORT, MEDIUM, LONG, FULL हो सकता है। LONG में ज़ोन का नाम (“MSK”) शामिल होता है, FULL में पूरा नाम (“Moscow Standard Time”) शामिल होता है।

महत्वपूर्ण: ZonedDateTime के साथ एक स्ट्रिंग को पार्स करते समय, प्रारूप में ज़ोन या ऑफ़सेट जानकारी होनी चाहिए। यदि ज़ोन निर्दिष्ट नहीं है, तो LocalDateTime.parse() और फिर atZone() का उपयोग करें।

kotlin
val zdt = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))

val iso = zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)

val custom = DateTimeFormatter
    .ofPattern("dd.MM.yyyy HH:mm z")
val formatted = zdt.format(custom)

val parsed = ZonedDateTime.parse(
    "2026-07-21T15:30:00+03:00",
    DateTimeFormatter.ISO_OFFSET_DATE_TIME
)

Android में ZonedDateTime: व्यावहारिक उदाहरण

पहला उदाहरण — उपयोगकर्ता को उसके स्थानीय टाइम ज़ोन में मीटिंग का समय दिखाना। सर्वर UTC में ZonedDateTime भेजता है, क्लाइंट डिवाइस के स्थानीय टाइम ज़ोन में कनवर्ट करता है।

kotlin
fun displayMeetingTime(
    serverUtc: ZonedDateTime
): String {
    val deviceZone = ZoneId.systemDefault()
    val localTime = serverUtc.withZoneSameInstant(deviceZone)
    val formatter = DateTimeFormatter
        .ofPattern("dd.MM.yyyy HH:mm z")
    return localTime.format(formatter)
}

दूसरा उदाहरण — टाइम ज़ोन को ध्यान में रखते हुए अगली घटना तक के समय की गणना करना। हम सर्वर समय के लिए ZonedDateTime और अंतर की गणना के लिए Duration.between() का उपयोग करते हैं।

kotlin
fun timeUntilEvent(eventTime: ZonedDateTime): String {
    val now = ZonedDateTime.now()
    val duration = Duration.between(now, eventTime)

    val hours = duration.toHours()
    val minutes = duration.toMinutes() % 60
    return "Remaining $hours h $minutes min"
}

तीसरा उदाहरण — Retrofit API के साथ काम करना। सर्वर ज़ोन के साथ ISO-8601 स्ट्रिंग लौटाता है। हम ZonedDateTime में कनवर्ट करने के लिए एक कस्टम डीसेरियलाइज़र का उपयोग करते हैं।

kotlin
data class EventResponse(
    @JsonAdapter(ZonedDateTimeAdapter::class)
    val eventTime: ZonedDateTime
)

class ZonedDateTimeAdapter : JsonAdapter<ZonedDateTime>() {
    override fun fromJson(reader: JsonReader): ZonedDateTime? {
        return ZonedDateTime.parse(
            reader.nextString()
        )
    }
}

टाइम ज़ोन के साथ काम करते समय सामान्य गलतियाँ

पहली गलती — सर्वर कोड में ZoneId.systemDefault() का उपयोग करना। सर्वर का टाइम ज़ोन क्लाइंट से भिन्न हो सकता है, और सर्वर पर सिस्टम ज़ोन का उपयोग करने से गलत गणनाएँ होती हैं। हमेशा स्पष्ट रूप से ज़ोन निर्दिष्ट करें या संदर्भ के रूप में UTC का उपयोग करें।

दूसरी गलती — अवधि की गणना करते समय DST को अनदेखा करना। Duration.between() संक्रमणों को सही ढंग से संभालता है, लेकिन यदि आप मैन्युअल रूप से टाइमस्टैम्प घटाते हैं, तो डेलाइट सेविंग टाइम 1 घंटे की त्रुटि पैदा कर सकता है। मैन्युअल गणित के बजाय ChronoUnit.HOURS.between() का उपयोग करें।

तीसरी गलती — withZoneSameInstant और withZoneSameLocal के बीच भ्रम। पहला क्षण को बनाए रखते हुए ज़ोन बदलता है — समय स्थानांतरित होता है। दूसरा स्थानीय समय को बनाए रखते हुए ज़ोन बदलता है — क्षण बदलता है। SonarSource (2024) के अनुसार, गलत विधि चुनना सबसे आम गलतियों में से एक है।

चौथी गलती — यह मान लेना कि डिवाइस का टाइम ज़ोन हमेशा उपयोगकर्ता के टाइम ज़ोन के समान है। उपयोगकर्ता यात्रा कर रहा हो सकता है और उम्मीद करता है कि ऐप वर्तमान ज़ोन के बजाय उसके “गृह” टाइम ज़ोन में समय दिखाए। इस मामले में, इंटरफ़ेस के माध्यम से ज़ोन चयन प्रदान करें।

अक्सर पूछे जाने वाले प्रश्न

ZonedDateTime और OffsetDateTime में क्या अंतर है?

ZonedDateTime में एक क्षेत्रीय ज़ोन पहचानकर्ता (उदा., “Europe/Moscow”) होता है और यह DST को संभालता है। OffsetDateTime क्षेत्रीय नियमों के बिना केवल एक निश्चित ऑफ़सेट (+03:00) संग्रहीत करता है। डेटाबेस भंडारण के लिए, OffsetDateTime की अनुशंसा की जाती है।

ZonedDateTime के माध्यम से UTC में वर्तमान समय कैसे प्राप्त करें?

ZonedDateTime.now(ZoneOffset.UTC) या Instant.now().atZone(ZoneOffset.UTC) का उपयोग करें। दोनों विकल्प शून्य ऑफ़सेट के साथ वर्तमान क्षण लौटाते हैं। एक सरल टाइमस्टैम्प के लिए, ज़ोन बाइंडिंग के बिना Instant.now() का उपयोग करें।

क्या ZonedDateTime को Gson या Moshi के माध्यम से सीरियलाइज़ किया जा सकता है?

हाँ, लेकिन एक कस्टम एडाप्टर आवश्यक है। Gson डिफ़ॉल्ट रूप से ZonedDateTime का समर्थन नहीं करता है। Moshi Rfc3339DateJsonAdapter के माध्यम से इसका समर्थन करता है। Jackson के लिए Kotlinx Serialization या JavaTimeModule लाइब्रेरी का उपयोग करने की अनुशंसा की जाती है।

जब समय DST अंतराल में पड़ता है तो स्थिति को कैसे संभालें?

java.time स्वचालित रूप से समय को ऑफ़सेट राशि से आगे स्थानांतरित करता है। उदाहरण के लिए, यदि 02:30 मौजूद नहीं है जब घड़ियाँ 03:00 पर आगे बढ़ती हैं, तो ZonedDateTime 03:30 पर एक ऑब्जेक्ट बनाएगा। आप ZoneRules.getTransition(instant) के माध्यम से अंतराल की जाँच कर सकते हैं।

SQL डेटाबेस के लिए ZonedDateTime की अनुशंसा क्यों नहीं की जाती है?

JDBC 4.2 OffsetDateTime का समर्थन करता है लेकिन सीधे ZonedDateTime का नहीं। ZonedDateTime में एक क्षेत्रीय ज़ोन होता है जिसका SQL में कोई समकक्ष नहीं है। OffsetDateTime या Instant संग्रहीत करने की अनुशंसा की जाती है, और ज़ोन को एक अलग कॉलम में संग्रहीत करें।

सारांश

  • ZonedDateTime टाइम ज़ोन के साथ दिनांक और समय के लिए एक अपरिवर्तनीय वर्ग है, जो IANA Time Zone Database के माध्यम से DST को सही ढंग से संभालता है।
  • LocalDateTime से मुख्य अंतर ज़ोन की उपस्थिति है, जो ZonedDateTime को समय में एक क्षण का असंदिग्ध पहचानकर्ता बनाता है।
  • ज़ोन के बीच रूपांतरण के लिए, withZoneSameInstant() का उपयोग करें, जो क्षण को बनाए रखता है, withZoneSameLocal का नहीं।
  • डेलाइट सेविंग टाइम संक्रमण के दौरान, java.time अंतर्निहित ज़ोन नियमों के माध्यम से स्वचालित रूप से अंतराल और अतिव्यापन को हल करता है।
  • डेटाबेस भंडारण के लिए, OffsetDateTime का उपयोग करें या Instant और ZoneId को अलग-अलग संग्रहीत करें।
  • Android में, ZonedDateTime को डिवाइस के स्थानीय समय में बदलने के लिए, ZoneId.systemDefault() का withZoneSameInstant के साथ उपयोग करें।
  • JSON सीरियलाइज़ेशन के लिए, एक कस्टम एडाप्टर आवश्यक है — Kotlinx Serialization या Jackson JavaTimeModule का उपयोग करें।

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें