如何将SystemClock.elapsedRealTime()
转换为可在文本视图中显示的可读CharSeq?
tl;dr
Duration.ofMillis( // Represent a span of time on scale of hours-minutes-seconds, unattached to the timeline.
SystemClock.elapsedRealTime() // 441_000L as an example.
)
.toString() // Generate a String in standard ISO 8601 format.
PT7M21S
避免一天中的时间格式
以一天中的时间(HH:MM:SS.SSS)的格式显示经过的时间具有误导性和歧义性,因为它很容易被误解为一天的时间。
ISO 8601–持续时间格式
ISO 8601标准定义了各种日期时间值的合理字符串表示。这些值包括经过的时间。
标准格式为PnYnMnDTnHnMnS
,其中开头用P
标记,而T
将年-月-天部分与小时-分-秒部分分隔开。例如:
PT30M
=半小时PT8H30M
=八个半小时P3Y6M4DT12H30M5S
表示"三年六个月四天十二小时三十分五秒">的持续时间
术语"周期"或"持续时间"通常用作同义词。日期时间工作中的术语尚未标准化。请注意标准如何使用术语"持续时间",但格式以P
开头,如"周期"中所示<这就是生活。>
java.time
java.time类提供了两个类来表示与时间线无关的时间跨度:
Period
年月日Duration
小时分秒
这两个类都解析/生成上面讨论的标准ISO 8601持续时间格式。
SystemClock.elapsedRealTime()
的输出是一个long
整数,用于计算经过的毫秒数。所以我们可能想要使用Duration
类。
long millis = SystemClock.elapsedRealTime() ;
Duration d = Duration.ofMillis( millis ) ;
让我们试试441000作为我们的millis。
Duration d = Duration.ofMillis( 441_000L ) ;
生成标准格式的字符串。对于441_000L
,我们得到7分21秒。
String output = d.toString() ; // Generate standard ISO 8601 string.
PT7M21S
您可以解析标准字符串,以获得Duration
对象。
Duration d = Duration.parse( "PT7M21S" ) ;
我建议您的用户阅读标准ISO 8601格式,因为它可读且明确。我强烈建议永远不要显示为一天中的时间格式(00:07:21
),因为我已经看到模糊性会在用户中引起很多困惑。但是,如果您的用户基础不符合标准格式,则可以生成其他字符串。
在这个类的一些后续版本中,可以调用to…Part
方法来检索七和二十一。
int minutesPart = d.toMinutesPart() ; // The whole-minutes portion.
int secondsPart = d.toSecondsPart() ; // The whole-seconds portion.
您还可以返回到总计毫秒数。
long millis = d.toMillis() ; // Not the part, but the entire span of time in terms of milliseconds.
关于java.time
java.time框架构建在Java8及更高版本中。这些类取代了诸如java.util.Date
、Calendar
和&CCD_ 20。
现在处于维护模式的JodaTime项目建议迁移到java.Time类。
要了解更多信息,请参阅Oracle教程。并在Stack Overflow中搜索许多示例和解释。规范是JSR310。
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要java.sql.*
类。
从哪里获得java.time类?
- Java SE 8、Java SE 9和更高版本
- 内置
- 标准Java API的一部分,带有捆绑实现
- Java 9添加了一些小功能和修复程序
- Java SE 6和Java SE 7
- 大部分Java.time功能都是向后移植到Java 6&7英寸ThreeTen背包
- Android
- java.time类的Android捆绑包实现的后续版本
- 对于早期的Android(<26),ThreeTenABP项目适用于ThreeTen Backport(如上所述)。请参阅如何使用ThreeTenABP…
ThreeTen Extra项目通过附加类扩展java.time。这个项目是将来可能添加到java.time的试验场。您可以在这里找到一些有用的类,如Interval
、YearWeek
、YearQuarter
等等。
Joda时间
更新:Joda Time项目现在处于维护模式,团队建议迁移到java.Time类。我将把这一部分原封不动地留给历史。
Joda时间库提供了三个类来表示一段时间,即Interval
、Duration
和Period
。最后一个,Period
,意味着一段时间,描述为天数、小时数等等。它类似于这种特殊的ISO 8601格式。Period
类还解析并生成ISO 8601格式的字符串。Joda Time在安卓系统中工作,作为臭名昭著的麻烦java.util.Date/.Calendar类的替代品,它已经过时,非常受欢迎。
Period
类采用long
整数作为持续时间的毫秒计数。这正是我们所需要的,因为SystemClock.elapsedRealtime()
为我们提供了自机器启动以来的毫秒计数。
long machineUptimeMillis = SystemClock.elapsedRealtime() ;
Period machineUptimePeriod = new Period( machineUptimeMillis );
String output = machineUptimePeriod.toString(); // Ex: P3DT2H15M37.123S
如果我们要跟踪某个运算需要多长时间,我们将在减法中使用一对这样的long
。
long start = SystemClock.elapsedRealtime() ;
// … Perform some operation …
long stop = SystemClock.elapsedRealtime() ;
long elapsedMillis = stop - start ;
Period elapsedPeriod = new Period( elapsedMillis );
小写
为了向人类用户演示,您可能希望去掉P
和/或T
,并使用小写字母以提高可读性。
String output = elapsedPeriod.toString().replace( "P" , "" ).replace( "T", " " ).toLowerCase() ;
例如,3y6m4d 12h30m5s
。
漂亮的印花
您可以漂亮地打印Period
值,例如"5年零2个月"。
使用内置的基于区域设置敏感单词的格式化程序。
PeriodFormatter formatter = PeriodFormat.wordBased( Locale.CANADA_FRENCH ) ;
String output = formatter.print( elapsedPeriod ) ;
或者使用PeriodFormatterBuilder
创建自己的自定义格式。
PeriodFormatter yearsAndMonths = new PeriodFormatterBuilder()
.printZeroAlways()
.appendYears()
.appendSuffix(" year", " years")
.appendSeparator(" and ")
.printZeroRarelyLast()
.appendMonths()
.appendSuffix(" month", " months")
.toFormatter() ;
请参阅以下问题:如何在Java中以hh:mm:ss.SSS格式格式化经过的时间间隔?。使用这种方法:
private static String formatInterval(final long millis) {
final long hr = TimeUnit.MILLISECONDS.toHours(millis);
final long min = TimeUnit.MILLISECONDS.toMinutes(millis - TimeUnit.HOURS.toMillis(hr));
final long sec = TimeUnit.MILLISECONDS.toSeconds(millis - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min));
final long ms = TimeUnit.MILLISECONDS.toMillis(millis - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min) - TimeUnit.SECONDS.toMillis(sec));
return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
}
然后假设您引用了TextView:
long elapsedTime = SystemClock.elapsedRealTime();
textView.setText(elapsedTime);
结果是,您的TextView将以人类可读的格式显示设备运行的总时间。