[英]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.