दो java.util की तुलना करना। यह देखने के लिए कि क्या वे एक ही दिन में हैं


250

मुझे दो Dateएस (जैसे date1औरdate2 ) और एक साथ आते हैं boolean sameDay, जिनमें से दो का सच है Dateरों शेयर एक ही दिन, और झूठे यदि वे नहीं कर रहे हैं।

मैं यह कैसे कर सकता हूँ? यहाँ भ्रम की एक बवंडर प्रतीत होता है ... और मैं अगर संभव हो तो जेडीके से परे अन्य निर्भरता में खींचने से बचना चाहूंगा।

स्पष्ट करने के लिए: यदि date1और date2उसी वर्ष, महीने और दिन को साझा करें, तो sameDayसच है, अन्यथा यह गलत है। मुझे लगता है कि इसके लिए एक समयक्षेत्र के ज्ञान की आवश्यकता है ... एक समयक्षेत्र में पास होना अच्छा होगा लेकिन जब तक मुझे पता है कि व्यवहार क्या है, तब तक मैं जीएमटी या स्थानीय समय के साथ रह सकता हूं।

फिर से, स्पष्ट करने के लिए:

date1 = 2008 Jun 03 12:56:03
date2 = 2008 Jun 03 12:59:44
  => sameDate = true

date1 = 2009 Jun 03 12:56:03
date2 = 2008 Jun 03 12:59:44
  => sameDate = false

date1 = 2008 Aug 03 12:00:00
date2 = 2008 Jun 03 12:00:00
  => sameDate = false

बस स्पष्ट करने के लिए - आप जानना चाहते हैं कि क्या सप्ताह के एक ही दिन दो दिनांक वस्तुएं गिरती हैं?
रॉब हेसर

क्या आप पूर्ण तिथि (दिन, माह, वर्ष) या केवल महीने के दिन की तुलना करना चाहते हैं?
XpiritO

1
@ रोब: नहीं, उसी दिन / महीने / वर्ष ... मैं स्पष्ट कर दूंगा।
जेसन एस

तो फिर आप "बराबर" का उपयोग क्यों नहीं करते?
XpiritO

7
क्योंकि घंटे / मिनट / सेकंड अलग होने पर वे समान नहीं हैं।
जेसन एस

जवाबों:


416
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(date1);
cal2.setTime(date2);
boolean sameDay = cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
                  cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);

ध्यान दें कि "एक ही दिन" एक सरल अवधारणा नहीं है जैसा कि लगता है जब विभिन्न समय क्षेत्र शामिल हो सकते हैं। उपरोक्त तिथियां दोनों तिथियों के लिए उस दिन के समय की गणना करती हैं, जिस समय यह कंप्यूटर द्वारा उपयोग किया जाता है। यदि यह वह नहीं है जिसकी आपको आवश्यकता है, तो आपको संबंधित समय क्षेत्र (क्षेत्रों) को पास करना होगाCalendar.getInstance() कॉल करना होगा, जब आप यह तय कर लेंगे कि वास्तव में "उसी दिन" के साथ आपका क्या मतलब है।

और हां, जोडा टाइम LocalDateपूरे मामले को बहुत साफ और आसान बना देगा (हालांकि समय क्षेत्र को शामिल करने वाली समान कठिनाइयां मौजूद होंगी)।


धन्यवाद, ऐसा लगता है कि यह वही करेगा जो मैं चाहता हूं। मेरे मामले में मैं एक श्रृंखला में लगातार तारीखों की तुलना कर रहा हूं, इसलिए ऐसा लगता है कि मैं अपनी श्रृंखला में दिनांक उदाहरणों के बजाय कैलेंडर उदाहरणों का उपयोग कर सकता हूं।
जेसन एस

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

शांत, धन्यवाद, मैं यहां पूछे गए तुलना-वर्तमान-और-पिछले-दिन के तर्क का उपयोग कर रहा हूं। "बराबर" और "हैशकोड" फ़ंक्शन को कभी भी कॉल नहीं किया जाना चाहिए।
जेसन एस

1
@UmerHayat: कोड वर्ष के दिन की तुलना करता है, न कि महीने के दिन की। एक कम तुलना आवश्यक, कम कोड।
माइकल बॉर्गवर्ड

2
सुझाव: DAY_OF_YEAR की तुलना पहले करें, इसके लिए वर्ष की जाँच नहीं करनी होगी। ठीक है, ऐसा लगता है कि इंट की तुलना करना वास्तव में महंगा नहीं है लेकिन ...
मार्टिन पी।

332

कैसा रहेगा:

SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
return fmt.format(date1).equals(fmt.format(date2));

आप जरूरत पड़ने पर टाइमडाजो को सिंपलडेटफार्मेट में भी सेट कर सकते हैं।


2
(मैं वास्तव में SimpleDateFormat का उपयोग वैसे भी मेरे मामले में कर रहा हूं, इसलिए यह उचित लगता है।)
जेसन एस

8
मैं वास्तव में इसे देखकर आश्चर्यचकित हूं, लेकिन एक प्रदर्शन के दृष्टिकोण से भी, यह SimpleDateFormatविधि वास्तव में Calendarएस का उपयोग करते हुए यहां बताए गए अन्य की तुलना में तेज है । औसतन यह Calendarविधि के रूप में आधा समय लेता है । (कम से कम मेरे सिस्टम पर)। कुडोस!
माइकल प्लॉत्ज़

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

1
मैं स्विफ्ट में भी ऐसा करता हूं। यह आश्चर्यजनक है कि इस तरह की सरल चीज़ को अधिकांश भाषाओं में समान हैक की आवश्यकता होती है। C # अपवाद होना - if (d1.Date == d2.Date) ...
alpsystems.com

2
यह कुरूप है; इस तरह एक हैक को देखकर हैरान रह गए।
Zsolt Safrany

162

मैं ऐसा करने के लिए "अपाचे कॉमन्स लैंग" पैकेज का उपयोग करता हूं (अर्थात् org.apache.commons.lang.time.DateUtils )

boolean samedate = DateUtils.isSameDay(date1, date2);  //Takes either Calendar or Date objects

2
यह एक बाहरी निर्भरता का उपयोग करता है ... लेकिन भविष्य के लिए जानना अच्छा है।
जेसन एस

20
बस स्रोत को कॉपी करें और इसे एक दिन कॉल करें :)
एंटोन कुज़मिन

लेकिन यह एक अवैध तर्क अपवाद को फेंकता है यदि किसी भी दिन शून्य है, जो कुछ मामलों में आदर्श नहीं है।
रविराज

1
जैसा कि stackoverflow.com/a/2517824/1665809 में टिप्पणी की गई है, यह समाधान उचित नहीं हो सकता है यदि अलग-अलग समय क्षेत्र शामिल हों।
mrod

24

आप बाहरी निर्भरता से बच सकते हैं और प्रत्येक तिथि के लिए जूलियन डे नंबर की गणना करके कैलेंडर का उपयोग करने के प्रदर्शन को प्रभावित कर सकते हैं और फिर इनकी तुलना कर सकते हैं:

public static boolean isSameDay(Date date1, Date date2) {

    // Strip out the time part of each date.
    long julianDayNumber1 = date1.getTime() / MILLIS_PER_DAY;
    long julianDayNumber2 = date2.getTime() / MILLIS_PER_DAY;

    // If they now are equal then it is the same day.
    return julianDayNumber1 == julianDayNumber2;
}

4
लेकिन सावधान रहें कि यह दिन की बचत के कारण दिन की लंबाई में परिवर्तन को ध्यान में रखने में विफल रहता है । लेकिन फिर सीधे Dateएस समय क्षेत्र की धारणा को अतिक्रमण नहीं करते हैं, इसलिए गैर-मनमाने ढंग से इसे ठीक करने का कोई तरीका नहीं है।
ऐयज

3
यह सबसे तेजी से समाधान है - बहुत बहुत धन्यवाद, वास्तव में मैं क्या देख रहा था; जैसा कि मुझे बहुत सारी तारीखों की जाँच करनी है ...
Ridcully

2
नाइटपिक: date1.getTime () जूलियन डे नंबर वापस नहीं करता है, लेकिन 1970-01-01 से मिलीसेकंड। बड़ा अंतर।
प्रति लिंडबर्ग

2
यह यूटीसी समय क्षेत्र में तुलना करता है। यदि आप अपना स्थानीय समय क्षेत्र या ग्रह पर कोई अन्य स्थान चाहते हैं, तो आप यह नहीं जान सकते हैं कि आपको प्राप्त होने वाला परिणाम सही है या नहीं।
ओले वीवी

20

Joda समय

एक निर्भरता जोड़ने के लिए, मुझे java.util से डर लगता है। दोस्तो और। कैलेन्डर वास्तव में इतने बुरे हैं कि मैं किसी भी नए प्रोजेक्ट के लिए सबसे पहले जोडा-टाइम लाइब्रेरी को जोड़ता हूं। जावा 8 में आप नए java.time पैकेज का उपयोग कर सकते हैं, जोडा-टाइम से प्रेरित है।

जोडा-टाइम का मूल DateTimeवर्ग है। Java.util.Date के विपरीत, यह अपने निर्धारित समय क्षेत्र ( DateTimeZone) को समझता है । जूडे से परिवर्तित करते समय, एक ज़ोन असाइन करें।

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTimeQuébec = new DateTime( date , zone );

LocalDate

यह सत्यापित करने का एक तरीका है कि एक ही तिथि पर दो बार-बार भूमि LocalDateऑब्जेक्ट में कनवर्ट हो ।

यह रूपांतरण निर्दिष्ट समय क्षेत्र पर निर्भर करता है। LocalDateवस्तुओं की तुलना करने के लिए , उन्हें उसी क्षेत्र के साथ परिवर्तित किया जाना चाहिए।

यहाँ थोड़ी उपयोगिता विधि है।

static public Boolean sameDate ( DateTime dt1 , DateTime dt2 )
{
    LocalDate ld1 = new LocalDate( dt1 );
    // LocalDate determination depends on the time zone.
    // So be sure the date-time values are adjusted to the same time zone.
    LocalDate ld2 = new LocalDate( dt2.withZone( dt1.getZone() ) );
    Boolean match = ld1.equals( ld2 );
    return match;
}

बेहतर एक और तर्क होगा, पहले डेटटाइम ऑब्जेक्ट के टाइम ज़ोन का उपयोग करने के बजाय टाइम ज़ोन को निर्दिष्ट करना।

static public Boolean sameDate ( DateTimeZone zone , DateTime dt1 , DateTime dt2 )
{
    LocalDate ld1 = new LocalDate( dt1.withZone( zone ) );
    // LocalDate determination depends on the time zone.
    // So be sure the date-time values are adjusted to the same time zone.
    LocalDate ld2 = new LocalDate( dt2.withZone( zone ) );
    return ld1.equals( ld2 );
}

स्ट्रिंग प्रतिनिधित्व

एक अन्य दृष्टिकोण प्रत्येक तिथि-समय के दिनांक भाग के एक स्ट्रिंग प्रतिनिधित्व का निर्माण करना है, फिर तार की तुलना करें।

फिर से, निर्धारित समय क्षेत्र महत्वपूर्ण है।

DateTimeFormatter formatter = ISODateTimeFormat.date();  // Static method.
String s1 = formatter.print( dateTime1 );
String s2 = formatter.print( dateTime2.withZone( dt1.getZone() )  );
Boolean match = s1.equals( s2 );
return match;

समय की सीमा

सामान्यीकृत समाधान समय की अवधि को परिभाषित करना है, फिर पूछें कि क्या अवधि में आपका लक्ष्य है। यह उदाहरण कोड Joda-Time 2.4 में है। ध्यान दें कि "मध्यरात्रि" -संबद्ध वर्गों को पदावनत किया जाता है। इसके बजाय का उपयोग करेंwithTimeAtStartOfDay विधि का । Joda-Time विभिन्न तरीकों से समय की अवधि का प्रतिनिधित्व करने के लिए तीन कक्षाएं प्रदान करता है: अंतराल, अवधि और अवधि।

"हाफ-ओपन" दृष्टिकोण का उपयोग करते हुए जहां स्पैन की शुरुआत समावेशी और अंतिम अनन्य है।

लक्ष्य का समय क्षेत्र अंतराल के समय क्षेत्र से भिन्न हो सकता है।

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime target = new DateTime( 2012, 3, 4, 5, 6, 7, timeZone );
DateTime start = DateTime.now( timeZone ).withTimeAtStartOfDay();
DateTime stop = start.plusDays( 1 ).withTimeAtStartOfDay();
Interval interval = new Interval( start, stop );
boolean containsTarget = interval.contains( target );

java.time

जावा 8 और बाद में जावा.टाइम फ्रेमवर्क के साथ आता है । जेएसआर 310 द्वारा परिभाषित, जोडा-टाइम से प्रेरित और थ्रीटेन-एक्स्ट्रा प्रोजेक्ट द्वारा विस्तारित। ट्यूटोरियल देखें

Joda-Time के निर्माताओं ने हम सभी को निर्देश दिया है कि जैसे ही सुविधाजनक हो, java.time पर जाएं। इस बीच, Joda-Time एक सक्रिय रूप से बनाए रखा परियोजना के रूप में जारी है। लेकिन भविष्य के काम की उम्मीद है कि यह केवल Joda.time और थ्रीटेन-एक्स्ट्रा में होने के बजाय Joda-Time से होता है।

संक्षेप में java.time को संक्षेप में… Instantयूटीसी में एक समयरेखा पर एक क्षण है। ऑब्जेक्ट ZoneIdप्राप्त करने के लिए एक समय क्षेत्र ( ) लागू करें ZonedDateTime। दिनांक-समय की अस्पष्ट अनिश्चितकालीन विचार प्राप्त करने के समय बंद जाने के लिए,, "स्थानीय" वर्गों का उपयोग करें: LocalDateTime, LocalDate, LocalTime

इस उत्तर के जोडा-टाइम खंड में चर्चित तर्क java.time पर लागू होता है।

पुराने java.util.Date वर्ग के पास toInstantjava.time में रूपांतरण के लिए एक नई विधि है।

Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type.

तिथि निर्धारित करने के लिए एक समय क्षेत्र की आवश्यकता होती है।

ZoneId zoneId = ZoneId.of( "America/Montreal" );

हम उस समय क्षेत्र ऑब्जेक्ट Instantको प्राप्त करने के लिए आवेदन करते हैं ZonedDateTime। उस से हम एक तारीख-केवल मूल्य (ए LocalDate) निकालते हैं क्योंकि हमारा लक्ष्य तारीखों की तुलना करना है (घंटे, मिनट आदि नहीं)।

ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate1 = LocalDate.from( zdt1 );

java.util.Dateतुलना के लिए हमें जिस दूसरी वस्तु की आवश्यकता है , वही करें । मैं इसके बजाय वर्तमान क्षण का उपयोग करूंगा।

ZonedDateTime zdt2 = ZonedDateTime.now( zoneId );
LocalDate localDate2 = LocalDate.from( zdt2 );

isEqualएक ही तिथि मान के लिए परीक्षण करने के लिए विशेष विधि का उपयोग करें ।

Boolean sameDate = localDate1.isEqual( localDate2 );

java.time: या आप बस कर सकते हैंLocalDate localDate = LocalDate.fromDateFields(yourJavaUtilDate);
CyberMew

1
@CyberMew एर? मेरी कक्षाfromDateFields() में कोई नहीं है । LocalDate
ओले वीवी

1
क्षमा करें, मुझे स्पष्ट होना चाहिए था। टिप्पणी Joda-Time LocalDate वर्ग के लिए प्रासंगिक है ।
साइबरएम

7

Java 8 java.time को दिनांक परिवर्तित करेंयहाँ देखें

LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

// compare dates
assertTrue("Not on the same day", localDate1.equals(localDate2));

यह मेरा पसंदीदा उत्तर है। यदि आप कंप्यूटर की सेटिंग पर निर्भर होने के बजाय उपयोग किए जाने वाले समय क्षेत्र को नियंत्रित करना चाहते हैं, तो यह सीधे तौर पर उदाहरण के लिए ZoneId.of("America/Phoenix") या ZoneId.of("Europe/Budapest")सिस्टम डिफॉल्ट के बजाय इसमें डाला जाना चाहिए।
ओले वीवी

6

जावा 8

यदि आप अपनी परियोजना में जावा 8 का उपयोग कर रहे हैं और तुलना कर रहे हैं java.sql.Timestamp, तो आप LocalDateकक्षा का उपयोग कर सकते हैं :

sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate());

यदि आप उपयोग कर रहे हैं java.util.Date, तो इस्तवान जवाब पर एक नज़र डालें जो कम अस्पष्ट है।


Java 8 का उपयोग करना एक अच्छा विचार है। क्या आप मान रहे हैं date1और date2हैं java.sql.Timestamp? प्रश्न के अनुसार वे हैं Date, मैं समझूंगा java.util.Date। इसके अलावा आपका कोड कंप्यूटर के समय क्षेत्र की सेटिंग का उपयोग करता है, जो कई उद्देश्यों के लिए ठीक होगा; फिर भी मैं इस तथ्य को कोड में स्पष्ट करना पसंद करूंगा।
ओले वीवी

@ OleV.V। आपकी टिप्पणी के लिए धन्यवाद, मेरा मूल उत्तर वास्तव में था java.sql.Timestamp। जैसा कि आपने कहा कि आमतौर पर समय क्षेत्र को स्पष्ट रूप से निर्धारित करना बेहतर होता है।
अक्टूबर को

5
private boolean isSameDay(Date date1, Date date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);
        boolean sameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
        boolean sameMonth = calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
        boolean sameDay = calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH);
        return (sameDay && sameMonth && sameYear);
    }

5

एंड्रॉइड उपयोगकर्ताओं के लिए:

आप उपयोग कर सकते हैं DateUtils.isToday(dateMilliseconds) जांचने के लिए कर सकते हैं कि दी गई तिथि वर्तमान दिन है या नहीं।

एपीआई संदर्भ: https://developer.android.com/reference/android/text/format/DateUtils.html#isToday(long)


1
इस विधि का उपयोग वस्तु समय जो एपीआई 22 के बाद से किया गया है: developer.android.com/reference/android/text/format/Time.html
ओलेक्सांद्रा बोडास्को

2
Android डेवलपर के लिए +1। इस विधि का उपयोग आदिम लंबे समय तक पैरामीटर के रूप में किया जाता है, बस उपयोग करें DateUtils.isToday(x.getTime())(x एक java.util.date उदाहरण है)
jackycflau

1

बिनिल थॉमस समाधान के अलावा

public static boolean isOnSameDay(Timestamp... dates) {
    SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
    String date1 = fmt.format(dates[0]);
    for (Timestamp date : dates) {
        if (!fmt.format(date).equals(date1)) {
            return false;
        }
    }
    return true;
}

प्रयोग

    isOnSameDay(date1,date2,date3 ...);
//or 
    isOnSameDay(mydates);

1

Kotlin devs के लिए यह स्वरूपित स्ट्रिंग्स दृष्टिकोण की तुलना करने वाला संस्करण है:

val sdf = SimpleDateFormat("yyMMdd")
if (sdf.format(date1) == sdf.format(date2)) {
    // same day
}

यह सबसे अच्छा तरीका नहीं है, लेकिन यह छोटा और काम कर रहा है।


1
जेएसआर 310 में परिभाषित SimpleDateFormatआधुनिक java.time.DateTimeFormatterवर्ग द्वारा वर्षों पहले इस वर्ग का दमन किया गया था । 2019 में इसके उपयोग का सुझाव देना खराब सलाह है।
बेसिल बोर्के

2
यह कोड समय क्षेत्र के महत्वपूर्ण मुद्दे की अनदेखी करता है। किसी भी क्षण के लिए, तिथि क्षेत्र के अनुसार दुनिया भर में भिन्न होती है।
बेसिल बोर्के

-4

आप SimpleDateFormat पर भरोसा किए बिना SimpleDateFormat समाधान के रूप में एक ही तर्क लागू कर सकते हैं

date1.getFullYear()*10000 + date1.getMonth()*100 + date1.getDate() == 
date2.getFullYear()*10000 + date2.getMonth()*100 + date2.getDate()

6
ये विधियाँ java.util.Date में पदावनत हैं। ऐसा करने के लिए आपको कैलेंडर का उपयोग करना चाहिए। इसके अलावा यह getYear है, getFullYear नहीं
Kris
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.