Java 中的解析持续时间类似于 "time=+1d1h55m15s584ms"

Parsing time duration in Java like "time=+1d1h55m15s584ms"

我目前 运行 在我的 android 应用程序中执行几个 shell 命令,并在我的应用程序上解析 shell 输出。

目前我的 shell 输出也返回前一个输出之间的持续时间。持续时间是这样的——time=+1d1h55m15s584ms

现在我被困在这里了。如果无论如何要将此持续时间计算为毫秒或将其转换为准确的时间戳?

你能控制字符串的生成吗?如果是这样,请改用标准格式。

ISO 8601

ISO 8601 standard defines many textual formats for representing date-time values. This includes a format for durations,例如您的 PnYnMnDTnHnMnS,其中 P 标记开始,T 将 years-month-days 与 [=93= 分开].

例如,一个半小时是PT1H30M

使用java.time

java.time 类 内置于 Java 8 及更高版本,以及 back-ported 至 Java 6 & 7 & Android,使用默认情况下,ISO 8601 格式用于解析和生成字符串。

java.time 类 将 years-months-days 表示为 Period object, and hours-minutes-seconds as a Duration 对象。

String input = "P1DT1H55M15.584S";
Duration d = Duration.parse ( input );

d.toString(): PT25H55M15.584S

d.toMillis(): 93315584

d.toNanos(): 93315584000000

字符串操作

如果您无法控制输入字符串的格式,我会考虑将这些输入操作为标准格式。添加 P,插入 T,并将 ms 部分更改为小数。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

java.time类在哪里获取?

  • Java SE 8 and SE 9 及更高版本
    • Built-in。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and SE 7
    • java.time 的大部分功能是 back-ported 到 Java ThreeTen-Backport 中的 6 和 7。
  • Android
    • ThreeTenABP项目专门为Android改编ThreeTen-Backport(上面提到的)。

大多数建议字符串输入预处理的答案的主要问题是输入字符串通常无法更改。

所以通常调整解析例程而不是输入更灵活。

要么你必须编写自己的解析例程,要么你可以使用我的库 Time4A which offers direct support for parsing durations on pattern base(而不是@Basil Bourque 的回答中建议的 ThreetenABP),然后使用此代码(版本 v3.28 或后来):

String input = "+1d1h55m15s584ms";
String pattern = "+[#D'd'][#h'h'][#m'm'][#s's'][fff'ms']";

long totalMillis =
    Duration.formatter(pattern)
    .parse(input)
    .toClockPeriodWithDaysAs24Hours()
    .with(ClockUnit.MILLIS.only())
    .getPartialAmount(ClockUnit.MILLIS);
System.out.println(totalMillis); // 93315584

详细说明

关于模式语法:

  • 方括号表示可选组件,在输入中不是强制性的。
  • 所有由撇号转义的部分都作为文字处理。
  • 模式符号“+”是正号或负号的占位符。
  • 符号 D、h、m、s、f 代表:日、时、分、秒和小数秒。
  • 如果此类符号前面有“#”,则此特殊模式字符会标记一个额外的前导数字,以这种方式指示允许的最大数字数。

解析输入后,解析后的持续时间需要分两步归一化:首先将整个持续时间转换为 clock-unit-based 持续时间(将天数处理为 24 小时),然后仅归一化为毫秒。经过第二步,我们知道,以毫秒为单位的部分量也是总量(希望的结果)。