java - time使用 - joda time教學




Joda-Time中兩個日期之間的天數 (4)

如何找到兩個Joda-Time DateTime實例之間的天數差異? 我的意思是,如果開始時間是星期一,結束時間是星期二,則無論開始日期和結束日期的小時/分鐘/秒是多少,我都希望返回值為1。

Days.daysBetween(start, end).getDays()給我0,如果開始是在晚上,結束在早上。

我也有與其他日期字段相同的問題,所以我希望有一種通用的方式來“忽略”較小意義的字段。

換句話說,2月到4月4日之間的月份也是1,14:45到15:12之間的時間也是1。 然而,14:01和14:55之間的小時差將是0。


TL;博士

java.time.temporal.ChronoUnit.DAYS.between( 
    earlier.truncatedTo( ChronoUnit.DAYS )  , 
    later.truncatedTo( ChronoUnit.DAYS ) 
)

…要么…

java.time.temporal.ChronoUnit.HOURS.between( 
    earlier.truncatedTo( ChronoUnit.HOURS )  , 
    later.truncatedTo( ChronoUnit.HOURS ) 
)

java.time

僅供參考, Joda-Time項目現在處於維護模式 ,團隊建議遷移到java.time類。

Joda-Time DateTime的等價物是ZonedDateTime

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

顯然你想按日期來計算日期,這意味著你想忽略一天的時間。 例如,在午夜前一分鐘開始,在午夜後一分鐘結束,應該導致一天。 對於這種行為,從ZonedDateTime提取一個LocalDateLocalDate類表示沒有時間和不帶時區的僅限日期的值。

LocalDate localDateStart = zdtStart.toLocalDate() ;
LocalDate localDateStop = zdtStop.toLocalDate() ;

使用ChronoUnit枚舉來計算經過的天數或其他單位。

long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;

截短

至於你問一個更一般的方法來做這個計算,你感興趣的時間為小時的時差,而不是完整的小時為六十分鐘的時間跨度,使用truncatedTo方法。

這是你當天14:45到15:12的例子。

ZoneId z = ZoneId.of( "America/Montreal" ); 
ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z );
ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z );

long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) );

1

對於按日期計算的天數,請截斷為ChronoUnit.DAYS 。 這是一個例子,從前五分鐘到五分鐘後的午夜,經過1天。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 23 , 55 , 0 , 0 , z );
ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 18 , 00 , 05 , 0 , 0 , z );

long days = ChronoUnit.DAYS.between( start.truncatedTo( ChronoUnit.DAYS ) , stop.truncatedTo( ChronoUnit.DAYS ) );

1

關於java.time

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

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

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

您可以直接與數據庫交換java.time對象。 使用符合JDBC 4.2或更高版本的JDBC驅動程序 。 不需要字符串,不需要java.sql.*類。

何處獲取java.time類?

  • Java SE 8Java SE 9Java SE 10和更高版本
    • 內置。
    • 帶有捆綁實現的標準Java API的一部分。
    • Java 9增加了一些次要功能和修復。
  • Java SE 6Java SE 7
  • Android
    • 後續版本的java.time類的Android捆綁實現。
    • 對於早期的Android(<26), ThreeTenABP項目採用了ThreeTen-Backport (如上所述)。 請參閱如何使用ThreeTenABP ...。

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

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


Days

使用Days類與withTimeAtStartOfDay方法應該工作:

Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays() 

你可以使用LocalDate

Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays() 

接受的答案構建兩個LocalDate對象,如果您正在閱讀大量數據,則這些對象相當昂貴。 我使用這個:

  public static int getDaysBetween(DateTime earlier, DateTime later)
  {
    return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
  }

通過調用getMillis()您可以使用已經存在的變量。
MILLISECONDS.toDays()則使用簡單的算術計算,不會創建任何對象。







jodatime