Skip to content

Commit 14c848b

Browse files
committed
[FLINK-37668][core] TimeUtils supports to parse ISO-8601 duration format
1 parent 929bd15 commit 14c848b

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

flink-core/src/main/java/org/apache/flink/util/TimeUtils.java

+16-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.math.BigInteger;
2222
import java.time.Duration;
23+
import java.time.format.DateTimeParseException;
2324
import java.time.temporal.ChronoUnit;
2425
import java.util.Arrays;
2526
import java.util.Collections;
@@ -43,7 +44,8 @@ public class TimeUtils {
4344
/**
4445
* Parse the given string to a java {@link Duration}. The string is in format "{length
4546
* value}{time unit label}", e.g. "123ms", "321 s". If no time unit label is specified, it will
46-
* be considered as milliseconds.
47+
* be considered as milliseconds. If above rules are not matched, it will fall back to parse
48+
* ISO-8601 duration format.
4749
*
4850
* <p>Supported time unit labels are:
4951
*
@@ -77,7 +79,19 @@ public static Duration parseDuration(String text) {
7779
final String unitLabel = trimmed.substring(pos).trim().toLowerCase(Locale.US);
7880

7981
if (number.isEmpty()) {
80-
throw new NumberFormatException("text does not start with a number");
82+
try {
83+
// Fall back to parse ISO-8601 duration format
84+
Duration parsedDuration = Duration.parse(trimmed);
85+
if (parsedDuration.isNegative()) {
86+
// Don't support negative duration which is consistent with before format
87+
throw new NumberFormatException("negative duration is not supported");
88+
}
89+
return parsedDuration;
90+
} catch (DateTimeParseException e) {
91+
throw new NumberFormatException(
92+
"text does not start with a number, and is not a valid ISO-8601 duration format: "
93+
+ trimmed);
94+
}
8195
}
8296

8397
final BigInteger value;

flink-core/src/test/java/org/apache/flink/util/TimeUtilsTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,14 @@ void testParseDurationTrim() {
116116
assertThat(TimeUtils.parseDuration(" 155 ms ").toMillis()).isEqualTo(155L);
117117
}
118118

119+
@Test
120+
public void testParseDurationISO8601() {
121+
assertThat(TimeUtils.parseDuration("PT20.345S").toMillis()).isEqualTo(20345);
122+
assertThat(TimeUtils.parseDuration("PT15M").toMinutes()).isEqualTo(15);
123+
assertThat(TimeUtils.parseDuration("PT10H").toHours()).isEqualTo(10);
124+
assertThat(TimeUtils.parseDuration("P2DT3H4M").toMinutes()).isEqualTo(3064);
125+
}
126+
119127
@Test
120128
void testParseDurationInvalid() {
121129
// null
@@ -145,6 +153,10 @@ void testParseDurationInvalid() {
145153
// negative number
146154
assertThatThrownBy(() -> TimeUtils.parseDuration("-100 ms"))
147155
.isInstanceOf(IllegalArgumentException.class);
156+
157+
// negative ISO-8601
158+
assertThatThrownBy(() -> TimeUtils.parseDuration("-PT6H3M"))
159+
.isInstanceOf(NumberFormatException.class);
148160
}
149161

150162
@Test

0 commit comments

Comments
 (0)