Java "30min"、 "2h 15min"、 "2d 15h 30min"などの時間文字列をミリ秒(またはある種のDurationオブジェクト)として解析できるライブラリを知っている人は誰でも知っています。時間はこのようなことをしますか?
(私はそのような解析を行う維持するための醜い長い方法があり、それを取り除きたい/より良い仕事をする何かで置き換えたいです。)
あなたはおそらくあなた自身のフォーマットのためにこれを少し微調整する必要があるでしょうが、これらの線に沿って何かを試してください:
_PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendDays().appendSuffix("d ")
.appendHours().appendSuffix("h ")
.appendMinutes().appendSuffix("min")
.toFormatter();
Period p = formatter.parsePeriod("2d 5h 30min");
_
より柔軟にする必要がある場合は、appendSuffix
パラメータを取るvariants
があることに注意してください。
Update:Joda Timeが追加された Period.toStandardDuration()
、そしてそこから getStandardSeconds()
経過時間を秒単位でlong
として取得します。
これらのメソッドのない古いバージョンを使用している場合でも、1日24時間、60分/時間などの標準を想定して、自分でタイムスタンプを計算できます(この場合、DateTimeConstants
クラスを使用して、マジックナンバーの必要性を回避します。
継続時間の解析が Java 8 に含まれるようになりました。標準 ISO 8601 フォーマットを Duration.parse
。
Duration d = Duration.parse("PT1H30M")
この期間を変換する をミリ秒単位の全長に変換できます。 Duration
の分解能はナノ秒であるため、 nanoseconds から milliseconds へのデータ損失が発生する可能性があることに注意してください。
long milliseconds = d.toMillis();
形式は、あなたが説明したものとは少し異なりますが、簡単に変換できます。
日、時間、分をオプションにしたかったのですが、これでうまくいくようです。 appendSuffix()呼び出しでは、文字の後にスペースがないことに注意してください。
Joda 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);
}
参考までに、これを1時間以上の期間について記述しただけで、Java.time.*
、理解し、必要に応じてカスタマイズするのはかなり簡単です。
このバージョンは次のような文字列で動作します。 3d12h
、2y
、9m10d
など.
import Java.time.Duration;
import Java.time.Instant;
import Java.time.Period;
import Java.util.regex.Matcher;
import Java.util.regex.Pattern;
import Java.util.Locale;
private static final Pattern periodPattern = Pattern.compile("([0-9]+)([hdwmy])");
public static Long parsePeriod(String period){
if(period == null) return null;
period = period.toLowerCase(Locale.ENGLISH);
Matcher matcher = periodPattern.matcher(period);
Instant instant=Instant.Epoch;
while(matcher.find()){
int num = Integer.parseInt(matcher.group(1));
String typ = matcher.group(2);
switch (typ) {
case "h":
instant=instant.plus(Duration.ofHours(num));
break;
case "d":
instant=instant.plus(Duration.ofDays(num));
break;
case "w":
instant=instant.plus(Period.ofWeeks(num));
break;
case "m":
instant=instant.plus(Period.ofMonths(num));
break;
case "y":
instant=instant.plus(Period.ofYears(num));
break;
}
}
return instant.toEpochMilli();
}
いいえ、Jodaはデフォルトで、期間、インスタント間隔、およびオブジェクトのみを取得します。後者の場合、日付やSOAP ISO形式など)を受け入れます。Durationクラス用に独自のコンバータをここに追加できます。これにより、醜いコードをすべて隠すことができます。