java.util.Date의 시간 부분을 무시하는 compareTo 메소드를 갖고 싶습니다. 이 문제를 해결하는 방법에는 여러 가지가 있다고 생각합니다. 가장 간단한 방법은 무엇입니까?
java.util.Date의 시간 부분을 무시하는 compareTo 메소드를 갖고 싶습니다. 이 문제를 해결하는 방법에는 여러 가지가 있다고 생각합니다. 가장 간단한 방법은 무엇입니까?
답변:
업데이트 : 당시 Joda Time은 권장 사항 이었지만 java.time가능한 경우 Java 8 이상 라이브러리를 사용하십시오 .
내가 선호하는 것은 Joda Time 을 사용 하는 것입니다.
DateTime first = ...;
DateTime second = ...;
LocalDate firstDate = first.toLocalDate();
LocalDate secondDate = second.toLocalDate();
return firstDate.compareTo(secondDate);
편집 : 의견에서 언급했듯이 사용 DateTimeComparator.getDateOnlyInstance()하면 훨씬 간단합니다 :)
// TODO: consider extracting the comparator to a field.
return DateTimeComparator.getDateOnlyInstance().compare(first, second);
( "사용 Joda 시간"에 대해 물어 거의 모든 SO 질문의 기초 java.util.Date나 java.util.Calendar. 그것은 철저하게 우수한 API입니다. 당신이하고있는 경우 어떤 날짜 / 시간으로 의미를 당신이 가능하게 할 수있는 경우에, 당신이 정말로 그것을 사용해야합니다.)
당신이 절대적으로하는 경우 강제 (가) API에 내장 된 사용하려면 인스턴스 생성해야 Calendar적절한 날짜 및 적절한 시간대를 사용합니다. 그런 다음 각 달력의 각 필드를 시간, 분, 초 및 밀리 초에서 0으로 설정하고 결과 시간을 비교할 수 있습니다. 확실히 Joda 솔루션과 비교하여 icky :)
시간대 부분이 중요하다는 : java.util.Date되어 항상 UTC 기준으로합니다. 날짜에 관심이있는 대부분의 경우 특정 시간대 의 날짜 였습니다 . 그 자체로 당신이 Calendar또는 Joda Time 을 사용하도록 강요 할 것입니다 (당신이 시간대를 직접 설명하고 싶지 않다면, 나는 권장하지 않습니다).
안드로이드 개발자를위한 빠른 참조
//Add joda library dependency to your build.gradle file
dependencies {
...
implementation 'joda-time:joda-time:2.9.9'
}
샘플 코드 (예)
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
Apache commons-lang 은 거의 어디에나 있습니다. 이건 어때?
if (DateUtils.isSameDay(date1, date2)) {
// it's same
} else if (date1.before(date2)) {
// it's before
} else {
// it's after
}
java.util.Date를 실제로 사용하려면 다음과 같이하십시오.
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();
}
}
또는 대신 달력을 사용하십시오 (getYear () 등이 더 이상 사용되지 않기 때문에 선호됩니다)
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);
}
}
Joda가 날짜와 시간을 구분 하기 때문에 Joda 라이브러리를 java.util.Date직접 사용하는 것이 좋습니다 ( YearMonthDay 및 DateTime 클래스 참조 ).
그러나 사용하고 싶다면 java.util.Date유틸리티 메소드를 작성하는 것이 좋습니다. 예 :
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();
}
이 대안에 대한 의견이 있으십니까?
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
sdf.format(date1).equals(sdf.format(date2));
==운영자는 반드시 반환하지 않습니다 true동등한 문자열 (사용 equals()). 언급 한 다른 비교 연산자도 사용할 수 없습니다.
sdf.format(date1).compareTo(sdf.format(date2));.
나도 Joda Time을 선호 하지만 대안은 다음과 같습니다.
long oneDay = 24 * 60 * 60 * 1000
long d1 = first.getTime() / oneDay
long d2 = second.getTime() / oneDay
d1 == d2
편집하다
UTC 이외의 특정 시간대의 날짜를 비교해야 할 경우를 대비하여 UTC를 아래에 두었습니다. 그래도 그런 필요가 있다면 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
Math.abs(second.getTime() - first.getTime()) < 1000L*60*60*24
< oneDay.
myJavaUtilDate1.toInstant()
.atZone( ZoneId.of( "America/Montreal" ) )
.toLocalDate()
.isEqual (
myJavaUtilDate2.toInstant()
.atZone( ZoneId.of( "America/Montreal" ) )
.toLocalDate()
)
java.time 클래스로 대체 된 Date& 와 같은 번거롭고 오래된 레거시 날짜-시간 클래스를 피하십시오 Calendar.
A java.util.Date는 타임 라인의 순간을 UTC로 나타냅니다. java.time의 해당 내용은 Instant입니다. 레거시 클래스에 추가 된 새 메서드를 사용하여 변환 할 수 있습니다.
Instant instant1 = myJavaUtilDate1.toInstant();
Instant instant2 = myJavaUtilDate2.toInstant();
날짜별로 비교하고 싶습니다. 시간대는 날짜를 결정하는 데 중요합니다. 주어진 순간마다 날짜는 지구마다 다릅니다. 예를 들어 파리 에서 자정이 지나고 몇 분 후에 프랑스 는 새로운 날이며 몬트리올 퀘벡 에서는 여전히 "어제"입니다 .
지정 적절한 시간대 이름 의 형식 continent/region예컨대, America/Montreal, Africa/Casablanca, 또는 Pacific/Auckland. 표준 시간대 가 아니EST 거나 표준화되지 않았으며 고유하지 않은 3-4 문자 약어를 사용하지 마십시오 .IST
ZoneId z = ZoneId.of( "America/Montreal" );
을 적용 ZoneId받는 Instant를 얻을 ZonedDateTime.
ZonedDateTime zdt1 = instant1.atZone( z );
ZonedDateTime zdt2 = instant2.atZone( z );
이 LocalDate클래스는 시간이없고 시간대가없는 날짜 전용 값을 나타냅니다. 우리는을 추출 할 수 있습니다 LocalDateA로부터 ZonedDateTime효율적으로 시간의 일 부분을 제거한다.
LocalDate localDate1 = zdt1.toLocalDate();
LocalDate localDate2 = zdt2.toLocalDate();
지금과 같은 방법을 사용하여, 비교 isEqual, isBefore및 isAfter.
Boolean sameDate = localDate1.isEqual( localDate2 );
instant1 : 2017-03-25T04 : 13 : 10.971Z | instant2 : 2017-03-24T22 : 13 : 10.972Z
zdt1 : 2017-03-25T00 : 13 : 10.971-04 : 00 [미국 / 몬트리올] | zdt2 : 2017-03-24T18 : 13 : 10.972-04 : 00 [미국 / 몬트리올]
localDate1 : 2017-03-25 | localDate2 : 2017-03-24
sameDate : 거짓
java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 - 시간의 수업을 java.util.Date, Calendar, SimpleDateFormat.
Joda 타임 프로젝트는 지금에 유지 관리 모드 의로 마이그레이션을 조언 java.time의 클래스.
자세한 내용은 Oracle Tutorial을 참조하십시오 . 많은 예제와 설명을 보려면 스택 오버플로를 검색하십시오. 사양은 JSR 310 입니다.
java.time 클래스는 어디서 구할 수 있습니까?
ThreeTen - 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 입증 된 근거입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval, YearWeek, YearQuarter, 그리고 더 .
"쉬운"또는 "간단한"이라고 할 수있는 두 날짜를 비교할 수있는 방법이 없습니다.
두 가지 시간 인스턴스를 감소 된 정밀도 (예 : 날짜 비교)와 비교할 때는 항상 시간대가 비교에 미치는 영향을 고려해야합니다.
경우 date1이 시간대에 발생한 이벤트를 지정하고 date2EST에서 발생한 이벤트를 지정하는 것입니다, 예를 들어, 당신은 제대로 비교의 의미를 이해하기 위해주의해야합니다.
두 일정이 각각의 시간대로 동일한 달력 날짜에 발생했는지 확인하려는 목적입니까? 또는 특정 시간대 (예 : UTC 또는 로컬 TZ)에서 두 날짜가 동일한 달력 날짜에 속하는지 알아야합니다.
실제로 비교하려는 것이 무엇인지 파악한 후에는 적절한 시간대에서 연도-월-일 트리플을 얻는 것과 비교하면됩니다.
Joda 시간은 실제 비교 작업을 훨씬 더 깔끔하게 보이게 할 수 있지만 비교의 의미는 여전히 당신이 알아 내야 할 무언가입니다.
Java 8을 사용하는 경우 java.time.*클래스를 사용하여 날짜를 비교해야합니다. 다양한 java.util.*클래스 보다 선호됩니다.
예를 들어; https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html
LocalDate date1 = LocalDate.of(2016, 2, 14);
LocalDate date2 = LocalDate.of(2015, 5, 23);
date1.isAfter(date2);
시간없이 두 날짜 만 비교하려면 다음 코드가 도움이 될 수 있습니다.
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
}
이 블로그의 솔루션은 다음과 같습니다. 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.");
즉, 밀리 초 단위의 시간 차이가 하루의 길이보다 작은 지 확인할 수 있습니다.
새로운 생각인지는 모르겠지만, 내가 한 것처럼 보여줍니다
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);
YEAR 속성과 함께 DAY_OF_YEAR을 확인하면됩니다.
boolean isSameDay =
firstCal.get(Calendar.YEAR) == secondCal.get(Calendar.YEAR) &&
firstCal.get(Calendar.DAY_OF_YEAR) == secondCal.get(Calendar.DAY_OF_YEAR)
편집하다:
이제 우리는 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
}
}
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();
}
시간을 고려하지 않고 날짜를 비교하는 데 도움이됩니다.
SimpleDateFormat의 getDateInstance를 사용하면 시간없이 두 개의 날짜 객체 만 비교할 수 있습니다. 아래 코드를 실행하십시오.
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));
}
http://mvnrepository.com/artifact/commons-lang/commons-lang 사용
Date date1 = new Date();
Date date2 = new Date();
if (DateUtils.truncatedCompareTo(date1, date2, Calendar.DAY_OF_MONTH) == 0)
// TRUE
else
// FALSE
DateUtils.isSameDay(date1, date2).
여기의 답변과 멘토 안내를 기반으로 한 또 다른 간단한 비교 방법
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());
}
편집 : @Jonathan Drapeau에 따르면 위의 코드는 일부 경우에 실패합니다 (이 경우 를보고 싶습니다). 그는 내가 이해할 때 다음을 제안했습니다.
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());
}
Date 클래스는 더 이상 사용되지 않으므로 국제화가 불가능합니다. Calendar 클래스가 대신 사용됩니다!
getXxx메소드를 사용하는 것보다 시간대를 명시 적으로 만드는 것이 더 좋습니다 Date.
먼저이 작업은 시간대에 따라 다릅니다. 따라서 UTC, 컴퓨터 시간대, 좋아하는 시간대 또는 장소 중에서 원하는 것을 선택하십시오. 아직 그것이 중요하지 않다고 확신한다면이 답의 맨 아래에있는 나의 예를보십시오.
귀하의 질문에 대해 명확하지 않기 때문에 특정 시점을 구현하고 구현하는 인스턴스 필드가있는 클래스가 있고 Comparable객체의 자연 순서가 날짜순이지만 시간이 아니라고 가정합니다. 그 분야의. 예를 들면 다음과 같습니다.
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.time클래스나는에서 인스턴스 필드의 유형을 변경의 자유를 찍은 Date로를 Instant, 자바 (8)에서 해당 클래스는 난의 치료에 복귀 할 것을 약속 Date아래. 시간대 상수도 추가했습니다. 당신은 그것을 설정할 수 있습니다 ZoneOffset.UTC하거나 ZoneId.of("Europe/Stockholm")또는 당신은 무엇을 (A로 설정 적절한 찾을 수 ZoneOffset있기 때문에 작품 ZoneOffset서브 클래스이다 ZoneId).
Java 8 클래스를 사용하여 솔루션을 표시하기로 선택했습니다. 가장 간단한 방법을 요청 하셨나요? :-) compareTo요청한 방법 은 다음과 같습니다 .
public int compareTo(ArnesClass o) {
LocalDate dateWithoutTime = when.atZone(arnesTimeZone).toLocalDate();
LocalDate otherDateWithoutTime = o.when.atZone(arnesTimeZone).toLocalDate();
return dateWithoutTime.compareTo(otherDateWithoutTime);
}
의 시간 부분이 필요하지 않은 경우 when물론을 선언 when하고 LocalDate모든 전환을 건너 뛰는 것이 더 쉽습니다 . 그런 다음 더 이상 시간대에 대해 걱정할 필요가 없습니다.
이제 어떤 이유로 when필드를 선언 할 수 없거나 Instant구식으로 유지하려고 한다고 가정하십시오 Date. 여전히 Java 8을 사용할 수 있다면로 변환 Instant한 다음 이전과 같이하십시오.
LocalDate dateWithoutTime = when.toInstant().atZone(arnesTimeZone).toLocalDate();
마찬가지로 o.when.
java 8을 사용할 수없는 경우 두 가지 옵션이 있습니다.
Calendar또는 이전 클래스 중 하나를 사용하여 해결하십시오 SimpleDateFormat.Adamski의 답변 은 클래스를 Date사용하여 시간 부분을 제거하는 방법을 보여줍니다 Calendar. 원하는 시간대에 대한 인스턴스 getInstance(TimeZone)를 얻는 데 사용 하는 것이 좋습니다 Calendar. 대안으로 Jorn 's answer의 후반부에서 아이디어를 사용할 수 있습니다 .
를 사용하는 SimpleDateFormat것은 실제로 객체를 포함하기 Calendar때문에 간접적으로 사용하는 방법입니다 . 그러나 직접 사용 하는 것보다 번거로울 수 있습니다.SimpleDateFormatCalendarCalendar
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));
}
이것은 Rob의 답변 에서 영감을 얻었습니다 .
특정 시간대를 선택해야하는 이유는 무엇입니까? UTC에서 3 월 24 일 0:00 (자정)과 12:00 (정오)의 두 번 비교하려고한다고 가정합니다. CET (유럽 / 파리)에서 그렇게하면 3 월 24 일 오전 1시와 오후 1시 즉 같은 날짜입니다. 뉴욕 (동부 일광 절약 시간)은 3 월 23 일 20시, 3 월 24 일 8시입니다. 즉, 같은 날짜가 아닙니다. 따라서 시간대를 선택하면 달라집니다. 컴퓨터의 기본값에 의존하는 경우 누군가가이 세계화 된 다른 장소의 컴퓨터에서 코드를 실행하려고 할 때 놀라게 될 수 있습니다.
: ThreeTen 백 포트, 자바 6, 7에 Java 8 날짜와 시간 클래스의 백 포트에 연결 http://www.threeten.org/threetenbp/ .
내 제안 :
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());
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
이것이이 문제를 해결하는 가장 간단한 방법입니다.
타임 스탬프로 비교 하여이 문제를 해결했습니다.
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
}
안드로이드에서는 거대한 공간을 사용하기 때문에 Joda Time을 사용하지 마십시오. 크기가 중요합니다. ;)
Java 8 및 Instant를 사용하는 또 다른 솔루션은 truncatedTo 메소드를 사용하는 것입니다.
이 Instant의 복사본을 지정된 단위로 잘립니다.
예:
@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)));
}
// 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)
}
이것이 나를 위해 일한 것입니다.
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 }