[英]ZonedDateTime to Date before Java 8 in early Android
我正在嘗試替換ZonedDateTime.toInstant
方法,因為它僅在適用於 Android 的 API 26 之后可用。
但我的應用程序應該支持 API 19。
我想將 ZonedDateTime 轉換為日期,以便我可以執行以下操作:
final Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
final long millis = calendar.getTimeInMillis();
我想要實現的是以下內容:
我想計算當前日期和另一個日期之間的差異,以秒、分鍾、小時為單位,......最高可能的單位獲勝,所以我會得到例如5 days ago
的結果。
對於 26歲之前的 Android,使用ThreeTen-ABP庫。
舊的日期時間類,例如Calendar
和Date
是可怕的,真的,可怕的可悲的類。 它們充滿了糟糕的設計決策和黑客,由不了解日期時間處理的人構建。 避開它們。 隨着 JSR 310 的采用,它們完全被java.time類所取代——實際上,有很多原因。
避免這些遺留類。 僅使用java.time類。
對於 Java 6 和 Java 7,大部分java.time功能都在ThreeTen-Backport項目中向后移植。
在ThreeTen-ABP項目中,該后向移植進一步適用於早期的 Android (<26)。
我敦促您將此庫添加到您的項目中,這樣您就可以避免使用悲劇性的遺留類。
如果您需要與尚未更新為java.time 的舊代碼進行交互,請在舊代碼和現代代碼之間來回轉換。
在 Java 8 及更高版本中,通過調用在舊類中找到的新的to…
和from…
方法進行轉換。
在后向端口中,使用org.threeten.bp.DateTimeUtils
類中的to…
轉換方法to…
轉換。
您的問題涉及計算經過時間。
要計算年、月和日,請使用Period
。
要計算天數(與日歷無關的 24 小時時間塊)、小時、分鍾、秒和小數秒,請使用Duration
。
搜索堆棧溢出以獲取更多信息。 這些類已經介紹了很多次。
java.time框架內置於 Java 8 及更高版本中。 這些類取代麻煩的老傳統日期時間類,如java.util.Date
, Calendar
,和SimpleDateFormat
。
要了解更多信息,請參閱Oracle 教程。 並在 Stack Overflow 上搜索許多示例和解釋。 規范是JSR 310 。
現在處於維護模式的Joda-Time項目建議遷移到java.time類。
您可以直接與您的數據庫交換java.time對象。 使用符合JDBC 4.2或更高版本的JDBC 驅動程序。 不需要字符串,不需要java.sql.*
類。
從哪里獲得 java.time 類?
您可以通過以下 gradle 配置簡單地啟用“支持更新的 Java 語言 API”:
<!-- Copyright 2019 Google LLC.
SPDX-License-Identifier: Apache-2.0 -->
android {
defaultConfig {
//Only 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 {
// Dependency with the implementation code for the APIs
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.5'
}
來源: https : //medium.com/androiddevelopers/support-for-newer-java-language-apis-bca79fc8ef65
Basil Bourque 已經有一個很好的答案。 在您發表評論后,我想我可以更具體一點:
public static String diff(String thenStr) {
Instant now = Instant.now();
Instant then = Instant.parse(thenStr);
ChronoUnit[] units = ChronoUnit.values();
// try longest units first, they are in the far end of the array
for (int i = units.length - 1; i >= 0; i--) {
if (then.isSupported(units[i])) {
long diffInCurrentUnit = units[i].between(then, now);
if (diffInCurrentUnit != 0) {
return "" + diffInCurrentUnit + ' ' + units[i].toString().toLowerCase();
}
}
}
return "0";
}
讓我們試試看:
System.out.println(diff("2019-02-23T16:50:21Z"));
System.out.println(diff("2019-02-23T20:15:21Z"));
剛才運行時的輸出:
3 hours 36 seconds
我使用的進口:
import org.threeten.bp.Instant;
import org.threeten.bp.temporal.ChronoUnit;
import org.threeten.bp.temporal.UnsupportedTemporalTypeException;
Instant
不支持比天(24 小時)更粗的單位。 如果您需要能夠返回數周、數月或數年,只需使用OffsetDateTime
而不是Instant
。
是的,java.time 在較舊和較新的 Android 設備上都能很好地工作。 它只需要至少Java 6 。
java.time
導入。org.threeten.bp
導入日期和時間類。編輯: @Basil Bourque 在評論中問道:
我想知道這是否可以壓縮成一條小溪,也許是一條單線?
它可以,但我認為在這種情況下這不會是一個優勢:
return IntStream.range(0, units.length)
.map(i -> units.length - i - 1)
.mapToObj(i -> units[i])
.filter(then::isSupported)
.filter(unit -> unit.between(then, now) != 0)
.map(unit -> "" + unit.between(then, now) + ' ' + unit.toString().toLowerCase())
.findFirst()
.orElse("0");
我發現向后獲取數組元素的代碼.map(i -> units.length - i - 1)
有點難以閱讀。 我們需要計算兩次差值,首先是過濾,然后是組合字符串結果。 但它有效,如果您願意,可以使用它。
使用內部流管道可以避免雙重計算,但同樣難以閱讀:
.flatMap(unit -> LongStream.of(unit.between(then, now))
.filter(diff -> diff != 0)
.mapToObj(diff -> "" + diff + ' ' + unit.toString().toLowerCase()))
java.time
。java.time
到 Java 6 和 7 的 backport(ThreeTen for JSR-310)。解決方案(ThreeTen-Backport 庫):
它工作得很好,我已經在 KitKat 模擬器上試過了。
private static final ChronoUnit[] chronoUnits = {ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS, ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS};
private static final Map<ChronoUnit, Integer> chronoUnitPluralIdMap = new HashMap<ChronoUnit, Integer>() {{
put(ChronoUnit.YEARS, R.plurals.chrono_unit_years_ago);
put(ChronoUnit.MONTHS, R.plurals.chrono_unit_months_ago);
put(ChronoUnit.DAYS, R.plurals.chrono_unit_days_ago);
put(ChronoUnit.HOURS, R.plurals.chrono_unit_hours_ago);
put(ChronoUnit.MINUTES, R.plurals.chrono_unit_minutes_ago);
put(ChronoUnit.SECONDS, R.plurals.chrono_unit_seconds_ago);
}};
public static String getTimeStringUntilNowFromUTC(Context context, String utcDate) {
Instant now = Instant.now(Clock.systemUTC());
Instant then = Instant.parse(utcDate);
for (ChronoUnit chronoUnit : chronoUnits) {
if (then.isSupported(chronoUnit)) {
long units = chronoUnit.between(then, now);
if (units > 0) {
//noinspection ConstantConditions
return context.getResources().getQuantityString(chronoUnitPluralIdMap.get(chronoUnit), (int)units, (int)units);
}
}
}
return "-";
}
public static String getTimeBetweenTwoDates(Context context, String date1, String date2) {
Instant date1Instant = Instant.parse(date1);
Instant date2Instant = Instant.parse(date2);
final long seconds = ChronoUnit.SECONDS.between(date1Instant, date2Instant);
return getMinutesSecondsString(context, seconds);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.