java calendar比較 - 計算兩個Java日期實例之間的差異




15 Answers

不幸的是,JDK Date API非常糟糕。 我建議使用喬達時間庫

喬達時間有一個時間的概念Interval

Interval interval = new Interval(oldTime, new Instant());

編輯:順便說一下,喬達有兩個概念:代表兩個時間點之間的時間間隔(表示時間為上午8點到上午10點)的時間間隔,以及表示沒有實際時間邊界的時間長度的時間間隔(例如代表兩個小時!)

如果你只關心時間比較,大多數Date實現(包括JDK)實現Comparable接口,它允許你使用Comparable.compareTo()

java判斷日期 android時間比較

我在Scala中使用Java的java.util.Date類,想要比較Date對象和當前時間。 我知道我可以使用getTime()來計算增量:

(new java.util.Date()).getTime() - oldDate.getTime()

但是,這只會讓我有很long代表毫秒。 有沒有更簡單,更好的方法來獲得時間增量?




int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
                 / (1000 * 60 * 60 * 24) )

請注意,這適用於UTC日期,所以如果您查看當地日期,則差異可能是休息一天。 由於夏令時間的原因,使用本地日期正確工作需要採用完全不同的方法。




使用Java 8+內置的java.time框架:

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println("ISO-8601: " + duration);
System.out.println("Minutes: " + duration.toMinutes());

輸出:

ISO-8601:PT24H10M

分鐘:1450

有關更多信息,請參閱Oracle教程ISO 8601標準。




TL;博士

將廢棄的java.util.Date對象轉換為它們的替換java.time.Instant 。 然後將持續時間計算為Duration

Duration d = 
    Duration.between(                   // Calculate the span of time between two moments as a number of hours, minutes, and seconds.
        myJavaUtilDate.toInstant() ,    // Convert legacy class to modern class by calling new method added to the old class.
        Instant.now()                   // Capture the current moment in UTC. About two and a half hours later in this example.
    )
;

d.toString():PT2H34M56S

d.toMinutes():154

d.toMinutesPart():34

ISO 8601格式: PnYnMnDTnHnMnS

明智的標準ISO 8601將時間跨度的簡明文本表示定義為年,月,日,小時等數。標準調用這樣的持續時間 。 格式為PnYnMnDTnHnMnS ,其中P表示“期間”, T將日期部分與時間部分分開,其間的數字後跟一個字母。

例子:

  • P3Y6M4DT12H30M5S
    三年,六個月,四天,十二小時,三十分鐘和五秒鐘
  • PT4H30M
    四個半小時

java.time

內置於Java 8及更高版本中的java.time框架取代了麻煩的舊java.util.Date / java.util.Calendar類。 新課程的靈感來自非常成功的Joda-Time框架,其目標是作為其後繼者,概念相似但重新設計。 由JSR 310定義。 由ThreeTen-Extra項目擴展。 參見Tutorial

時刻

Instant類表示UTC時間軸上的某個時刻,分辨率為nanoseconds (小數點後最多九位數字)。

Instant instant = Instant.now() ;  // Capture current moment in UTC.

最好避免諸如Date / Calendar等遺留類。 但是,如果您必須與尚未更新為java.time的舊代碼進行互操作,請來迴轉換。 調用添加到舊類的新轉換方法。 要從java.util.Date移動到Instant ,請調用Date::toInstant

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.

時間跨度

java.time類將這種將時間跨度表示為幾年,幾個月,幾天,幾小時,幾分鐘,幾秒的想法分成兩部分:

  • Period為幾年,幾個月,幾天
  • Duration幾天,幾小時,幾分鐘,幾秒鐘

這是一個例子。

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );

轉儲到控制台。

PeriodDuration使用ISO 8601標準來生成其值的字符串表示。

System.out.println ( "now: " + now + " to future: " + now + " = " + duration );

現在:2015-11-26T00:46:48.016-05:00 [America / Montreal] to future:2015-11-26T00:46:48.016-05:00 [America / Montreal] = PT1H3M

Java 9增加了Duration方法來獲取日期部分,小時部分,分鐘部分和秒部分。

您可以獲得整個持續時間的總天數或小時數或分鐘或秒或毫秒或納秒。

long totalHours = duration.toHours();

在Java 9中, Duration類獲得用於返回天,小時,分,秒,毫秒/納秒的各種部分的新方法 。 調用to…Part方法: toDaysPart()toHoursPart()等。

ChronoUnit

如果您只關心更簡單的更大時間間隔,例如“經過的天數”,請使用ChronoUnit枚舉。

long daysElapsed = ChronoUnit.DAYS.between( earlier , later );

另一個例子。

Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );
…
long minutesElapsed = ChronoUnit.MINUTES.between( now , later );

120

關於java.time

java.time框架內置於Java 8及更高版本中。 這些類取代了諸如java.util.DateCalendarSimpleDateFormat等麻煩的舊式legacy日期時間類。

Joda-Time項目現在處於維護模式 ,建議遷移到java.time。

要了解更多信息,請參閱Tutorial 。 並蒐索堆棧溢出了很多例子和解釋。 規範是JSR 310

何處獲取java.time類?

  • Java SE 8SE 9及更高版本
    • 內置。
    • 帶有捆綁實現的標準Java API的一部分。
    • Java 9增加了一些次要功能和修復。
  • Java SE 6SE 7
  • Android
    • ThreeTenABP項目專門針對Android採用了ThreeTen-Backport (上文提到)。
    • 請參閱如何使用...。

ThreeTen-Extra項目將java.time擴展到其他類。 這個項目是未來可能增加java.time的一個試驗場。 您可以在這裡找到一些有用的課程,例如IntervalYearWeekYearQuarter等。

喬達時間

更新: Joda-Time項目現在處於維護模式 ,團隊建議遷移到java.time類。 我將這部分留給了歷史。

喬達時間庫默認使用ISO 8601。 它的Period類解析並生成這些PnYnMnDTnHnMnS字符串。

DateTime now = DateTime.now(); // Caveat: Ignoring the important issue of time zones.
Period period = new Period( now, now.plusHours( 4 ).plusMinutes( 30));
System.out.println( "period: " + period );

呈現:

period: PT4H30M



使用毫秒方法可能會在某些語言環境中導致問題。

例如,讓我們看看2007年3月24日和2007年3月25日兩天之間的差異應該是1天;

但是,使用毫秒級的路線,如果您在英國運行,您將獲得0天的時間!

/** Manual Method - YIELDS INCORRECT RESULTS - DO NOT USE**/  
/* This method is used to find the no of days between the given dates */  
public long calculateDays(Date dateEarly, Date dateLater) {  
   return (dateLater.getTime() - dateEarly.getTime()) / (24 * 60 * 60 * 1000);  
} 

更好的實現方法是使用java.util.Calendar

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  



由於這裡所有的答案都是正確的,但是使用遺留的java或像joda或類似的第三方庫,我將在Java 8及更高版本中使用新的java.time類來放棄另一種方式。 請參閱Oracle教程

使用LocalDateChronoUnit

LocalDate d1 = LocalDate.of(2017, 5, 1);
LocalDate d2 = LocalDate.of(2017, 5, 18);

long days = ChronoUnit.DAYS.between(d1, d2);
System.out.println( days );



如果你不想使用JodaTime或類似的,最好的解決方案可能是這樣的:

final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
long msDiff= date1.getTime() - date2.getTime();
long daysDiff = Math.round(msDiff / ((double)MILLIS_PER_DAY));

每天的ms數並不總是相同(由於夏令時和閏秒),但它非常接近,並且由於夏令時造成的偏差至少會在較長的時間段內抵消。 因此,除法和舍入將給出正確的結果(至少只要使用的本地日曆不包含除DST和閏秒以外的奇怪時間跳轉)。

請注意,這仍假定date1date2設置為一天中的同一時間。 對於一天中的不同時間,您首先必須定義“日期差異”的含義,正如Jon Skeet所指出的那樣。




讓我展示Joda Interval和Days之間的區別:

DateTime start = new DateTime(2012, 2, 6, 10, 44, 51, 0);
DateTime end = new DateTime(2012, 2, 6, 11, 39, 47, 1);
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
System.out.println(period.getYears() + " years, " + period.getMonths() + " months, " + period.getWeeks() + " weeks, " + period.getDays() + " days");
System.out.println(period.getHours() + " hours, " + period.getMinutes() + " minutes, " + period.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *1 weeks, 1 days*
//0 hours, 54 minutes, 56 seconds 

//Period can set PeriodType,such as PeriodType.yearMonthDay(),PeriodType.yearDayTime()...
Period p = new Period(start, end, PeriodType.yearMonthDayTime());
System.out.println(p.getYears() + " years, " + p.getMonths() + " months, " + p.getWeeks() + " weeks, " + p.getDays() + "days");
System.out.println(p.getHours() + " hours, " + p.getMinutes() + " minutes, " + p.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *0 weeks, 8 days*
//0 hours, 54 minutes, 56 seconds 



檢查示例這裡http://www.roseindia.net/java/beginners/DateDifferent.shtml這個例子給你在天,小時,分鐘,秒和毫秒的差異:)。

import java.util.Calendar;
import java.util.Date;

public class DateDifferent {
    public static void main(String[] args) {
        Date date1 = new Date(2009, 01, 10);
        Date date2 = new Date(2009, 07, 01);
        Calendar calendar1 = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();
        calendar1.setTime(date1);
        calendar2.setTime(date2);
        long milliseconds1 = calendar1.getTimeInMillis();
        long milliseconds2 = calendar2.getTimeInMillis();
        long diff = milliseconds2 - milliseconds1;
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000);
        long diffHours = diff / (60 * 60 * 1000);
        long diffDays = diff / (24 * 60 * 60 * 1000);
        System.out.println("\nThe Date Different Example");
        System.out.println("Time in milliseconds: " + diff + " milliseconds.");
        System.out.println("Time in seconds: " + diffSeconds + " seconds.");
        System.out.println("Time in minutes: " + diffMinutes + " minutes.");
        System.out.println("Time in hours: " + diffHours + " hours.");
        System.out.println("Time in days: " + diffDays + " days.");
    }
}



以下代碼可以為您提供所需的輸出:

String startDate = "Jan 01 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
LocalDate date = LocalDate.parse(startDate, formatter);

String currentDate = "Feb 11 2015";
LocalDate date1 = LocalDate.parse(currentDate, formatter);

System.out.println(date1.toEpochDay() - date.toEpochDay());



int daysDiff = (date1.getTime() - date2.getTime()) / MILLIS_PER_DAY;



That's probably the most straightforward way to do it - perhaps it's because I've been coding in Java (with its admittedly clunky date and time libraries) for a while now, but that code looks "simple and nice" to me!

Are you happy with the result being returned in milliseconds, or is part of your question that you would prefer to have it returned in some alternative format?




Note: startDate and endDates are -> java.util.Date

import org.joda.time.Duration;
import org.joda.time.Interval;
Interval interval = new Interval(startDate.getTime(), endDate.getTime);
Duration period = interval.toDuration();
period.getStandardDays() //gives the number of days elapsed between start and end date

Similar to days, you can also get hours, minutes and seconds

period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();



嘗試這個:

int epoch = (int) (new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse("01/01/1970  00:00:00").getTime() / 1000);

you can edit the string in the parse() methods param.




Just use below method with two Date objects. If you want to pass current date, just pass new Date() as a second parameter as it is initialised with current time.

public String getDateDiffString(Date dateOne, Date dateTwo)
{
    long timeOne = dateOne.getTime();
    long timeTwo = dateTwo.getTime();
    long oneDay = 1000 * 60 * 60 * 24;
    long delta = (timeTwo - timeOne) / oneDay;

    if (delta > 0) {
        return "dateTwo is " + delta + " days after dateOne";
    }
    else {
        delta *= -1;
        return "dateTwo is " + delta + " days before dateOne";
     }
}

Also, apart from from number of days, if, you want other parameter difference too, use below snippet,

int year = delta / 365;
int rest = delta % 365;
int month = rest / 30;
rest = rest % 30;
int weeks = rest / 7;
int days = rest % 7;

PS Code is entirely taken from an SO answer.




Related

java date time timedelta java.util.date