解析时间段在Java

Parse period of time in Java

我希望能够解析时间段(天、小时、分钟)+ 可选字符串,因此输入如下所示:<time>(white_spaces)<optional_string>。据我所知,正则表达式是处理这类事情的正确工具,所以我想出了这样的表达方式:

Pattern.compile("((?<days>\d+)d)?((?<hours>\d+)h)?((?<minutes>\d+)m)?\s+?(?<reason>.+)?");

基本上它按预期工作,但是在此表达式中,所有时间组(天、小时、分钟)都是可选的,我希望输入至少包含分钟组。但是,如果指定了小时或天,则不需要分钟。此外,时间组的所有组合(d+h、h+m、d+m、d+h+m)都是可能的。那么我该如何纠正我的表情呢?或者也许还有其他方法来解析时间段?

编辑: 输入示例:

12h64m - 正确

12d43m dsd - 正确

</code> - 空字符串 - 不正确</p> <p><code>12m - 正确

12d32h43m - 正确

sdsds - 不正确 - 不 "time group specified"

((?<minutes>\d+)m)?表示,分钟组是可选的。但是您希望它是强制性的,所以删除尾随的问号。

tl;博士

Duration.parse( 
    "P"
    .concat( "12d32h43m".replace( "d" , "DT" ) )
    .toUpperCase()
).toHoursPart()

8

你说:

As i know regex is the right tool for such things

没有。 不需要正则表达式。

ISO 8601

您输入的字符串格式接近 ISO 8601 标准正式定义的格式:PnYnMnDTnHnMnS

P 标志着开始。 T 将任何 years-months-days 与任何 hours-minutes-seconds 分开。

转换您的输入以符合标准。

String input =  "P".concat( "12d32h43m".replace( "d" , "DT" ) ).toUpperCase() ;

P12DT32H43M

java.time

Java 有一个 class,Duration(和 Period)。不需要正则表达式。

每个部分都可以查询。调用 Java 9. For Java 8, see this Question and this Question.

中添加的 to…Part 方法
long daysPart = d.toDaysPart() ;
int hoursPart = d.toHoursPart() ;

整个示例:

String input = "P".concat( "12d32h43m".replace( "d" , "DT" ) ).toUpperCase();
Duration d = Duration.parse( input );
long daysPart = d.toDaysPart();
int hoursPart = d.toHoursPart();
long hoursTotal = d.toHours(); // Total elapsed hours of entire duration.

转储到控制台。注意数学。您输入的 32 小时被重新计算为 8,天数从 12 变为 13(额外的 24 小时块 = 一天)。

System.out.println( "input: " + input );
System.out.println( "d.toString()" + d );
System.out.println( "daysPart: " + daysPart );  // 13, not the 12 days seen in the input string. 24 hours were taken from the excessive `32h` of the input string, leaving 8 in the hours part.
System.out.println( "hoursPart: " + hoursPart );
System.out.println( "hoursTotal: " + hoursTotal );  // ( ( 13 * 24 ) + 8 ) = ( 312 + 8 ) = 320 

input: P12DT32H43M

d.toString()PT320H43M

daysPart: 13

hoursPart: 8

hoursTotal: 320

DurationPeriod

对 hours-minutes-seconds 值使用 Duration。使用 Period 获得 years-months-days 值。

  • Duration 中,“天”被理解为与日期和日历无关的 24 小时通用块。
  • 如果你想要日期,你应该使用 Period class。
  • 如果你想要两者,请再考虑一下。混合这两个概念通常没有意义,尽管乍一看这似乎 counter-intuitive。但如果你坚持,请参阅 PeriodDuration class available in the ThreeTen-Extra 项目。

关于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 classes.

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

使用 JDBC driver compliant with JDBC 4.2 或更高版本,您可以直接与数据库交换 java.time 对象。不需要字符串,也不需要 java.sql.* classes.

从哪里获得java.time classes?

  • Java SE 8, Java SE 9,及以后
    • Built-in。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and Java SE 7
    • java.time 的大部分功能是 back-ported 到 Java ThreeTen-Backport 中的 6 和 7。
  • Android
    • Android java.time classes.
    • 捆绑实施的更高版本
    • 对于较早的 Android,ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.