Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> प्रोग्रामिंग

जावा डेट फॉर्मेटिंग में महारत: SimpleDateFormat और DateFormat समझाया गया

परिचय

SimpleDateFormat कस्टम पैटर्न स्ट्रिंग्स का उपयोग करके java.util.Date मानों को फॉर्मेट और पार्स करता है, और DateFormat लोकेल-अवेयर डेट और टाइम फॉर्मेटिंग के लिए एब्स्ट्रैक्ट बेस API प्रदान करता है। जब आप लिगेसी जावा कोड को बनाए रखते हैं जो अभी भी java.util.Date पर निर्भर करता है तो इन API का उपयोग करें; नए कोड के लिए, जावा 8+ डेट/टाइम API से DateTimeFormatter को प्राथमिकता दें क्योंकि SimpleDateFormat थ्रेड-सेफ नहीं है।

यह ट्यूटोरियल दिखाता है कि फॉर्मेटिंग, पार्सिंग, टाइमज़ोन रूपांतरण, और लोकेल-विशिष्ट आउटपुट के लिए DateFormat और SimpleDateFormat का उपयोग कैसे करें। इसमें setLenient(false) के साथ सख्त सत्यापन, थ्रेड सेफ्टी वर्कअराउंड, और DateTimeFormatter के लिए एक व्यावहारिक माइग्रेशन पथ भी शामिल है।

मुख्य बातें

  • DateFormat एब्स्ट्रैक्ट फॉर्मेटिंग API है, और SimpleDateFormat पैटर्न-आधारित फॉर्मेटिंग और पार्सिंग के लिए ठोस कार्यान्वयन है
  • SimpleDateFormat वर्षों, महीनों, दिनों, समय फ़ील्ड, और टाइमज़ोन आउटपुट के लिए समृद्ध पैटर्न टोकन का समर्थन करता है
  • एक साझा SimpleDateFormat इंस्टेंस मल्टीथ्रेडेड कोड में असुरक्षित है क्योंकि इसकी आंतरिक स्थिति परिवर्तनीय है
  • ThreadLocal<SimpleDateFormat> लिगेसी कोड तुरंत माइग्रेट नहीं कर सकता जब प्रति थ्रेड फॉर्मेटर इंस्टेंस को अलग करता है
  • DateTimeFormatter अपरिवर्तनीय और थ्रेड-सेफ है, इसलिए यह नए जावा कोड के लिए पसंदीदा प्रतिस्थापन है
  • .parse() ParseException फेंक सकता है, इसलिए पार्सिंग कोड को ट्राई-कैच और उपयोगी त्रुटि संदेशों का उपयोग करना चाहिए
  • setLenient(false) अमान्य तिथियों को चुपचाप समायोजित होने से रोकता है, जैसे 2024-13-45
  • सर्वर डिप्लॉयमेंट में वातावरण-निर्भर आउटपुट से बचने के लिए हमेशा एक स्पष्ट Locale पास करें

जावा में SimpleDateFormat क्या है?

SimpleDateFormat वह DateFormat सबक्लास है जो आपको जावा में फॉर्मेटिंग और पार्सिंग के लिए स्पष्ट डेट/टाइम पैटर्न परिभाषित करने देता है।

जब आप फ़ैक्टरी मेथड के माध्यम से स्टाइल-आधारित, लोकेल-अवेयर आउटपुट चाहते हैं तो DateFormat का उपयोग करें, और जब आपको "dd-MM-yyyy" या "yyyy-MM-dd'T'HH:mm:ssZ" जैसे सटीक पैटर्न कंट्रोल की आवश्यकता हो तो SimpleDateFormat का उपयोग करें। DateFormat स्टाइल कॉन्स्टेंट (SHORT, MEDIUM, LONG, FULL) बिना आपको सटीक क्षेत्रीय डेट ऑर्डर जाने बिना लोकेल-उपयुक्त आउटपुट उत्पन्न करते हैं, जो उपयोगकर्ता-सामना करने वाले डिस्प्ले स्ट्रिंग्स के लिए उपयोगी है जहां फॉर्मेट को उपयोगकर्ता के लोकेल कन्वेंशन का पालन करना चाहिए। SimpleDateFormat का उपयोग तब करें जब आउटपुट फॉर्मेट बाहरी आवश्यकता जैसे API कॉन्ट्रैक्ट, लॉग फॉर्मेट, या फ़ाइल नामकरण कन्वेंशन द्वारा तय किया जाता है, क्योंकि उन मामलों में लोकेल की परवाह किए बिना एक सटीक पैटर्न की आवश्यकता होती है।

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

Locale locale = Locale.US;
DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
String styleBased = dateFormat.format(new Date());
SimpleDateFormat patternBased = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss", locale);
String patternOutput = patternBased.format(new Date());
System.out.println(styleBased);
System.out.println(patternOutput);
Jan 5, 2026
05-01-2026 14:30:22

new Locale(String, String) जावा 19 से डिप्रिकेटेड है। इसके बजाय Locale.Builder का उपयोग करें।

Locale locale = new Locale.Builder()
    .setLanguage("en")
    .setRegion("US")
    .build();

डेट के बजाय समय फॉर्मेट करने के लिए, उसी लोकेल और स्टाइल पैरामीटर्स के साथ DateFormat.getTimeInstance() का उपयोग करें।

Locale locale = Locale.US;
DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale);
System.out.println(timeFormat.format(new Date()));
आउटपुट वर्तमान समय और टाइमज़ोन पर निर्भर करता है, उदाहरण के लिए: 2:30:45 PM

आधुनिक जावा डेट/टाइम API के व्यापक अवलोकन के लिए, जावा 8 डेट, LocalDate, LocalDateTime, इंस्टेंट और उदाहरणों के साथ जावा 8 फीचर्स देखें।

SimpleDateFormat पैटर्न सिंटैक्स संदर्भ

SimpleDateFormat पैटर्न अक्षर सीधे डेट/टाइम घटकों से मैप होते हैं, और सही पैटर्न चयन आउटपुट फॉर्मेट और पार्स व्यवहार दोनों को नियंत्रित करता है।

प्रतीकअर्थउदाहरण पैटर्नउदाहरण आउटपुट
Gयुग डिज़ाइनेटरGAD
yवर्षyyyy2026
Mवर्ष में महीनाMMMMJanuary
wवर्ष में सप्ताहw3
Wमहीने में सप्ताहW1
Dवर्ष में दिनD15
dमहीने में दिनdd05
Fमहीने में सप्ताह का दिनF1
Eसप्ताह में दिन का नामEEEMon
uसप्ताह में दिन संख्या (1 = Monday)u1
aAM/PM मार्करaPM
Hदिन में घंटा (0-23)HH14
kदिन में घंटा (1-24)k14
Kam/pm में घंटा (0-11)K2
ham/pm में घंटा (1-12)hh02
mघंटे में मिनटmm30
sमिनट में सेकंडss45
SमिलीसेकंडSSS123
zसामान्य टाइमज़ोनzIST
ZRFC 822 टाइमज़ोन ऑफसेटZ+0530
XISO 8601 टाइमज़ोन ऑफसेटXXX+05:30

पैटर्न पुनरावृत्ति और आउटपुट चौड़ाई

दोहराए गए पैटर्न अक्षर चौड़ाई, न्यूमेरिक पैडिंग, या टेक्स्ट स्टाइल को बदलते हैं।

फ़ील्डपैटर्नउदाहरण आउटपुट
महीनाM1
महीनाMM01
महीनाMMMJan
महीनाMMMMJanuary
महीने का दिनd5
महीने का दिनdd05
घंटा (0-23)H7
घंटा (0-23)HH07
वर्षyy26
वर्षyyyy2026

अपेक्षित आउटपुट के साथ सामान्य पैटर्न उदाहरण

ये सामान्य पैटर्न लॉग, API, और उपयोगकर्ता-सामना करने वाली तिथियों के लिए उपयोगी हैं।

पैटर्नउदाहरण आउटपुट
MM/dd/yyyy01/05/2026
dd-M-yyyy hh:mm:ss05-1-2026 02:30:45
dd MMMM yyyy05 January 2026
dd MMMM yyyy zzzz05 January 2026 India Standard Time
E, dd MMM yyyy HH:mm:ss zMon, 05 Jan 2026 14:30:45 IST

SimpleDateFormat का उपयोग करके डेट फॉर्मेट करना

Date को फॉर्मेट करने के लिए, एक पैटर्न के साथ SimpleDateFormat बनाएं और .format(date) कॉल करें।

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

Date now = new Date();
SimpleDateFormat basic = new SimpleDateFormat("MM-dd-yyyy", Locale.US);
SimpleDateFormat withTime = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss", Locale.US);
SimpleDateFormat isoLike = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
System.out.println(basic.format(now));
System.out.println(withTime.format(now));
System.out.println(isoLike.format(now));
01-05-2026
05-01-2026 14:30:45
2026-01-05T14:30:45+0000

SimpleDateFormat फॉर्मेटर इंस्टेंस से टाइमज़ोन और लोकेल नियम लागू करता है, इसलिए जब आउटपुट सुसंगत होना चाहिए तो उन मानों को स्पष्ट रूप से सेट करें।

SimpleDateFormat का उपयोग करके स्ट्रिंग को डेट में पार्स करना

स्ट्रिंग को Date में पार्स करने के लिए, सटीक इनपुट पैटर्न के साथ एक फॉर्मेटर बनाएं और .parse(input) कॉल करें।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

try {
    SimpleDateFormat dateParser = new SimpleDateFormat("dd-MM-yyyy", Locale.US);
    Date parsedDate = dateParser.parse("05-01-2026");
    System.out.println(parsedDate);
    SimpleDateFormat timeParser = new SimpleDateFormat("HH:mm:ss", Locale.US);
    Date parsedTime = timeParser.parse("22:15:09");
    System.out.println(parsedTime);
} catch (ParseException e) {
    e.printStackTrace();
}
Mon Jan 05 00:00:00 UTC 2026
Thu Jan 01 22:15:09 UTC 1970

यदि केवल समय प्रदान किया जाता है, तो जावा डेट भाग के लिए एपोक डेट का उपयोग करता है।

ParseException को सही ढंग से संभालना

जब इनपुट कॉन्फ़िगर किए गए पैटर्न से मेल नहीं खाता तो parse() ParseException फेंकता है, इसलिए प्रोडक्शन कोड को इसे पकड़ना चाहिए और कच्चे इनपुट और अपेक्षित पैटर्न दोनों को लॉग करना चाहिए।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;

String input = "31/01/2026";
String pattern = "dd-MM-yyyy";
SimpleDateFormat parser = new SimpleDateFormat(pattern, Locale.US);
try {
    parser.parse(input);
    System.out.println("Parsed successfully");
} catch (ParseException e) {
    // आसान डीबगिंग के लिए इनपुट मान और पैटर्न दोनों शामिल करें।
    System.err.println("Failed to parse date string: " + input);
    System.err.println("Expected pattern: " + pattern);
    System.err.println("Parser error: " + e.getMessage());
}
Failed to parse date string: 31/01/2026
Expected pattern: dd-MM-yyyy
Parser error: Unparseable date: "31/01/2026"

सेवाओं में पुन: उपयोग किए जा सकने वाले अपवाद हैंडलिंग पैटर्न के लिए, जावा में अपवाद हैंडलिंग और जावा 8 डेट, LocalDate, LocalDateTime, इंस्टेंट देखें।

पार्सिंग से पहले डेट स्ट्रिंग को मान्य करना

SimpleDateFormat डिफ़ॉल्ट रूप से लीनियंट है, इसलिए अमान्य मान फेल होने के बजाय रोल ओवर कर सकते हैं; सख्त सत्यापन लागू करने के लिए setLenient(false) कॉल करें।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Locale;

String invalid = "2024-13-45";
SimpleDateFormat lenientParser = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
SimpleDateFormat strictParser = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
strictParser.setLenient(false);
System.out.println("Lenient parse result:");
try {
    // लीनियंट मोड अमान्य मानों को फेंकने के बजाय चुपचाप रोल ओवर करता है।
    System.out.println(lenientParser.parse(invalid));
} catch (ParseException e) {
    System.out.println("ParseException: " + e.getMessage());
}
System.out.println("Strict parse result:");
try {
    System.out.println(strictParser.parse(invalid));
} catch (ParseException e) {
    System.out.println("ParseException: " + e.getMessage());
}
Lenient parse result: Fri Feb 14 00:00:00 UTC 2025
Strict parse result: ParseException: Unparseable date: "2024-13-45"

SimpleDateFormat में टाइमज़ोन हैंडलिंग

SimpleDateFormat फॉर्मेटर पर टाइमज़ोन सेट करके एक ही Date को अलग-अलग टाइमज़ोन में रेंडर कर सकता है। एक Date ऑब्जेक्ट केवल UTC मिलीसेकंड काउंट स्टोर करता है और अपने स्वयं का कोई टाइमज़ोन नहीं रखता। टाइमज़ोन एक फॉर्मेटिंग चिंता है, स्टोरेज चिंता नहीं; वही Date मान अलग-अलग मानव-पठनीय आउटपुट उत्पन्न करता है जो इस बात पर निर्भर करता है कि फॉर्मेटर कौन सा टाइमज़ोन लागू करता है। इसका मतलब है कि setTimeZone() को format() कॉल करने से पहले फॉर्मेटर पर कॉल किया जाना चाहिए; इसे बाद में सेट करने का पहले से उत्पादित आउटपुट पर कोई प्रभाव नहीं पड़ता।

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

Date timestamp = new Date(1700000000000L); // दोहराने योग्य आउटपुट के लिए निश्चित इंस्टेंट
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("UTC: " + formatter.format(timestamp));
formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println("New York: " + formatter.format(timestamp));
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
System.out.println("Kolkata: " + formatter.format(timestamp));
UTC: 2023-11-14 22:13:20 +0000
New York: 2023-11-14 17:13:20 -0500
Kolkata: 2023-11-15 03:43:20 +0530

गहरे टाइमज़ोन रूपांतरण पैटर्न के लिए जावा डेट को विशिष्ट टाइमज़ोन फॉर्मेट में कैसे बदलें देखें।

सामान्य टाइमज़ोन गलतियाँ और उनसे कैसे बचें

टाइमज़ोन बग अक्सर संग्रहीत इंस्टेंट को रेंडर्ड स्थानीय समय के साथ भ्रमित करने से आते हैं।

  • Date UTC मिलीसेकंड स्टोर करता है, और टाइमज़ोन केवल फॉर्मेटिंग करते समय लागू होता है
  • मल्टीथ्रेडेड वातावरण में साझा फॉर्मेटर इंस्टेंस पर setTimeZone() कॉल करने से किसी अन्य थ्रेड की इन-फ्लाइट कॉल के लिए टाइमज़ोन मध्य-संचालन में बदल सकता है, जिससे कोई अपवाद फेंके बिना गलत टाइमज़ोन में आउटपुट उत्पन्न होता है
  • सर्वलेट या स्प्रिंग कंट्रोलर में HTTP अनुरोधों में एकल SimpleDateFormat इंस्टेंस का पुन: उपयोग करने से एक अनुरोध का setTimeZone() कॉल दूसरे अनुरोध के आउटपुट को प्रभावित कर सकता है; प्रति अनुरोध एक नया इंस्टेंस बनाएं या स्टेट को अलग करने के लिए ThreadLocal<SimpleDateFormat> का उपयोग करें
  • TimeZone.getTimeZone("Invalid/Zone") चुपचाप GMT पर फॉलबैक करता है क्योंकि मेथड कॉन्ट्रैक्ट अपरिचित IDs के लिए डिफ़ॉल्ट के रूप में GMT निर्दिष्ट करता है बजाय अपवाद फेंकने के
  • java.time से ZoneId.of() के साथ ज़ोन IDs को मान्य करें TimeZone.getTimeZone() में पास करने से पहले; ZoneId.of() अमान्य ID पर ZoneRulesException फेंकता है, जो समस्या को स्पष्ट करता है

लोकेल-अवेयर डेट फॉर्मेटिंग

फ्रेंच महीने के नाम या जर्मन दिन के नाम जैसे लोकेल-विशिष्ट डेट आउटपुट उत्पन्न करने के लिए, SimpleDateFormat कंस्ट्रक्टर को Locale पास करें। सामान्य क्षेत्रों के लिए बिल्ट-इन कॉन्स्टेंट Locale.US, Locale.UK, Locale.FRENCH, Locale.GERMAN का उपयोग करें, या कस्टम लोकेल बनाने के लिए Locale.Builder का उपयोग करें जब आपको कॉन्स्टेंट द्वारा कवर नहीं किए गए क्षेत्र की आवश्यकता हो। Locale महीने के नाम, दिन के नाम, और AM/PM मार्कर जैसे टेक्स्ट फ़ील्ड के लिए उपयोग की जाने वाली भाषा को नियंत्रित करता है।

SimpleDateFormat कंस्ट्रक्टर में लोकेल निर्दिष्ट करना

दूसरे कंस्ट्रक्टर आर्गुमेंट के रूप में Locale पास करें। यदि आप इसे छोड़ देते हैं, तो SimpleDateFormat आंतरिक रूप से Locale.getDefault() को कॉल करता है, जो फॉर्मेटर को JVM के रनटाइम लोकेल से बांधता है, एक ऐसा मान जो डेवलपर मशीनों, CI वातावरण, और विभिन्न OS लोकेल कॉन्फ़िगरेशन के तहत चलने वाले प्रोडक्शन सर्वरों के बीच भिन्न होता है।

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

Date sample = new Date(1700000000000L);
String pattern = "EEEE, dd MMMM yyyy";
SimpleDateFormat usFormatter = new SimpleDateFormat(pattern, Locale.US);
SimpleDateFormat frFormatter = new SimpleDateFormat(pattern, Locale.FRENCH);
String usDate = usFormatter.format(sample);
String frDate = frFormatter.format(sample);
System.out.println("US: " + usDate);
System.out.println("French: " + frDate);
US: Tuesday, 14 November 2023
French: mardi, 14 novembre 2023

क्षेत्र के अनुसार महीने और दिन के नाम फॉर्मेट करना

वही पैटर्न लोकेल द्वारा अलग टेक्स्ट आउटपुट उत्पन्न करता है।

लोकेलपैटर्नआउटपुट
Locale.USEEEE, dd MMMM yyyyTuesday, 14 November 2023
Locale.FRENCHEEEE, dd MMMM yyyymardi, 14 novembre 2023
Locale.GERMANEEEE, dd MMMM yyyyDienstag, 14 November 2023

सर्वर वातावरण में चल रहे JVM में Locale.getDefault() पर भरोसा करना असंगत आउटपुट उत्पन्न कर सकता है क्योंकि OS लोकेल सेटिंग्स होस्ट में भिन्न होती हैं। हमेशा एक स्पष्ट Locale पास करें।

SimpleDateFormat के साथ थ्रेड सेफ्टी समस्याएं

SimpleDateFormat थ्रेड-सेफ क्यों नहीं है

SimpleDateFormat पार्स/फॉर्मेट ऑपरेशन के दौरान आंतरिक Calendar और NumberFormat स्टेट को म्यूटेट करता है। यदि कई थ्रेड एक इंस्टेंस का उपयोग करते हैं, तो ये परिवर्तनीय फ़ील्ड मध्य-संचालन में ओवरराइट हो सकते हैं, जिससे रेस कंडीशन और अप्रत्याशित आउटपुट होता है। व्यवहार में यह एक थ्रेड की तारीखों के दूसरे थ्रेड के परिणाम में दिखाई देने, .parse() के बिना किसी अपवाद के पूरी तरह से गलत तारीख लौटाने, या फॉर्मेटर के अंदर से ArrayIndexOutOfBoundsException फेंके जाने के रूप में सामने आता है। ये विफलताएं आंतरायिक और लोड-निर्भर हैं, जो उन्हें सिंगल-थ्रेडेड टेस्ट वातावरण में पुन: उत्पन्न करना मुश्किल बनाती हैं।

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

SimpleDateFormat इंस्टेंस को अलग करने के लिए ThreadLocal का उपयोग

ThreadLocal<SimpleDateFormat> प्रत्येक थ्रेड को अपना फॉर्मेटर इंस्टेंस देता है और साझा परिवर्तनीय स्थिति से बचाता है। सर्वलेट कंटेनर और स्प्रिंग एप्लिकेशन जैसे थ्रेड-पूल वातावरण में, थ्रेड्स को अनुरोधों में पुन: उपयोग किया जाता है और कभी समाप्त नहीं होता, जिसका अर्थ है ThreadLocal मान कभी स्वचालित रूप से हटाए नहीं जाते। ऑपरेशन पूरा होने के बाद हमेशा FORMATTER.remove() कॉल करें, या फॉर्मेटर इंस्टेंस थ्रेड के जीवनकाल के लिए बना रहेगा और निरंतर लोड के तहत मेमोरी लीक के रूप में जमा होगा।

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class ThreadSafeLegacyFormatter {
    // प्रत्येक थ्रेड को एक समर्पित फॉर्मेटर इंस्टेंस मिलता है।
    private static final ThreadLocal<SimpleDateFormat> FORMATTER = ThreadLocal.withInitial(() ->
        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US));

    public static String format(Date date) {
        try {
            // कोई क्रॉस-थ्रेड म्यूटेशन नहीं क्योंकि प्रत्येक थ्रेड अपना फॉर्मेटर पढ़ता है।
            return FORMATTER.get().format(date);
        } finally {
            // उपयोग के बाद इंस्टेंस को हटाएं ताकि थ्रेड पूल में मेमोरी लीक न हो।
            FORMATTER.remove();
        }
    }
}

थ्रेड-सेफ विकल्प के रूप में DateTimeFormatter पर स्विच करना

DateTimeFormatter अपरिवर्तनीय और थ्रेड-सेफ है, इसलिए एक साझा स्टैटिक इंस्टेंस सुरक्षित है।

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;

// थ्रेड्स में साझा होने पर थ्रेड-सेफ नहीं
SimpleDateFormat unsafe = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
System.out.println(unsafe.format(new Date()));

// थ्रेड-सेफ: DateTimeFormatter अपरिवर्तनीय है और इसे स्टैटिक फ़ील्ड के रूप में संग्रहीत किया जा सकता है
DateTimeFormatter safe = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.US);
System.out.println(safe.format(LocalDateTime.now()));
2026-01-05 14:30:22
2026-01-05 14:30:22

SimpleDateFormat से DateTimeFormatter में माइग्रेशन

DateTimeFormatter पर माइग्रेशन थ्रेड-सेफ्टी जोखिमों को हटाता है, ThreadLocal वर्कअराउंड को समाप्त करता है, और java.time प्रकारों के साथ साफ़ एकीकरण करता है। अधिकांश कोडबेस के लिए माइग्रेशन मैकेनिकल है: पैटर्न सिंटैक्स लगभग समान है, दो API वृद्धिशील रोलआउट के दौरान सह-अस्तित्व में रह सकते हैं, और आपको एक साथ सब कुछ बदलने की आवश्यकता नहीं है। मुख्य जोखिम u प्रतीक है, जिसका अर्थ SimpleDateFormat में डे-ऑफ-वीक और DateTimeFormatter में वर्ष है; इस प्रतीक की जांच किए बिना API के बीच सीधे कॉपी किए गए पैटर्न चुपचाप गलत आउटपुट उत्पन्न करेंगे।

साइड-बाय-साइड कोड तुलना

यह साइड-बाय-साइड स्निपेट लिगेसी और आधुनिक API में समकक्ष फॉर्मेटिंग और पार्सिंग व्यवहार दिखाता है।

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;

String pattern = "yyyy-MM-dd";
String input = "2026-01-05";

// SimpleDateFormat (लिगेसी java.util.Date API)
SimpleDateFormat legacyFormatter = new SimpleDateFormat(pattern, Locale.US);
Date legacyParsed = legacyFormatter.parse(input);
String legacyFormatted = legacyFormatter.format(new Date());

// DateTimeFormatter (आधुनिक java.time API)
DateTimeFormatter modernFormatter = DateTimeFormatter.ofPattern(pattern, Locale.US);
LocalDate modernParsed = LocalDate.parse(input, modernFormatter);
String modernFormatted = modernFormatter.format(LocalDate.now());

System.out.println(legacyParsed);
System.out.println(legacyFormatted);
System.out.println(modernParsed);
System.out.println(modernFormatted);
Mon Jan 05 00:00:00 UTC 2026
2026-01-05
2026-01-05
2026-01-05

दोनों API के बीच पैटर्न सिंटैक्स अंतर

अधिकांश पैटर्न अक्षर समान हैं, लेकिन कुछ प्रतीक भिन्न हैं और सीधे कॉपी किए जाने पर माइग्रेशन को तोड़ सकते हैं।

कार्यSimpleDateFormat पैटर्नDateTimeFormatter पैटर्ननोट
वर्षyyyyuuuu या yyyyjava.time में प्रोलेप्टिक वर्ष स्थिरता के लिए uuuu पसंद करें
टाइमज़ोन ऑफसेट/नामz, Z, Xz, Z, x, Xjava.time अधिक ऑफसेट वेरिएंट (x और X) को अलग करता है
शाब्दिक टेक्स्ट'T''T'दोनों API शाब्दिक के लिए सिंगल कोट्स का उपयोग करते हैं
u प्रतीकडे-ऑफ-वीक नंबरवर्षज्ञात गोटचा: u API के बीच अर्थ बदलता है

चरण-दर-चरण माइग्रेशन चेकलिस्ट

मौजूदा कोडबेस में एक बार में एक फॉर्मेटर को कन्वर्ट करने के लिए इस चेकलिस्ट का उपयोग करें।

  1. import java.text.SimpleDateFormat; को import java.time.format.DateTimeFormatter; से बदलें
  2. new SimpleDateFormat("yyyy-MM-dd") को DateTimeFormatter.ofPattern("yyyy-MM-dd") से बदलें
  3. इनपुट परिशुद्धता के आधार पर .parse() को LocalDate.parse() या LocalDateTime.parse() से बदलें
  4. .format(date) को formatter.format(localDate) या formatter.format(localDateTime) से बदलें
  5. जहां संभव हो new Date() को हटाएं और LocalDate.now() या Instant.now() का उपयोग करें

DateTimeFormatter विशेष रूप से java.time प्रकारों (LocalDate, LocalDateTime, ZonedDateTime, Instant) के साथ काम करता है। यह सीधे java.util.Date स्वीकार नहीं करता। यदि आपके पास कोड है जो अभी भी java.util.Date मान उत्पन्न करता है, उदाहरण के लिए लिगेसी ORM या JDBC ड्राइवर से, date.toInstant() के साथ पहले कन्वर्ट करें DateTimeFormatter में पास करने से पहले। दोनों API वृद्धिशील माइग्रेशन के दौरान एक ही कोडबेस में सह-अस्तित्व में रह सकते हैं; आपको एक साथ सब कुछ बदलने की आवश्यकता नहीं है। DateTimeFormatter ParseException को java.time.format.DateTimeParseException से भी बदल देता है, जो अनचेक्ड अपवाद है, इसलिए ट्राई-कैच ब्लॉक वैकल्पिक हो जाते हैं लेकिन प्रोडक्शन पार्सिंग कोड में अभी भी अनुशंसित हैं।

माइग्रेशन संदर्भ और प्रकार विकल्पों के लिए, जावा 8 डेट, LocalDate, LocalDateTime, इंस्टेंट देखें।

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

जावा में SimpleDateFormat और DateFormat में क्या अंतर है?

DateFormat एक एब्स्ट्रैक्ट क्लास है जो डेट/टाइम फॉर्मेटिंग के लिए कॉन्ट्रैक्ट परिभाषित करती है। SimpleDateFormat इसका ठोस सबक्लास है जो कस्टम पैटर्न-आधारित फॉर्मेटिंग की अनुमति देता है। आप कोड में SimpleDateFormat का सीधे उपयोग करते हैं; जब आप किसी भी कार्यान्वयन को स्वीकार करना चाहते हैं तो रेफरेंस प्रकार के रूप में DateFormat का उपयोग करते हैं।

क्या SimpleDateFormat थ्रेड-सेफ है?

नहीं। SimpleDateFormat इंस्टेंस थ्रेड-सेफ नहीं हैं। सिंक्रनाइज़ेशन के बिना थ्रेड्स में एक इंस्टेंस साझा करने से अप्रत्याशित पार्स और फॉर्मेट परिणाम होते हैं। ThreadLocal<SimpleDateFormat> का उपयोग करें या इसे java.time.format.DateTimeFormatter से बदलें, जो अपरिवर्तनीय और थ्रेड-सेफ है।

SimpleDateFormat का उपयोग करके dd-MM-yyyy फॉर्मेट में डेट स्ट्रिंग को कैसे पार्स करें?

पैटर्न "dd-MM-yyyy" के साथ SimpleDateFormat इंस्टेंशिएट करें, फिर .parse(yourString) कॉल करें। ParseException के लिए ट्राई-कैच ब्लॉक में कॉल को लपेटें। सुनिश्चित करें कि इनपुट स्ट्रिंग सेपरेटर वर्णों सहित पैटर्न से सटीक मेल खाती है।

SimpleDateFormat का उपयोग करके Date को अलग टाइमज़ोन में कैसे बदलें?

अपने SimpleDateFormat इंस्टेंस पर .format(date) कॉल करने से पहले .setTimeZone(TimeZone.getTimeZone("America/New_York")) कॉल करें। अंतर्निहित Date ऑब्जेक्ट UTC मिलीसेकंड रखता है; फॉर्मेटर आउटपुट के दौरान टाइमज़ोन ऑफसेट लागू करता है।

पैटर्न "yyyy-MM-dd'T'HH:mm:ssZ" क्या उत्पन्न करता है?

यह ISO 8601-संगत टाइमस्टैम्प उत्पन्न करता है, उदाहरण के लिए 2024-06-15T14:30:00+0530। T सिंगल कोट्स में लिपटा एक शाब्दिक वर्ण है। Z RFC 822 टाइमज़ोन ऑफसेट का प्रतिनिधित्व करता है।

SimpleDateFormat से DateTimeFormatter में माइग्रेशन कैसे करें?

new SimpleDateFormat("yyyy-MM-dd") को DateTimeFormatter.ofPattern("yyyy-MM-dd") से बदलें। .parse() कॉल को LocalDate.parse() या LocalDateTime.parse() से बदलें। .format(date) कॉल को formatter.format(localDate) से बदलें। ध्यान दें कि DateTimeFormatter कुछ संदर्भों में y के बजाय वर्ष के लिए u का उपयोग करता है।

SimpleDateFormat अमान्य डेट को अपवाद फेंके बिना क्यों पार्स करता है?

डिफ़ॉल्ट रूप से, SimpleDateFormat लीनियंट पार्सिंग मोड का उपयोग करता है, जो आउट-ऑफ-रेंज मानों को अस्वीकार करने के बजाय समायोजित करता है। पार्सिंग से पहले .setLenient(false) कॉल करके सख्त सत्यापन लागू करें और अमान्य इनपुट पर ParseException फेंकें।

SimpleDateFormat का उपयोग करके विशिष्ट लोकेल के साथ डेट कैसे फॉर्मेट करें?

कंस्ट्रक्टर के दूसरे आर्गुमेंट के रूप में Locale पास करें: new SimpleDateFormat("dd MMMM yyyy", Locale.FRENCH)। यह महीने और दिन के नामों को निर्दिष्ट भाषा में रेंडर करता है, जो कई क्षेत्रों की सेवा करने वाले एप्लिकेशन के लिए महत्वपूर्ण है।

निष्कर्ष

इस गाइड में DateFormat और SimpleDateFormat फंडामेंटल, पैटर्न सिंटैक्स, फॉर्मेटिंग और पार्सिंग वर्कफ़्लो, टाइमज़ोन व्यवहार, लोकेल-अवेयर रेंडरिंग, थ्रेड सेफ्टी मुद्दे, और DateTimeFormatter पर माइग्रेशन शामिल हैं।

अब आप लिगेसी और आधुनिक कोड के लिए सही फॉर्मेटर चुन सकते हैं, सख्त सत्यापन के साथ इनपुट को रक्षात्मक रूप से पार्स कर सकते हैं, सर्वर वातावरण में लोकेल और टाइमज़ोन ड्रिफ्ट से बच सकते हैं, और साझा डेट फॉर्मेटर से कंकरेंसी जोखिमों को हटा सकते हैं।

अगले चरणों के लिए, जावा 8 डेट, LocalDate, LocalDateTime, इंस्टेंट, उदाहरणों के साथ जावा 8 फीचर्स, जावा में अपवाद हैंडलिंग, और जावा डेट को विशिष्ट टाइमज़ोन फॉर्मेट में कैसे बदलें की समीक्षा करें ताकि जावा एप्लिकेशन में डेट/टाइम हैंडलिंग को आधुनिक बनाना जारी रख सकें।

संदर्भ:

  • SimpleDateFormat API डॉक
  • DateFormat API डॉक
  • DateTimeFormatter API डॉक

जावा डेट फॉर्मेटिंग में महारत: SimpleDateFormat और DateFormat समझाया गयायह कार्य क्रिएटिव कॉमन्स एट्रिब्यूशन-नॉनकमर्शियल-शेयरअलाइक 4.0 इंटरनेशनल लाइसेंस के तहत लाइसेंस प्राप्त है।

  1. Android में EditText पर ईमेल एड्रेस वैलिडेशन कैसे करें? Android में EditText पर ईमेल एड्रेस वैलिडेशन कैसे करें?

    यह उदाहरण दर्शाता है कि Android में EditText पर ईमेल एड्रेस वैलिडेशन कैसे करें। ईमेल वैलिडेशन का उदाहरण चरण 1 - नया प्रोजेक्ट बनाएं Android Studio में एक नया प्रोजेक्ट बनाएं: File → New Project पर जाएं और आवश्यक विवरण भरें। चरण 2 - लेआउट XML में कोड जोड़ें res/layout/activity_main.xml में निम्नलि

  1. PHP में imagecolorallocatealpha() फंक्शन PHP में imagecolorallocatealpha() फंक्शन

    imagecolorallocatealpha() फंक्शन इमेज के लिए रंग आवंटित करता है। सिंटैक्स imagecolorallocatealpha ( img, red, green, blue, alpha ) पैरामीटर्स img: imagecreatetruecolor() के साथ बनाया गया इमेज रिसोर्स। red: लाल रंग घटक green: हरा रंग घटक blue: नीला रंग घटक alpha: इमेज की पारदर्शिता, 0 पूरी तरह से

  1. C++ में दिए गए प्रीऑर्डर ट्रैवर्सल से फुल k-एरी ट्री बनाना C++ में दिए गए प्रीऑर्डर ट्रैवर्सल से फुल k-एरी ट्री बनाना

    हमें एक सरणी arr[] दी गई है जिसमें k-एरी ट्री का प्रीऑर्डर ट्रैवर्सल क्रम में है। लक्ष्य उसी k-एरी ट्री को उससे बनाना और उसका पोस्टऑर्डर ट्रैवर्सल प्रिंट करना है। एक फुल k-एरी ट्री वह है जिसमें रूट नोड के 0 या k चाइल्ड होते हैं यानी अधिकतम k चाइल्ड। उदाहरण के लिए इनपुट int arr[] = {2, 5, 1, 3, 6, 7,