问题描述
val leftTimeInMillis = 12728918
val mTimeFormat = SimpleDateFormat("HH:mm:ss",Locale.ROOT)
binding.textTimeLeft.text = mTimeFormat.format(leftTimeInMillis)
通常文本必须指示 03:32:08 但它是 05:32:08
解决方法
java.time.Duration 通过脱糖和 String.format()
使用现代 Java 日期和时间 API java.time 来处理您的时间工作。
我没有 Android 开发环境,但我希望以下内容能够与脱糖一起使用(请参阅下面的链接)。它适用于桌面 Java 版本 9 及更高版本。
int leftTimeInMillis = 12_728_918;
Duration timeLeft = Duration.ofMillis(leftTimeInMillis);
String formattedTimeLeft = String.format("%02d:%02d:%02d",timeLeft.toHours(),timeLeft.toMinutesPart(),timeLeft.toSecondsPart());
System.out.println(formattedTimeLeft);
输出是必需的:
03:32:08
如果出于某种原因,而不是脱糖您正在使用 ThreeTenABP,我相信 toMinutesPart
和 toSecondsPart
方法不包括在内。然后转换需要多一点:
Duration timeLeft = Duration.ofMillis(leftTimeInMillis);
long hours = timeLeft.toHours();
timeLeft = timeLeft.minusHours(hours);
long minutes = timeLeft.toMinutes();
timeLeft = timeLeft.minusMinutes(minutes);
long seconds = timeLeft.getSeconds();
String formattedTimeLeft = String.format("%02d:%02d:%02d",hours,minutes,seconds);
输出和之前一样。
替代方案:Time4A
如果您对用于日期和时间的广泛外部库感到满意,则可以选择 Time4A,Time4J 的 Android 版本。它提供了一种更优雅、更符合您自己尝试过的解决方案。我更喜欢声明一个静态格式化程序:
private static final Duration.Formatter<ClockUnit> M_TIME_FORMAT
= Duration.formatter(ClockUnit.class,"hh:mm:ss");
现在格式如下:
int leftTimeInMillis = 12_728_918;
Duration<ClockUnit> timeLeft = Duration.of(leftTimeInMillis,ClockUnit.MILLIS)
.with(Duration.STD_CLOCK_PERIOD);
String formattedTimeLeft = M_TIME_FORMAT.format(timeLeft);
System.out.println(formattedTimeLeft);
03:32:08
我再次使用 Time4J 在桌面 Java 上开发了我的代码。
您的代码出了什么问题?
你的代码发生了什么?这两个小时从哪里来? SimpleDateFormat
是在 1990 年代设计的,始终用于格式化和解析时间点,而不是时间量。因此,您的数字 12 728 918 表示 UTC 时间 1970 年 1 月 1 日 Java 纪元之后几毫秒的时间点。换句话说,您正在尝试格式化 1970-01-01T03:32:08.918Z 的瞬间。由于您设备的时区设置(猜测是欧洲/雅典)在 1970 年冬天比 UTC 早 2 小时,因此用于格式化的日期和时间是 1970-01-01T05:32:08.918+02:00 [欧洲/雅典]。这就是您得到 05:32:08
的原因。
假设你在 1970 年的元旦晚上没有时间,那么你所做的就是错误的,即使你能让它工作,也会让每个阅读你代码的人感到困惑。另外如果某一天的毫秒数超过24小时,则不会打印整天,可能会造成很大的混乱。请勿将 SimpleDateFormat
用于此目的。并考虑永远不要使用 SimpleDateFormat
,因为该类是出了名的麻烦且过时。
问题:java.time 不需要 Android API 级别 26 吗?
java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少 Java 6。
- 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 开始)中,内置了现代 API。
- 在非 Android Java 6 和 7 中获得 ThreeTen Backport,现代类的向后移植(ThreeTen for JSR 310;请参阅底部的链接)。
- 在较旧的 Android 上,使用脱糖或 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。在后一种情况下,请确保使用子包从
org.threeten.bp
导入日期和时间类。
链接
- Oracle tutorial: Date Time 解释如何使用 java.time。
-
Java Specification Request (JSR) 310,其中首次描述了
java.time
。 -
ThreeTen Backport project,将
java.time
向后移植到 Java 6 和 7(JSR-310 的 ThreeTen)。 - Java 8+ APIs available through desugaring
- ThreeTenABP,ThreeTen Backport 的 Android 版
- Question: How to use ThreeTenABP in Android Project,非常详尽的解释。
- Time4A on GitHub