I want to parse a string like 1d2h3m4s
into a java.time.Duration
. I can use a joda's PeriodFormatter
to parse the string into a org.joda.time.Duration
but I can't figure out how to convert that to a standard Java8's java.time.Duration
.
I have to interface to some "legacy" code that already expects java.time.Duration
as input, but I want to use joda's parsePeriod
because the java.time.Duration.parse()
only accepts ISO-8601 duration format (1d2h3m4s
is not ISO-8601 duration compliant)
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;
...
final PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
.printZeroNever()
.appendDays().appendSuffix("d")
.appendHours().appendSuffix("h")
.appendMinutes().appendSuffix("m")
.appendSeconds().appendSuffix("s").toFormatter();
org.joda.time.Duration myduration = periodFormatter.parsePeriod("1d1s").toStandardDuration();
java.util.time myduration2 = XXXXX
Please bear in mind that I'm not trying to remove the usage of org.joda.time.Period
from my code like in Converting org.joda.time.Period to java.time.Period. I still want to have a org.joda.time.Period
because I have more parsing option to generate those, and I need a java.time.Period
/java.time.Duration
because I interact with some other API/libraries that expect java.time.*
.
So, is there a way to convert a org.joda.time.Duration
to a java.time.Duration
?
I am presenting three options
- Hand modify the string to ISO 8601 format so that
java.time.Duration
can parse it. - Convert through count of milliseconds.
- Convert from
joda.time.Duration.toString()
.
Modify the string
Personally I don’t think I would want to depend in Joda-Time for this. Instead I would modify your non-ISO 8601 string to ISO 8601 format.
String durationString = "1d1s";
// Convert to ISO 8601 format
String isoString = durationString.replaceFirst("(.*?[Dd])?(.*)", "P$1T$2");
java.time.Duration dur = java.time.Duration.parse(isoString);
System.out.println(dur);
Output is:
PT24H1S
I admit that the regular expression is a bit hard to read. If there is an uppercase or lowercase D
in the string, everything up to and including that D
is placed before the T
in the ISO string. Everything else is placed after the T
.
Convert over milliseconds
This is an idea similar to the one in the answer by ecerulm. I didn’t want to lose the millisecond precision of the Joda-Time duration, so I rely of milliseconds rather than seconds (I know that for your example strings it will make no difference).
final PeriodFormatter periodFormatter = new PeriodFormatterBuilder()
.printZeroNever()
.appendDays().appendSuffix("d")
.appendHours().appendSuffix("h")
.appendMinutes().appendSuffix("m")
.appendSeconds().appendSuffix("s").toFormatter();
org.joda.time.Duration myduration = periodFormatter.parsePeriod("1d1s").toStandardDuration();
java.time.Duration dur = java.time.Duration.ofMillis(myduration.getMillis());
The result is the same as before.
Convert over a string
java.time.Duration dur = java.time.Duration.parse(myduration.toString());
Again the result is the same. Formatting the duration into an ISO 8601 string only to parse it back feels like a waste, though.