Làm thế nào để so sánh hai Ngày không có phần thời gian?


203

Tôi muốn có một phương thức so sánh mà bỏ qua phần thời gian của java.util.Date. Tôi đoán có một số cách để giải quyết điều này. Cách đơn giản nhất là gì?

Câu trả lời:


212

Cập nhật: trong khi Joda Time là một đề xuất tốt vào thời điểm đó, hãy sử dụng java.timethư viện từ Java 8+ thay vào đó nếu có thể.


Sở thích của tôi là sử dụng Joda Time , điều này làm cho việc này cực kỳ dễ dàng:

DateTime first = ...;
DateTime second = ...;

LocalDate firstDate = first.toLocalDate();
LocalDate secondDate = second.toLocalDate();

return firstDate.compareTo(secondDate);

EDIT: Như đã lưu ý trong các bình luận, nếu bạn sử dụng DateTimeComparator.getDateOnlyInstance()nó thậm chí còn đơn giản hơn :)

// TODO: consider extracting the comparator to a field.
return DateTimeComparator.getDateOnlyInstance().compare(first, second);

( "Sử dụng Joda Thời gian" là nền tảng của hầu hết các câu hỏi SO mà hỏi về java.util.Datehay java.util.Calendar. Đó là một API triệt để vượt trội. Nếu bạn đang làm bất cứ điều gì có ý nghĩa với ngày / lần, bạn thực sự cần sử dụng nó nếu bạn có thể.)

Nếu bạn hoàn toàn bị buộc phải sử dụng API tích hợp, bạn nên tạo một phiên bản Calendarvới ngày thích hợp và sử dụng múi giờ thích hợp. Sau đó, bạn có thể đặt từng trường trong mỗi lịch ngoài giờ, phút, giây và mili giây thành 0 và so sánh thời gian kết quả. Chắc chắn icky so với giải pháp Joda mặc dù :)

Các múi giờ một phần rất quan trọng: java.util.Dateluôn luôn dựa trên UTC. Trong hầu hết các trường hợp tôi quan tâm đến một ngày, đó là một ngày trong một múi giờ cụ thể . Điều đó tự nó sẽ buộc bạn sử dụng Calendarhoặc Joda Time (trừ khi bạn muốn tự mình tính đến múi giờ mà tôi không khuyến nghị.)

Tham khảo nhanh cho các nhà phát triển Android

//Add joda library dependency to your build.gradle file
dependencies {
     ...
     implementation 'joda-time:joda-time:2.9.9'
}

Mã mẫu (ví dụ)

DateTimeComparator dateTimeComparator = DateTimeComparator.getDateOnlyInstance();

Date myDateOne = ...;
Date myDateTwo = ...;

int retVal = dateTimeComparator.compare(myDateOne, myDateTwo);

if(retVal == 0)
   //both dates are equal
else if(retVal < 0)
   //myDateOne is before myDateTwo
else if(retVal > 0)
   //myDateOne is after myDateTwo

28
Rõ ràng như Jon nói "Sử dụng thời gian Joda" là cơ sở của hầu hết tất cả các câu hỏi SO hỏi về java.util.Date hoặc java.util.CalWiki Tôi luôn nghĩ rằng trước hết là đưa ra câu trả lời cụ thể dựa trên câu hỏi của người dùng, tại ít nhất để cho thấy mức độ khó có thể làm theo cách java. Và sau đó gợi ý sử dụng Joda ...
JuanZe

13
@JuanZe: Điều đó đòi hỏi phải tìm ra chính xác cách thực hiện một cái gì đó đúng cách trong một API đau đớn, theo định nghĩa là đau đớn. Tôi thà dành thời gian đó để làm việc gì đó hiệu quả hơn :)
Jon Skeet

1
@ MetroidFan2002: LocalDate là một lựa chọn tốt hơn so với DateUnnight, vì nó biểu cảm hơn - không phải tất cả các ngày đều có nửa đêm ...
Jon Skeet

2
@dertoni: Chắc chắn - ở Brazil, khi đồng hồ đi về phía trước do thời gian tiết kiệm ánh sáng ban ngày, điều đó xảy ra vào đầu ngày ... vì vậy một chiếc đồng hồ sẽ đọc 23:59:58, 23:59:59, 01:00 : 00, 01:00:01, v.v.
Jon Skeet

8
Sẽ không tốt hơn nếu sử dụng DateTimeComparator.getDateOnlyInstance ()
Emil

125

Apache commons-lang gần như có mặt khắp nơi. Vậy cái này thì sao?

if (DateUtils.isSameDay(date1, date2)) {
    // it's same
} else if (date1.before(date2)) {
   // it's before
} else {
   // it's after
}

Phiên bản 2.6 bao gồm chức năng cắt
ngắnCompareTo

2
Đáng buồn là không chịu được ngày vô giá trị
Pavel Niedoba

Các bạn, ngày nay chúng ta có Java 8 stackoverflow.com/a/35411693/259237
André

Tôi không khuyên bạn nên sử dụng trước cách này bởi vì nếu là người đầu tiên hoặc các đối tượng ngày thứ hai đã được donwcasted từ Timestamp và có mileseconds, và khác là một một ngày đối tượng bình thường bạn sẽ gặp khó khăn bởi vì, ngày từ dấu ngày tháng lưu trữ trong một phần khác nhau của đối tượng, milisecond cho sự khác biệt ngay cả khi cả hai ngày bằng nhau.
Zini

Thật không may, Apache không phải trên 1,3 tỷ thiết bị Android và đó là một thư viện khổng lồ chỉ phụ thuộc vào một trường hợp sử dụng. Tôi sẽ cần một cái gì đó khác: /
milosmns

58

Nếu bạn thực sự muốn sử dụng java.util.Date, bạn sẽ làm một cái gì đó như thế này:

public class TimeIgnoringComparator implements Comparator<Date> {
  public int compare(Date d1, Date d2) {
    if (d1.getYear() != d2.getYear()) 
        return d1.getYear() - d2.getYear();
    if (d1.getMonth() != d2.getMonth()) 
        return d1.getMonth() - d2.getMonth();
    return d1.getDate() - d2.getDate();
  }
}

hoặc, sử dụng Lịch thay thế (ưu tiên, vì getYear () và như vậy không được dùng nữa)

public class TimeIgnoringComparator implements Comparator<Calendar> {
  public int compare(Calendar c1, Calendar c2) {
    if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR)) 
        return c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
    if (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH)) 
        return c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
    return c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);
  }
}

1
Trong phương pháp thứ hai, bạn quên cập nhật một số tài liệu tham khảo của mình, từ d1, d2 đến c1, c2.
stivlo

1
Sau khi sửa chi tiết đó, mã của bạn hoạt động tốt: Tôi đã kiểm tra đơn vị rộng rãi. Tôi đã thêm bước để tạo Lịch từ ngày và đã sử dụng mã của bạn trong dự án github mới được tạo của tôi org.obl Liquid.helpers , cảm ơn.
stivlo

Giải pháp ngọt ngào, tốt đẹp mà không cần sử dụng bất kỳ thư viện bên ngoài.
4gus71n

1
Tất cả các phương pháp này đều không được chấp nhận. Điều này có thể có bất kỳ loại tác động?
Pranav Mahajan

36

Sở thích của tôi sẽ là sử dụng trực tiếp thư viện Jodajava.util.Date , vì Joda phân biệt giữa ngày và thời gian (xem các lớp YearMonthDayDateTime ).

Tuy nhiên, nếu bạn muốn sử dụng, java.util.Datetôi khuyên bạn nên viết một phương thức tiện ích; ví dụ

public static Date setTimeToMidnight(Date date) {
    Calendar calendar = Calendar.getInstance();

    calendar.setTime( date );
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    return calendar.getTime();
}

1
Joda-Time YearMonthDay không được dùng cho LocalDate. Ngoài ra, mã trên lịch sẽ có vấn đề nếu múi giờ không có nửa đêm 00:00 do tiết kiệm ánh sáng ban ngày.
JodaStephen

1
Điều này không hoạt động 100% thời gian. Có một trường hợp sử dụng trong đó tôi đã làm điều đó và calendar.getTime () vẫn sẽ trả về thời gian với số giờ được đặt là ngày tham số. Tốt nhất để xóa các lĩnh vực và chỉ thiết lập năm, tháng và ngày.
Jonathan Drapeau

31

Bất kỳ ý kiến ​​về sự thay thế này?

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

1
Tôi không nghĩ rằng nó sẽ hoạt động, ngay cả khi chuyển đổi sang String là một ý tưởng tốt. Các ==nhà điều hành không nhất thiết phải trở truecho tương đương Strings (sử dụng equals()). Bạn chắc chắn không thể sử dụng các toán tử so sánh khác mà bạn đã đề cập.
harto

1
À đúng rồi - viên hồng ngọc của tôi đang hủy hoại Java của tôi! Có thể chuyển đổi chuỗi thành int mặc dù cho <,> vv
Robert Brown

Sử dụng Joda là cách âm thanh, nhưng điều này là thanh lịch!
Arne Evertsson

Điều này sẽ không làm việc cho tất cả mọi người, nhưng nó rất đơn giản và nhẹ; một lựa chọn tốt khi các lib khác không có sẵn.
Jacob Marble

Để có được thứ tự của ngày, bạn cũng có thể sử dụng sdf.format(date1).compareTo(sdf.format(date2));.
Ole VV

18

Nếu bạn chỉ muốn so sánh tháng, ngày và năm của hai ngày, mã sau đây hoạt động với tôi:

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

Cảm ơn Rob.


13

Tôi cũng thích Joda Time , nhưng đây là một giải pháp thay thế:

long oneDay = 24 * 60 * 60 * 1000
long d1 = first.getTime() / oneDay
long d2 = second.getTime() / oneDay
d1 == d2

BIÊN TẬP

Tôi đặt UTC điều bên dưới trong trường hợp bạn cần so sánh ngày cho một múi giờ cụ thể khác với UTC. Tuy nhiên, nếu bạn có nhu cầu như vậy, thì tôi thực sự khuyên bạn nên đi Joda.

long oneDay = 24 * 60 * 60 * 1000
long hoursFromUTC = -4 * 60 * 60 * 1000 // EST with Daylight Time Savings
long d1 = (first.getTime() + hoursFromUTC) / oneDay
long d2 = (second.getTime() + hoursFromUTC) / oneDay
d1 == d2

Tôi đã nói rằng tôi muốn sử dụng Joda Time, nhưng đó là một điểm tốt. Tôi chỉ sử dụng các chiến thuật thấp như vậy khi tôi không thực sự quan tâm đến TZ.
Daniel C. Sobral

Bộ phận có thể tránh được:Math.abs(second.getTime() - first.getTime()) < 1000L*60*60*24
Vadzim

@Vadzim Làm cho nó < oneDay.
Daniel C. Sobral

2
@Vadzim, chỉ kiểm tra nếu ngày cách nhau dưới 1 ngày. Không nhất thiết có nghĩa là họ đang ở trong cùng một ngày.
thù

@arahant, vâng. điều này có thể đủ khi ngày thứ hai luôn luôn được căn chỉnh nửa đêm.
Vadzim

12

tl; dr

myJavaUtilDate1.toInstant()
               .atZone( ZoneId.of( "America/Montreal" ) )
               .toLocalDate()
               .isEqual (
                   myJavaUtilDate2.toInstant()
                                  .atZone( ZoneId.of( "America/Montreal" ) )
                                  .toLocalDate()
               )

Tránh các lớp học thời gian kế thừa

Tránh các lớp thời gian cũ kế thừa rắc rối như Date& Calendar, giờ được thay thế bởi các lớp java.time.

Sử dụng java.time

A java.util.Dateđại diện cho một khoảnh khắc trên dòng thời gian trong UTC. Tương đương trong java.time là Instant. Bạn có thể chuyển đổi bằng các phương thức mới được thêm vào lớp kế thừa.

Instant instant1 = myJavaUtilDate1.toInstant();
Instant instant2 = myJavaUtilDate2.toInstant();

Bạn muốn so sánh theo ngày. Một múi giờ là rất quan trọng trong việc xác định một ngày. Đối với bất kỳ thời điểm nào, ngày thay đổi trên toàn cầu theo khu vực. Chẳng hạn, vài phút sau nửa đêm ở Paris Pháp là một ngày mới trong khi ngày hôm qua vẫn còn ở Montréal Québec .

Chỉ định một tên múi giờ thích hợp trong các định dạng của continent/region, chẳng hạn như America/Montreal, Africa/Casablancahoặc Pacific/Auckland. Không bao giờ sử dụng chữ viết tắt 3-4 chữ cái như ESThoặc ISTchúng không phải là múi giờ thực, không được chuẩn hóa và thậm chí không phải là duy nhất (!).

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

Áp dụng ZoneIdđến Instantđể có được một ZonedDateTime.

ZonedDateTime zdt1 = instant1.atZone( z );
ZonedDateTime zdt2 = instant2.atZone( z );

Các LocalDatelớp đại diện cho một giá trị ngày tháng chỉ mà không cần thời gian của ngày và không có múi giờ. Chúng tôi có thể trích xuất LocalDatetừ một ZonedDateTime, loại bỏ hiệu quả phần thời gian trong ngày.

LocalDate localDate1 = zdt1.toLocalDate();
LocalDate localDate2 = zdt2.toLocalDate();

Bây giờ so sánh, sử dụng các phương pháp như isEqual, isBefore, và isAfter.

Boolean sameDate = localDate1.isEqual( localDate2 );

Xem mã này chạy trực tiếp tại IdeOne.com .

tức thì1: 2017-03-25T04: 13: 10.971Z | tức thì2: 2017-03-24T22: 13: 10.972Z

zdt1: 2017-03-25T00: 13: 10.971-04: 00 [Mỹ / Montreal] | zdt2: 2017-03-24T18: 13: 10.972-04: 00 [Mỹ / Montreal]

địa phươngDate1: 2017-03-25 | địa phươngDate2: 2017-03-24

cùng ngày: sai


Giới thiệu về java.time

Các java.time khung được xây dựng vào Java 8 và sau đó. Những lớp học thay thế cái cũ phiền hà di sản lớp học ngày thời gian như java.util.Date, Calendar, & SimpleDateFormat.

Các Joda thời gian dự án, bây giờ trong chế độ bảo trì , khuyên chuyển đổi sang các java.time lớp.

Để tìm hiểu thêm, xem Hướng dẫn Oracle . Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310 .

Nơi để có được các lớp java.time?

  • Java SE 8 SE 9 trở lên
    • Được xây dựng trong.
    • Một phần của API Java tiêu chuẩn với việc triển khai đi kèm.
    • Java 9 thêm một số tính năng nhỏ và sửa lỗi.
  • Java SE 6 SE 7
    • Phần lớn chức năng java.time được chuyển ngược lại sang Java 6 & 7 trong ThreeTen-Backport .
  • Android

Các ThreeTen-Extra dự án mở rộng java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho các bổ sung có thể trong tương lai cho java.time. Bạn có thể tìm thấy một số các lớp học hữu ích ở đây chẳng hạn như Interval, YearWeek, YearQuarter, và nhiều hơn nữa .


7

Đã đề cập đến apache commons-utils :

org.apache.commons.lang.time.DateUtils.truncate(date, Calendar.DAY_OF_MONTH)

cung cấp cho bạn đối tượng Ngày chỉ chứa ngày, không có thời gian và bạn có thể so sánh nó với Date.compareTo


6

Tôi sợ rằng không có phương pháp so sánh hai ngày có thể được gọi là "dễ dàng" hoặc "đơn giản".

Khi so sánh hai trường hợp thời gian với bất kỳ loại độ chính xác giảm nào (ví dụ: chỉ so sánh ngày), bạn phải luôn tính đến việc múi giờ ảnh hưởng đến việc so sánh như thế nào.

Ví dụ, nếu date1chỉ định một sự kiện xảy ra trong +2 múi giờ và date2chỉ định một sự kiện xảy ra trong EST, chẳng hạn, bạn phải cẩn thận để hiểu đúng ý nghĩa của so sánh.

Mục đích của bạn là tìm hiểu xem hai sự kiện đã xảy ra trong cùng một ngày theo lịch trong múi giờ tương ứng của chúng phải không? Hoặc bạn cần biết nếu hai ngày rơi vào cùng một ngày theo lịch trong một múi giờ cụ thể (ví dụ: UTC hoặc TZ địa phương của bạn).

Một khi bạn tìm ra những gì thực sự mà bạn đang cố gắng so sánh, đó chỉ là vấn đề nhận được bộ ba ngày tháng trong một múi giờ thích hợp và thực hiện so sánh.

Thời gian của Joda có thể làm cho hoạt động so sánh thực tế trông gọn gàng hơn nhiều, nhưng ngữ nghĩa của so sánh vẫn là điều bạn cần tự mình tìm ra.



5

Nếu bạn chỉ muốn so sánh chỉ hai ngày mà không có thời gian, thì đoạn mã sau có thể giúp bạn:

final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
Date dLastUpdateDate = dateFormat.parse(20111116);
Date dCurrentDate = dateFormat.parse(dateFormat.format(new Date()));
if (dCurrentDate.after(dLastUpdateDate))
{
   add your logic
}

Điều đó giống như câu trả lời của Rob . Tôi nghĩ giải pháp của Jorn là tốt hơn vì nó không liên quan đến một chuyến đi khứ hồi đến các chuỗi và sẽ hoàn thành điều tương tự.
Rupi

4

Đây là một giải pháp từ blog này: http://brigitzblog.blogspot.com/2011/10/java-compare-dates.html

long milliseconds1 = calendar1.getTimeInMillis();
long milliseconds2 = calendar2.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.println("Time in days: " + diffDays  + " days.");

tức là bạn có thể thấy nếu chênh lệch thời gian tính bằng mili giây nhỏ hơn độ dài của một ngày.


4
Mẫu đó sẽ kiểm tra xem hai ngày có trong vòng 24 giờ của nhau hay không nhưng không nhất thiết nếu cả hai cùng một ngày, tức là có thể kéo dài nửa đêm. Thay vào đó, tốt hơn là nên chia cả hai bộ millis cho MILLIS_IN_DAY và so sánh kết quả, nhưng điều đó sẽ chỉ chính xác cho UTC chứ không phải giờ địa phương.
Rupi

4

`

SimpleDateFormat sdf= new SimpleDateFormat("MM/dd/yyyy")

   Date date1=sdf.parse("03/25/2015");



  Date currentDate= sdf.parse(sdf.format(new Date()));

   return date1.compareTo(currentDate);

`


3

Tôi không biết đó là suy nghĩ mới hay khác, nhưng tôi chỉ cho bạn thấy như tôi đã làm

SimpleDateFormat dtf = new SimpleDateFormat("dd/MM/yyyy");
Date td_date = new Date();
String first_date = dtf.format(td_date);    //First seted in String 
String second_date = "30/11/2020";          //Second date you can set hear in String

String result = (first_date.equals(second_date)) ? "Yes, Its Equals":"No, It is not Equals";
System.out.println(result);

3

Chỉ cần kiểm tra DAY_OF_YEAR kết hợp với thuộc tính NĂM

boolean isSameDay = 
firstCal.get(Calendar.YEAR) == secondCal.get(Calendar.YEAR) &&
firstCal.get(Calendar.DAY_OF_YEAR) == secondCal.get(Calendar.DAY_OF_YEAR)

BIÊN TẬP:

Bây giờ chúng ta có thể sử dụng sức mạnh của các chức năng mở rộng Kotlin

fun Calendar.isSameDay(second: Calendar): Boolean {

    return this[Calendar.YEAR] == second[Calendar.YEAR] && this[Calendar.DAY_OF_YEAR] == second[Calendar.DAY_OF_YEAR]
}

fun Calendar.compareDatesOnly(other: Calendar): Int {

    return when {
        isSameDay(other) -> 0
        before(other) -> -1
        else -> 1
    }
}

Đó là sai vì ngày với các năm khác nhau có thể có cùng một ngày trong năm, ví dụ 2015-01-01 và 2016-01-01.
nelson eldoro

@nelsoneldoro cảm ơn vì nhận xét của bạn, quên thêm một kiểm tra cho năm nay, bây giờ nó sẽ ổn thôi.
Simon K. Gerges

2

Trong Java 8, bạn có thể sử dụng LocalDate rất giống với từ Joda Time.


2
public Date saveDateWithoutTime(Date date) {
    Calendar calendar = Calendar.getInstance();

    calendar.setTime( date );
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.HOUR, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    return calendar.getTime();
}

Điều này sẽ giúp bạn so sánh ngày mà không cần xem xét thời gian.


1

Sử dụng getDateInstance của SimpleDateFormat, chúng ta chỉ có thể so sánh hai đối tượng ngày mà không có thời gian. Thực thi mã dưới đây.

public static void main(String[] args) {        
        Date date1  = new Date();
        Date date2  = new Date();
        DateFormat dfg = SimpleDateFormat.getDateInstance(DateFormat.DATE_FIELD);
        String dateDtr1 = dfg.format(date1);
        String dateDtr2 = dfg.format(date2);
        System.out.println(dateDtr1+" : "+dateDtr2);
        System.out.println(dateDtr1.equals(dateDtr2));  

    }


1

Một phương pháp so sánh đơn giản khác dựa trên các câu trả lời ở đây và hướng dẫn của người cố vấn của tôi

public static int compare(Date d1, Date d2) {
    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c1.setTime(d1);
    c1.set(Calendar.MILLISECOND, 0);
    c1.set(Calendar.SECOND, 0);
    c1.set(Calendar.MINUTE, 0);
    c1.set(Calendar.HOUR_OF_DAY, 0);
    c2.setTime(d2);
    c2.set(Calendar.MILLISECOND, 0);
    c2.set(Calendar.SECOND, 0);
    c2.set(Calendar.MINUTE, 0);
    c2.set(Calendar.HOUR_OF_DAY, 0);
    return c1.getTime().compareTo(c2.getTime());
  }

EDIT : Theo @Jonathan Drapeau, đoạn mã trên không thành công trong một số trường hợp (tôi muốn xem những trường hợp đó) , và anh ấy đã gợi ý những điều sau đây khi tôi hiểu:

public static int compare2(Date d1, Date d2) {
    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c1.clear();
    c2.clear();
    c1.set(Calendar.YEAR, d1.getYear());
    c1.set(Calendar.MONTH, d1.getMonth());
    c1.set(Calendar.DAY_OF_MONTH, d1.getDay());
    c2.set(Calendar.YEAR, d2.getYear());
    c2.set(Calendar.MONTH, d2.getMonth());
    c2.set(Calendar.DAY_OF_MONTH, d2.getDay());
    return c1.getTime().compareTo(c2.getTime());
}

Xin lưu ý rằng, lớp Date không được chấp nhận vì không thể quốc tế hóa được. Lớp Lịch được sử dụng thay thế!


Điều này không hoạt động 100% thời gian. Có một trường hợp sử dụng trong đó tôi đã làm điều đó và calendar.getTime () vẫn sẽ trả về thời gian với số giờ được đặt là ngày tham số. Tốt nhất để xóa các lĩnh vực và chỉ thiết lập năm, tháng và ngày.
Jonathan Drapeau

@JonathanDrapeau, nghe có vẻ như bạn có thể đã gặp phải hậu quả của việc không chọn múi giờ rõ ràng. Chắc chắn tốt hơn làm cho múi giờ rõ ràng hơn là sử dụng các getXxxphương pháp không dùng nữa Date.
Ole VV

1

Đầu tiên, hãy lưu ý rằng thao tác này phụ thuộc vào múi giờ. Vì vậy, chọn xem bạn muốn làm điều đó trong UTC, trong múi giờ của máy tính, trong múi giờ yêu thích của riêng bạn hay ở đâu. Nếu bạn chưa thuyết phục được nó, hãy xem ví dụ của tôi ở cuối câu trả lời này.

Vì câu hỏi của bạn không rõ ràng về vấn đề này, tôi giả sử rằng bạn có một lớp với trường thể hiện đại diện cho một thời điểm và thực hiện Comparable , và bạn muốn thứ tự tự nhiên của các đối tượng của bạn là theo ngày, nhưng không phải là thời gian , của lĩnh vực đó. Ví dụ:

public class ArnesClass implements Comparable<ArnesClass> {

    private static final ZoneId arnesTimeZone = ZoneId.systemDefault();

    private Instant when;

    @Override
    public int compareTo(ArnesClass o) {
        // question is what to put here
    }

}

Các java.timelớp Java 8

Tôi đã tự do thay đổi loại trường cá thể của bạn từ Datesang Instant, lớp tương ứng trong Java 8. Tôi hứa sẽ quay lại xử lý Datebên dưới. Tôi cũng đã thêm một hằng số múi giờ. Bạn có thể đặt nó thành ZoneOffset.UTChoặc ZoneId.of("Europe/Stockholm")hoặc những gì bạn thấy phù hợp (đặt nó thành một ZoneOffsettác phẩm vì ZoneOffsetlà một lớp con của ZoneId).

Tôi đã chọn hiển thị giải pháp bằng cách sử dụng các lớp Java 8. Bạn hỏi cách đơn giản nhất, phải không? :-) Đây là compareTophương pháp bạn yêu cầu:

public int compareTo(ArnesClass o) {
    LocalDate dateWithoutTime = when.atZone(arnesTimeZone).toLocalDate();
    LocalDate otherDateWithoutTime = o.when.atZone(arnesTimeZone).toLocalDate();
    return dateWithoutTime.compareTo(otherDateWithoutTime);
}

Nếu bạn không bao giờ cần một phần thời gian của whennó là tất nhiên dễ dàng hơn để tuyên bố whenmột LocalDatevà bỏ qua tất cả các chuyển đổi. Sau đó, chúng ta không phải lo lắng về múi giờ nữa.

Bây giờ, giả sử rằng vì một số lý do, bạn không thể khai báo whentrường của mình Instanthoặc bạn muốn giữ nó theo kiểu cũ Date. Nếu bạn vẫn có thể sử dụng Java 8, chỉ cần chuyển đổi nó thành Instant, sau đó làm như trước:

    LocalDate dateWithoutTime = when.toInstant().atZone(arnesTimeZone).toLocalDate();

Tương tự cho o.when.

Không có Java 8?

Nếu bạn không thể sử dụng java 8, có hai tùy chọn:

  1. Giải quyết nó bằng một trong các lớp cũ, Calendarhoặc SimpleDateFormat.
  2. Sử dụng backport của các lớp ngày và giờ Java 8 cho Java 6 và 7, sau đó chỉ cần làm như trên. Tôi bao gồm một liên kết ở phía dưới. Không sử dụng JodaTime. JodaTime có lẽ là một gợi ý tốt khi các câu trả lời đề nghị nó được viết; nhưng JodaTime hiện đang ở chế độ bảo trì, do đó, backport ThreeTen là một tùy chọn tương lai tốt hơn và tốt hơn.

Những cách thức lỗi thời

Câu trả lời của Adamski cho bạn thấy làm thế nào để loại bỏ phần thời gian khỏi Dateviệc sử dụng Calendarlớp. Tôi đề nghị bạn sử dụng getInstance(TimeZone)để lấy Calendarví dụ cho múi giờ bạn muốn. Để thay thế, bạn có thể sử dụng ý tưởng từ nửa sau câu trả lời của Jorn .

Sử dụng SimpleDateFormatthực sự là một cách sử dụng gián tiếp CalendarSimpleDateFormatcó chứa một Calendarđối tượng. Tuy nhiên, bạn có thể thấy nó ít rắc rối hơn so với sử dụng Calendartrực tiếp:

private static final TimeZone arnesTimeZone = TimeZone.getTimeZone("Europe/Stockholm");
private static final DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
static {
    formatter.setTimeZone(arnesTimeZone);
}

private Date when;

@Override
public int compareTo(ArnesClass o) {
    return formatter.format(when).compareTo(formatter.format(o.when));
}

Điều này được lấy cảm hứng từ câu trả lời của Rob .

Phụ thuộc múi giờ

Tại sao chúng ta phải chọn một múi giờ cụ thể? Nói rằng chúng tôi muốn so sánh hai lần trong UTC là 24 tháng 3 0:00 (nửa đêm) và 12:00 (trưa). Nếu bạn làm điều đó trong CET (giả sử Châu Âu / Paris), thì họ là 1 giờ sáng và 1 giờ chiều ngày 24 tháng 3, tức là cùng ngày. Ở New York (Giờ ban ngày miền Đông), họ là 20:00 ngày 23 tháng 3 và 8:00 ngày 24 tháng 3, tức là không cùng ngày. Vì vậy, nó làm cho một sự khác biệt mà múi giờ bạn chọn. Nếu bạn chỉ dựa vào mặc định của máy tính, bạn có thể gặp bất ngờ khi ai đó cố chạy mã của bạn trên máy tính ở một nơi khác trong thế giới toàn cầu hóa này.

Liên kết

Liên kết với ThreeTen Backport, backport của các lớp ngày và giờ Java 8 với Java 6 và 7: http://www.threeten.org/threetenbp/ .


0

Đề xuất của tôi:

    Calendar cal = Calendar.getInstance();
    cal.set(1999,10,01);   // nov 1st, 1999
    cal.set(Calendar.AM_PM,Calendar.AM);
    cal.set(Calendar.HOUR,0);
    cal.set(Calendar.MINUTE,0);
    cal.set(Calendar.SECOND,0);
    cal.set(Calendar.MILLISECOND,0);

    // date column in the Thought table is of type sql date
    Thought thought = thoughtDao.getThought(date, language);

    Assert.assertEquals(cal.getTime(), thought.getDate());

0

Sử dụng Apache commons bạn có thể làm:

import org.apache.commons.lang3.time.DateUtils

DateUtils.truncatedEquals(first, second, Calendar.DAY_OF_MONTH)

0
public static Date getZeroTimeDate(Date fecha) {
    Date res = fecha;
    Calendar calendar = Calendar.getInstance();

    calendar.setTime( fecha );
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    res = calendar.getTime();

    return res;
}

Date currentDate = getZeroTimeDate(new Date());// get current date   

đây là cách đơn giản nhất để giải quyết vấn đề này


0

Tôi đã giải quyết điều này bằng cách so sánh bằng dấu thời gian:

    Calendar last = Calendar.getInstance();

    last.setTimeInMillis(firstTimeInMillis);

    Calendar current = Calendar.getInstance();

    if (last.get(Calendar.DAY_OF_MONTH) != current.get(Calendar.DAY_OF_MONTH)) {
        //not the same day
    }

Tôi tránh sử dụng Joda Time vì trên Android sử dụng một không gian rộng lớn. Vấn đề kích cỡ. ;)


0

Một giải pháp khác sử dụng Java 8 và Instant, là sử dụng phương thức rút gọn

Trả về một bản sao của Instant này bị cắt ngắn cho đơn vị được chỉ định.

Thí dụ:

@Test
public void dateTruncate() throws InterruptedException {
    Instant now = Instant.now();
    Thread.sleep(1000*5);
    Instant later = Instant.now();
    assertThat(now, not(equalTo(later)));
    assertThat(now.truncatedTo(ChronoUnit.DAYS), equalTo(later.truncatedTo(ChronoUnit.DAYS)));
}

0
// Create one day 00:00:00 calendar
int oneDayTimeStamp = 1523017440;
Calendar oneDayCal = Calendar.getInstance();
oneDayCal.setTimeInMillis(oneDayTimeStamp * 1000L);
oneDayCal.set(Calendar.HOUR_OF_DAY, 0);
oneDayCal.set(Calendar.MINUTE, 0);
oneDayCal.set(Calendar.SECOND, 0);
oneDayCal.set(Calendar.MILLISECOND, 0);

// Create current day 00:00:00 calendar
Calendar currentCal = Calendar.getInstance();
currentCal.set(Calendar.HOUR_OF_DAY, 0);
currentCal.set(Calendar.MINUTE, 0);
currentCal.set(Calendar.SECOND, 0);
currentCal.set(Calendar.MILLISECOND, 0);

if (oneDayCal.compareTo(currentCal) == 0) {
    // Same day (excluding time)
}

Cảm ơn! Mặc dù vậy, vẫn có một số câu trả lời khác có cùng cách tiếp cận - mặc dù tôi thấy bây giờ bạn đang so sánh trực tiếp các đối tượng Lịch trong khi chúng chủ yếu so sánh các getTime ().
Rup

-2

Đây là những gì làm việc cho tôi:

var Date1 = new Date(dateObject1.toDateString()); //this sets time to 00:00:00
var Date2 = new Date(dateObject2.toDateString()); 
//do a normal compare
if(Date1 > Date2){ //do something }

2
So sánh "bình thường" của bạn thậm chí sẽ không biên dịch trong Java. Nếu có, nó sẽ so sánh các tham chiếu đối tượng, nhưng điều này không được phép.
stivlo

Tôi đã chỉnh sửa để thêm Markdown, nhưng stivlo là đúng. Tôi không biết làm thế nào mã đó "làm việc cho bạn."
Pops

Đây có lẽ là js.
Andrey Luiz

-2

Thế còn DateUtil.daysBetween(). Đó là Java và nó trả về một số (chênh lệch theo ngày).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.