2011-06-19 95 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。」 –