Jak porównać dwie daty bez przedziału czasu?


202

Chciałbym mieć metodę CompareTo, która ignoruje część czasu java.util.Date. Sądzę, że istnieje wiele sposobów rozwiązania tego. Jaki jest najprostszy sposób?

Odpowiedzi:


212

Aktualizacja: chociaż Joda Time była wówczas świetną rekomendacją, w miarę możliwości korzystaj z java.timebiblioteki Java 8+.


Wolę używać Joda Time, co czyni to niezwykle łatwym:

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

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

return firstDate.compareTo(secondDate);

EDYCJA: Jak zaznaczono w komentarzach, jeśli używasz DateTimeComparator.getDateOnlyInstance(), jest jeszcze prostsze :)

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

(„Użyj Joda Time” jest podstawą prawie wszystkich pytań SO, które zadają pytania dotyczące java.util.Datelub java.util.Calendar. Jest to całkowicie lepszy interfejs API. Jeśli robisz coś znaczącego z datami / godzinami, powinieneś naprawdę go użyć, jeśli to możliwe.)

Jeśli jesteś absolutnie zmuszony do korzystania z wbudowanego interfejsu API, powinieneś utworzyć instancję Calendarz odpowiednią datą i przy użyciu odpowiedniej strefy czasowej. Następnie możesz ustawić każde pole w każdym kalendarzu poza godziną, minutą, sekundą i milisekundą na 0 i porównać otrzymane czasy. Zdecydowanie obrzydliwe w porównaniu z rozwiązaniem Joda :)

Strefa czasowa jest to ważne: java.util.Datejest zawsze oparte na UTC. W większości przypadków, gdy byłem zainteresowany datą, była to data w określonej strefie czasowej . To samo w sobie zmusi cię do korzystania z CalendarJoda Time (chyba że sam chcesz wziąć pod uwagę strefę czasową, której nie polecam).

Krótki przewodnik dla programistów Androida

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

Przykładowy kod (przykład)

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
Chociaż, jak mówi Jon, „Use Joda Time” jest podstawą prawie wszystkich SO pytań, które dotyczą java.util.Date lub java.util.Calendar Zawsze myślę, że po pierwsze najlepiej jest udzielić konkretnej odpowiedzi na podstawie pytania użytkownika, na przynajmniej by pokazać, jak trudne może być zrobienie w java sposób. A potem sugerowanie używania
Jody

13
@JuanZe: Wymaga to dokładnego określenia, jak właściwie zrobić coś w bolesnym API, co z definicji jest bolesne. Wolę spędzać ten czas na robieniu czegoś bardziej produktywnego :)
Jon Skeet

1
@ MetroidFan2002: LocalDate to lepsza opcja niż DateMidnight, ponieważ jest bardziej ekspresyjna - i nie wszystkie dni mają północy ...
Jon Skeet

2
@dertoni: Jasne - w Brazylii, kiedy zegary idą do przodu ze względu na czas letni, dzieje się to na początku dnia ... więc zegar odczytuje 23:59:58, 23:59:59, 01:00 : 00, 01:00:01 itd.
Jon Skeet

8
Czy nie lepiej byłoby użyć DateTimeComparator.getDateOnlyInstance ()
Emil

125

Apache commons-lang jest prawie wszechobecny. A co z tym?

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

Wersja 2.6 zawiera funkcję truncatedCompareTo commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/…
użytkownik

2
Niestety nie toleruje dat zerowych
Pavel Niedoba

Chłopaki, obecnie mamy Java 8 stackoverflow.com/a/35411693/259237
André

Nie polecam korzystania z tego w ten sposób, ponieważ jeśli pierwszy lub drugi obiekt Date został przesłany z datownika i ma milisekundy, a drugi jest normalnym obiektem Date, będziesz miał problem, ponieważ: Data z magazynu dat w innej części przedmiotu milisekundy dają różnice, nawet jeśli obie daty są równe.
Zini

Niestety, Apache nie ma więcej niż 1,3 miliarda urządzeń z Androidem i jest to ogromna biblioteka, na której można polegać tylko w jednym przypadku. Będę potrzebować czegoś innego: /
milosmns

58

Jeśli naprawdę chcesz użyć java.util.Date, zrobiłbyś coś takiego:

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();
  }
}

lub używając zamiast tego Kalendarza (preferowane, ponieważ getYear () i takie są przestarzałe)

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
W drugiej metodzie zapomniałeś zaktualizować niektóre ze swoich odniesień, od d1, d2 do c1, c2.
stivlo

1
Po naprawieniu tego szczegółu twój kod działa dobrze: dokładnie go przetestowałem. Dodałem krok, aby utworzyć Kalendarz z dat i użyłem twojego kodu w moim nowo utworzonym projekcie github org.obliquid.helpers , dzięki.
stivlo

Słodkie, miłe rozwiązanie bez użycia zewnętrznej biblioteki.
4gus71n

1
Wszystkie te metody są przestarzałe. Czy może to mieć jakikolwiek wpływ?
Pranav Mahajan

36

Moje preferencje byłoby użyć Joda biblioteki insetad się java.util.Datebezpośrednio, jak Joda dokonuje rozróżnienia pomiędzy datą i godziną (patrz YearMonthDay i DateTime klas).

Jeśli jednak chcesz użyć java.util.Date, proponuję napisać metodę narzędzia; na przykład

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 jest przestarzałe na rzecz LocalDate. Ponadto kod w kalendarzu będzie miał problemy, jeśli strefa czasowa nie ma północy 00:00 ze względu na oszczędność czasu.
JodaStephen

1
To nie działa w 100% przypadków. Miałem przypadek użycia, w którym to zrobiłem, a calendar.getTime () nadal zwracałby czas z godzinami ustawionymi jako data parametru. Najlepiej wyczyścić pola i ustawić tylko rok, miesiąc i dzień.
Jonathan Drapeau

31

Jakieś opinie na temat tej alternatywy?

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

1
Nie sądzę, żeby to działało, nawet jeśli konwersja na Strings była dobrym pomysłem. ==Operator nie musi powrócić truerównoważną łańcuchy (stosowania equals()). Z pewnością nie możesz również użyć innych operatorów porównania, o których wspomniałeś.
harto

1
Ach tak - mój rubin rujnuje moją Javę! Może konwertować ciągi znaków na ints dla <,> itd.
Robert Brown

Korzystanie z Jody to dobry sposób, ale jest elegancki!
Arne Evertsson,

To nie będzie działać dla wszystkich, ale jest bardzo proste i lekkie; dobra alternatywa, gdy inne biblioteki nie są dostępne.
Jacob Marble

Aby uzyskać kolejność dat, możesz również użyć sdf.format(date1).compareTo(sdf.format(date2));.
Ole VV

18

Jeśli chcesz porównać tylko miesiąc, dzień i rok dwóch dat, dla mnie działa następujący kod:

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

Dzięki, Rob.


13

Ja też wolę Joda Time , ale oto alternatywa:

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

EDYTOWAĆ

Poniżej umieszczam UTC na wypadek, gdybyś musiał porównać daty dla określonej strefy czasowej innej niż UTC. Jeśli jednak masz taką potrzebę, to naprawdę radzę wybrać Jodę.

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

Powiedziałem, że wolę używać Joda Time, ale to dobra uwaga. Stosuję tak niskie taktyki tylko wtedy, gdy tak naprawdę nie interesuję się TZ.
Daniel C. Sobral,

Podziału można uniknąć:Math.abs(second.getTime() - first.getTime()) < 1000L*60*60*24
Vadzim,

@Vadzim Make it < oneDay.
Daniel C. Sobral

2
@Vadzim, który sprawdza tylko, czy daty są krótsze niż 1 dzień od siebie. Nie musi to oznaczać, że są tego samego dnia.
arahant

@arahant, tak. może to być wystarczające, gdy druga data jest zawsze wyrównana do północy.
Vadzim

12

tl; dr

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

Unikaj starszych klas daty i godziny

Unikaj starych, kłopotliwych klas daty i czasu, takich jak Date& Calendar, teraz zastąpionych przez klasy java.time.

Korzystanie z java.time

A java.util.Dateoznacza moment na osi czasu w UTC. Odpowiednikiem w java.time jest Instant. Możesz dokonać konwersji za pomocą nowych metod dodanych do starszej klasy.

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

Chcesz porównać według daty. Strefa czasowa ma kluczowe znaczenie przy ustalaniu daty. W danym momencie data zmienia się na całym świecie w zależności od strefy. Na przykład kilka minut po północy w Paryżu Francja to nowy dzień, a jeszcze „wczoraj” w Montrealu Quebec .

Określ prawidłową nazwę strefy czasowej w formacie continent/region, takie jak America/Montreal, Africa/Casablancalub Pacific/Auckland. Nigdy nie używaj 3-4 literowego skrótu, takiego jak ESTlub, ISTponieważ nie są to prawdziwe strefy czasowe, nie są znormalizowane, a nawet unikalne (!).

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

Zastosuj ZoneIddo, Instantaby uzyskać ZonedDateTime.

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

LocalDateKlasa reprezentuje wartość data-tylko bez time-of-day i bez strefy czasowej. Możemy wyodrębnić LocalDatez ZonedDateTime, skutecznie eliminując porę dnia.

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

Teraz porównać, przy użyciu metod, takich jak isEqual, isBeforei isAfter.

Boolean sameDate = localDate1.isEqual( localDate2 );

Zobacz ten kod uruchamiany na żywo w IdeOne.com .

instant1: 2017-03-25T04: 13: 10.971Z | instant2: 2017-03-24T22: 13: 10.972Z

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

localDate1: 2017-03-25 | localDate2: 2017-03-24

sameData: fałsz


O java.time

Środowisko java.time jest wbudowane w Javę 8 i nowsze wersje . Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak java.util.Date, Calendar, i SimpleDateFormat.

Projekt Joda-Time , teraz w trybie konserwacji , zaleca migrację do klas java.time .

Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj stos przepełnienia dla wielu przykładów i wyjaśnień. Specyfikacja to JSR 310 .

Gdzie można uzyskać klasy java.time?

Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Można znaleźć kilka przydatnych klas tutaj takie jak Interval, YearWeek, YearQuarter, i więcej .


7

Wspomniane już apache commons-utils :

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

daje ci obiekt Date zawierający tylko datę, bez czasu, i możesz ją porównać Date.compareTo


6

Obawiam się, że nie ma metody porównywania dwóch dat, które można by nazwać „łatwymi” lub „prostymi”.

Porównując dwa wystąpienia czasowe z jakimkolwiek ograniczeniem precyzji (np. Po prostu porównując daty), zawsze należy wziąć pod uwagę wpływ strefy czasowej na porównanie.

Jeśli date1określasz zdarzenie, które wystąpiło w strefie czasowej +2 i date2określa na przykład zdarzenie, które wystąpiło w EST, musisz zadbać o właściwe zrozumienie konsekwencji porównania.

Czy chcesz dowiedzieć się, czy dwa wydarzenia miały miejsce w tym samym dniu kalendarzowym w ich odpowiednich strefach czasowych? A może musisz wiedzieć, czy dwie daty mieszczą się w tej samej dacie kalendarzowej w określonej strefie czasowej (na przykład UTC lub lokalny TZ).

Gdy dowiesz się, co tak naprawdę próbujesz porównać, wystarczy, że potroisz datę roku-miesiąca w odpowiedniej strefie czasowej i dokonasz porównania.

Czas Jody może sprawić, że rzeczywista operacja porównania będzie wyglądać na znacznie czystszą, ale semantyka porównania wciąż jest czymś, co musisz samemu wymyślić.



5

Jeśli chcesz porównać tylko dwie daty bez czasu, poniższy kod może ci pomóc:

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
}

To to samo co odpowiedź Roba . Myślę, że rozwiązanie Jorna jest lepsze, ponieważ nie wiąże się z objazdem do łańcuchów i powinno osiągnąć to samo.
Rup

4

Oto rozwiązanie z tego bloga: 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.");

tzn. możesz zobaczyć, czy różnica czasu w milisekundach jest mniejsza niż długość jednego dnia.


4
Ta próbka sprawdzi, czy dwie daty są w ciągu 24 godzin od siebie, ale niekoniecznie, jeśli obie są w tym samym dniu, tzn. Możliwe jest wybranie północy. Lepiej byłoby zamiast tego podzielić oba zestawy milisów przez MILLIS_IN_DAY i porównać wynik, ale będzie to dokładne tylko dla czasu UTC, a nie czasu lokalnego.
Rup

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

Nie wiem, czy to nowy pomysł, ale pokazuję wam, jak to zrobiłem

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

Wystarczy sprawdzić DAY_OF_YEAR w połączeniu z właściwością YEAR

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

EDYTOWAĆ:

Teraz możemy wykorzystać moc funkcji rozszerzenia 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
    }
}

Jest to złe, ponieważ daty z różnymi latami mogą mieć ten sam dzień w roku, na przykład 2015-01-01 i 2016-01-01.
nelson eldoro

@ nelsoneldoro dzięki za komentarz, zapomniałem dodać czek na rok, teraz powinno być w porządku.
Simon K. Gerges,

2

W Javie 8 możesz używać LocalDate, która jest bardzo podobna do tej z 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();
}

Pomoże Ci to porównać daty bez uwzględnienia czasu.


1

Używając getDateInstance z SimpleDateFormat, możemy porównać tylko dwa obiekty daty bez czasu. Wykonaj poniższy kod.

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

Kolejna prosta metoda porównywania oparta na odpowiedziach tutaj i wskazówkach mojego mentora

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());
  }

EDYCJA : Według @Janathan Drapeau, powyższy kod zawodzi w niektórych przypadkach (chciałbym zobaczyć te przypadki, proszę) i zasugerował, co rozumiem:

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());
}

Zwróć uwagę, że klasa Date jest przestarzała, ponieważ nie była podatna na internacjonalizację. Zamiast tego używana jest klasa Calendar!


To nie działa w 100% przypadków. Miałem przypadek użycia, w którym to zrobiłem, a calendar.getTime () nadal zwracałby czas z godzinami ustawionymi jako data parametru. Najlepiej wyczyścić pola i ustawić tylko rok, miesiąc i dzień.
Jonathan Drapeau

@JonathanDrapeau, brzmi dla mnie tak, jakbyś mógł spotkać się z konsekwencją braku wybrania wyraźnej strefy czasowej. Z pewnością lepiej wyraź strefę czasową, niż używaj przestarzałych getXxxmetod Date.
Ole VV

1

Po pierwsze, należy pamiętać, że ta operacja zależy od strefy czasowej. Więc wybierz, czy chcesz to zrobić w UTC, w strefie czasowej komputera, we własnej ulubionej strefie czasowej lub gdzie. Jeśli nie jesteś jeszcze przekonany, że to ma znaczenie, zobacz mój przykład na dole tej odpowiedzi.

Ponieważ twoje pytanie nie jest do końca jasne, zakładam, że masz klasę z polem instancji reprezentującym moment w czasie i implementującym Comparable, i chcesz, aby naturalne uporządkowanie twoich obiektów było według daty, ale nie godziny , z tego pola. Na przykład:

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
    }

}

java.timeKlasy Java 8

Brałem wolność zmiany typu swojej dziedzinie instancji od Datecelu Instant, odpowiednie klasy w Javie 8. Obiecuję, aby powrócić do leczenia Dateponiżej. Dodałem również stałą strefy czasowej. Możesz ustawić go na ZoneOffset.UTClub, ZoneId.of("Europe/Stockholm")co uważasz za odpowiednie (ustawienie na ZoneOffsetdziała, ponieważ ZoneOffsetjest to podklasa ZoneId).

Zdecydowałem się pokazać rozwiązanie za pomocą klas Java 8. Prosiłeś o najprostszy sposób, prawda? :-) Oto compareTometoda, o którą prosiłeś:

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

Jeśli nie trzeba część czasu when, to oczywiście łatwiejsze zadeklarować i pominąć wszystkie konwersje. W takim razie nie musimy się już martwić strefą czasową.whenLocalDate

Załóżmy teraz, że z jakiegoś powodu nie możesz zadeklarować swojego whenpola Instantlub chcesz zachować staroświeckie Date. Jeśli nadal możesz używać języka Java 8, po prostu przekonwertuj go na Instant, a następnie wykonaj następujące czynności:

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

Podobnie dla o.when .

Brak Java 8?

Jeśli nie możesz użyć java 8, istnieją dwie opcje:

  1. Rozwiązać go za pomocą jednego z dawnych klas, albo CalendarczySimpleDateFormat .
  2. Użyj backportu klas daty i godziny Java 8 do Java 6 i 7, a następnie po prostu wykonaj powyższe czynności. Podaję link na dole. Nie używaj JodaTime. JodaTime była prawdopodobnie dobrą propozycją, gdy zostały napisane odpowiedzi, które ją zalecały; ale JodaTime jest teraz w trybie konserwacji, więc backport ThreeTen jest lepszą i bardziej odporną na przyszłość opcją.

Staromodne sposoby

Odpowiedź Adamskiego pokazuje, jak pozbawić część czasu Datekorzystania z Calendarklasy. Sugeruję, aby użyć getInstance(TimeZone)do uzyskania Calendarinstancji dla wybranej strefy czasowej. Alternatywnie możesz skorzystać z pomysłu z drugiej połowy odpowiedzi Jorna .

Korzystanie SimpleDateFormatjest naprawdę pośrednim sposobem korzystania, Calendarponieważ obiekt SimpleDateFormatzawiera Calendarobiekt. Jednak może być mniej kłopotliwe niż Calendarbezpośrednie:

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));
}

To było zainspirowane odpowiedzią Roba .

Zależność strefy czasowej

Dlaczego musimy wybrać konkretną strefę czasową? Powiedzmy, że chcemy porównać dwa razy w UTC: 24 marca 0:00 (północ) i 12:00 (południe). Jeśli zrobisz to w CET (powiedzmy, Europa / Paryż), będą to 1 rano i 13 po południu 24 marca, czyli w tym samym dniu. W Nowym Jorku (wschodni czas letni) są one 20:00 w dniu 23 marca i 8:00 w dniu 24 marca, czyli nie w tym samym dniu. To decyduje, którą strefę czasową wybierzesz. Jeśli polegasz tylko na domyślnych ustawieniach komputera, możesz być zaskoczony, gdy ktoś próbuje uruchomić kod na komputerze w innym miejscu w zglobalizowanym świecie.

Połączyć

Link do ThreeTen Backport, backport klas daty i godziny Java 8 do Java 6 i 7: http://www.threeten.org/threetenbp/ .


0

Moja propozycja:

    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

Używając wspólnych Apache możesz:

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   

jest to najprostszy sposób rozwiązania tego problemu.


0

Rozwiązałem to, porównując według znacznika czasu:

    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
    }

Unikam używania Joda Time, ponieważ na Androidzie używa ogromnej przestrzeni. Rozmiar ma znaczenie. ;)


0

Innym rozwiązaniem korzystającym z Java 8 i Instant jest metoda truncatedTo

Zwraca kopię tego błyskawicznego skrótu do określonej jednostki.

Przykład:

@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)
}

Dzięki! Istnieje jednak kilka innych odpowiedzi z tym samym podejściem - chociaż widzę, że bezpośrednio porównujesz obiekty kalendarza, podczas gdy w dużej mierze porównują one getTime ().
Rup

-2

Oto, co zadziałało dla mnie:

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
Twoje „normalne” porównanie nawet nie skompiluje się w Javie. Jeśli tak, porównałby odwołania do obiektów, ale nie jest to dozwolone.
stivlo

Zredagowałem, aby dodać Markdown, ale stivlo ma rację. Nie mam pojęcia, jak ten kod „działał dla ciebie”.
Wyskakuje

To prawdopodobnie js.
Andrey Luiz,

-2

Jak o DateUtil.daysBetween(). Jest to Java i zwraca liczbę (różnicę dni).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.