在 Java 中解析时间段

pet*_*iza 1 java regex date iso8601

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

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

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

编辑:输入示例:

12h64m - 正确的

12d43m dsd - 正确的

- 空字符串 - 不正确

12m - 正确的

12d32h43m - 正确的

sdsds - 不正确 - 没有“指定时间组”

Bas*_*que 6

tl;博士

Duration.parse( 
    "P"
    .concat( "12d32h43m".replace( "d" , "DT" ) )
    .toUpperCase()
).toHoursPart()
Run Code Online (Sandbox Code Playgroud)

8

你说:

据我所知,正则表达式是处理此类事情的正确工具

不。不需要正则表达式。

ISO 8601

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

P标志的开始。该T分离任何小时-分-秒的任何年,月,日。

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

String input =  "P".concat( "12d32h43m".replace( "d" , "DT" ) ).toUpperCase() ;
Run Code Online (Sandbox Code Playgroud)

P12DT32H43M

时间

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

您可以询问每个部分。to…PartJava 9 中添加的调用方法。对于 Java 8,请参阅此问题此问题

long daysPart = d.toDaysPart() ;
int hoursPart = d.toHoursPart() ;
Run Code Online (Sandbox Code Playgroud)

整个例子:

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.
Run Code Online (Sandbox Code Playgroud)

转储到控制台。注意数学。您输入的 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 
Run Code Online (Sandbox Code Playgroud)

输入:P12DT32H43M

d.toString()PT320H43M

天部分:13

小时部分:8

小时总数:320

Duration 相对 Period

Duration了几个小时,分钟,秒值。使用Period多年的月日值。

  • 在 a 中Duration,“天”被理解为与日期和日历无关的 24 小时的通用块。
  • 如果你想要日期,你应该使用这个Period类。
  • 如果两者都想要,请再想一想。混合这两个概念通常没有意义,尽管乍一看这似乎违反直觉。但如果您坚持,请查看ThreeTen-Extra项目中PeriodDuration可用的类。

关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

使用符合JDBC 4.2或更高版本的JDBC 驱动程序,您可以直接与您的数据库交换java.time对象。不需要字符串或 java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多