2011-06-19 54 views
31

任何人都知道可以解析时间字符串(如“30min”或“2h 15min”或“2d 15h 30min”)为毫秒(或某种Duration对象)的Java库。乔达时间可以做这样的事吗?解析时间字符串,如“1h 30min”

(的东西,没有一个更好的工作,我有一个丑陋的长期的方法来维持,做这样的分析,并希望摆脱它/更换。)

+0

我已经看到这个“Xd Yh Zm”或“Xd Yh Zmin”被称为“JIRA符号”,但我不知道这个术语是否广泛传播。 – Jonik

回答

29

你可能不得不调整这一点为自己的格式,但尝试一些沿着这些路线:

PeriodFormatter formatter = new PeriodFormatterBuilder() 
    .appendDays().appendSuffix("d ") 
    .appendHours().appendSuffix("h ") 
    .appendMinutes().appendSuffix("min") 
    .toFormatter(); 

Period p = formatter.parsePeriod("2d 5h 30min"); 

请注意,有一个appendSuffix,需要一个variants参数,如果你需要使它更灵活。

更新:约达时间以来增加Period.toStandardDuration(),并从那里你可以使用getStandardSeconds()获得所用时间,以秒为long

如果您使用的是没有这些方法的旧版本,您仍然可以通过假设标准的24小时/ 60分钟/小时等来计算时间戳。(在这种情况下,利用DateTimeConstants类,以避免需要幻数。)

+0

+1:打败我吧。 –

+1

谢谢!只需稍作调整,我就能完成这个任务,而且它比我所面对的150行正则表达式/状态机怪物要好得多。 (顺便说一句,对于'Period' - > millis转换,Joda的'DateTimeConstants'包含有用的常量,例如'MILLIS_PER_DAY'。) – Jonik

-1

没有,乔达默认为仅服用持续时间,即时间隔和对象。对于后者,它接受诸如日期或SOAP ISO格式之类的东西。你可以在这里为持续时间类添加你自己的转换器,并承认这会隐藏你所有难看的代码。

12

我想使日,时,分可选,这似乎是工作要做到这一点。请注意,appendSuffix()调用在字符后没有空格。

使用乔达2.3。

PeriodParser parser = new PeriodFormatterBuilder() 
     .appendDays().appendSuffix("d").appendSeparatorIfFieldsAfter(" ") 
     .appendHours().appendSuffix("h").appendSeparatorIfFieldsAfter(" ") 
     .appendMinutes().appendSuffix("min") 
     .toParser(); 

上述代码通过了这些测试。

@Test 
public void testConvert() { 
    DurationConverter c = new DurationConverter(); 

    Duration d; 
    Duration expected; 

    d = c.convert("1d"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardDays(1),1); 
    assertEquals(d, expected); 

    d = c.convert("1d 1h 1min"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardDays(1),1) 
      .withDurationAdded(Duration.standardHours(1),1) 
      .withDurationAdded(Duration.standardMinutes(1),1); 
    assertEquals(d, expected); 


    d = c.convert("1h 1min"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardHours(1),1) 
      .withDurationAdded(Duration.standardMinutes(1),1); 
    assertEquals(d, expected); 

    d = c.convert("1h"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardHours(1),1); 
    assertEquals(d, expected); 

    d = c.convert("1min"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardMinutes(1),1); 
    assertEquals(d, expected); 

} 
+0

'PeriodParser'主要是指内部接口。 'PeriodFormatter'是面向用户的API。 –

+0

其中是'DurationConverter'定义? –

+0

尽管我原本认为这很有用,但它没有正确处理无效输入。或者至少它可能,但这将是我们看不到的DurationConverter的实现。 –

23

持续时间解析现在包含在Java 8中。使用标准ISO 8601格式与Duration.parse

Duration d = Duration.parse("PT1H30M") 

您可以convert this duration以毫秒为单位的总长度。请注意,Duration的分辨率为纳秒,因此您可能会将数据从nanoseconds丢失至milliseconds

long milliseconds = d.toMillis(); 

格式与您描述的格式稍有不同,但可以很容易地从一个翻译到另一个。

+2

这也增加了持续时间支持ISO8601标准的好处。 ISO字符串必须匹配形式P [yY] [mM] [dD] [T [hH] [mM] [s [.s] S]]。它使用Java 8中的标准Java类,并且还有用于Java 6和7的backports,请参阅:http://www.threeten.org/threetenbp/ – theINtoy

+0

我不确定它是否支持整个ISO8601标准,特别是具有星期:例如P2W不可解析,但我相信每个标准都是有效的。 “持续时间”的文档说:“从文本字符串获得持续时间,如PnDTnHnMn.nS。” –