Android 使用LocalDate、LocalTime、LocalDateTime等Java8的日期時間
以往在Android處理日期時間Date(java.util.Date)
及Calendar(java.util.Calendar)
有一些不太方便的地方。到了Java 8 有了新的日期類別來處理:
LocalDate 表示一個日期
LocalTime 表示不含日期的時間
LocalDateTime 表示日期與時間
ZonedDateTime 包含時區的時間
Duration、Period 時間長度
在Java8的日期(java.time)
雖然好用,但以前要使用LocalDate
這些就會有minSdkVersion 26 以上才能使用的限制(如下圖),所以也很難真的在Android上使用。

但在gradle:4.0.0 以上有了Java 8+ API desugaring support,也就不受需要API 26以上的限制了。
build.gradle(Project)
首先當然你的gradle版本要在4.0.0以上
dependencies {
classpath "com.android.tools.build:gradle:4.0.0"
}
build.gralde(Module)
android {
defaultConfig {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled true
} compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
}
改好了Gradle之後Sync,就可以使用Java 8 的日期了。
LocalDate、LocalTime、LocalDateTime
以Local 開頭的這3個都是沒有包含時區的日期與時間。例如要表示生日是2000–01–01,不管在什麼時區,你都會說你的生日都是2000–01–01。
LocalDate
LocalDate 僅有日期資訊,沒有時間
//取得現在日期
val date = LocalDate.now()//特定日期,如2021-1-1
val date = LocalDate.of(2021, 1, 1)
LocalTime
LocalDate 僅有時間資訊,沒有日期
//13:40:50
val time = LocalTime.of(13, 40, 50)
LocalDateTime
同時有日期與時間
//2021-1-1 13:40:50.30
val datetime = LocalDateTime.of(2021, 1, 1, 13, 40, 50, 30)
建立日期時間的方式,除了上方用的of
,也可以用parse
的方式。
val date = LocalDate.parse("2021-01-01")val time = LocalTime.parse("13:40:50")val dateTime = LocalDateTime.parse("2021-01-01T13:40:50")
如果要用自定的格式來建立日期時間,就可以使用DateTimeFormatter
val dateTime = LocalDateTime.parse(
"2021/01/01 13:40:50",
DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")
)
建立時間後,就可以直接取得這些資訊
//2021/01/01 13:40:50
dateTime.year //2021
dateTime.monthValue //1
dateTime.month //JANUARY
dateTime.dayOfMonth //1
dateTime.dayOfWeek //FRIDAY
dateTime.hour //13
dateTime.minute //40
dateTime.second //50
格式化時間(日期轉字串)
//dateTime: 2021-01-01 13:40:50//20210101
dateTime.format(DateTimeFormatter.BASIC_ISO_DATE)//2021-01-01
dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE)//13:40:50
dateTime.format(DateTimeFormatter.ISO_LOCAL_TIME)//2021/01/01
dateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))
時間的加減
dateTime.plusDays(1) //加一天
dateTime.plusWeeks(1) //加一週
dateTime.plusMonths(1) //加一個月
TemporalAdjusters
用來取得這個月的最後一天、今年的最後一天等這些資訊
//dateTime=2021/01/01 13:40:50//這個月的最後一天 2021-01-31T13:40:50
dateTime.with(TemporalAdjusters.lastDayOfMonth())
dayOfWeekInMonth 每週的第幾天
firstDayOfMonth 當月第一天
firstDayOfNextMonth 下個月的第一天
firstDayOfNextYear 明年的第一天
firstDayOfYear 今年的第一天
firstInMonth 當月的第一個星期幾
lastDayOfMonth 當月最後一天
lastDayOfNextMonth 下個月的最後一天
lastDayOfNextYear 明年的最後一天
lastDayOfYear 今年的最後一天
lastInMonth 當月的最後一個星期幾
比較時間
dateTime.isBefore(LocalDateTime.parse("2021-01-02T13:40:50")) //true
dateTime.isAfter(LocalDateTime.parse("2021-01-02T13:40:50")) //false
Period
用來定義時間長度,你可以用來計算兩個時間的間距。
val startDate = LocalDate.of(2021, 1, 1)val endDate = LocalDate.of(2021, 1, 3)val period = Period.between(startDate, endDate) //P2Dperiod.days //幾天
period.months //幾個月
period.years //幾年//自定義Period
Period.parse("P2D")
Duration
跟Period一樣是用來定義時間長度,但時間單位更小
val startDateTime = LocalDateTime.parse("2021-01-02T13:40:50")val endDateTime = LocalDateTime.parse("2021-01-02T13:40:51.11")val duration = Duration.between(startDateTime, endDateTime) //PT1.11Sduration.seconds //幾秒//自定義Duration
Period.parse("PT1.11S")
ZonedDateTime
ZonedDateTime則是包含了時區的日期時間。你可以加上ZoneId來建立一個含有時區的時間。
val dateTime = ZonedDateTime.of(
LocalDateTime.parse("2021-01-02T13:10:00"),
ZoneId.of("UTC+8"))
ZoneId
用ZoneId來建立一個時區的代碼
val zoneId = ZoneId.of("UTC+8")
取得所有時區,像是Asia/Tokyo、America/Los_Angeles、UCT、GMT
ZoneId.getAvailableZoneIds()
有了ZonedDateTime,就可以把不同時區的時間來比較。例如我要計算台北飛東京的飛行時間。
台北起飛:2021–01–02 13:10 (台北時間)
東京抵達:2021–01–02 16:40 (東京時間)
//台北出發2021-01-02 13:10
val departure = ZonedDateTime.of(
LocalDateTime.parse("2021-01-02T13:10:00"),
ZoneId.of("UTC+8")
)//東京抵達2021-01-02 16:40
val arrival = ZonedDateTime.of(
LocalDateTime.parse("2021-01-02T16:40:00"),
ZoneId.of("Asia/Tokyo")
)//飛行時間2小時30分
val duration = Duration.between(departure, arrival)
println(duration) //PT2H30M
參考:
https://developer.android.com/studio/write/java8-support#library-desugaring