Improve java.util.Date support for action inputs (#5310)

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
Jacob Laursen
2026-02-28 18:06:36 +01:00
committed by GitHub
parent 3108cd9984
commit 01c20d59ad
2 changed files with 42 additions and 33 deletions
@@ -13,8 +13,6 @@
package org.openhab.core.automation.util; package org.openhab.core.automation.util;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -24,6 +22,7 @@ import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -293,9 +292,6 @@ public class ActionInputsHelper {
// Accepted format is: 2007-12-03T10:15:30 // Accepted format is: 2007-12-03T10:15:30
LocalDateTime.parse(valueString); LocalDateTime.parse(valueString);
case "java.util.Date" -> case "java.util.Date" ->
// Accepted format is: 2007-12-03T10:15:30
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(valueString);
case "java.time.ZonedDateTime" -> {
/* /*
* Accepted format is one of: * Accepted format is one of:
* - 2007-12-03T10:15:30 * - 2007-12-03T10:15:30
@@ -303,14 +299,8 @@ public class ActionInputsHelper {
* - 2007-12-03T10:15:30+01:00 * - 2007-12-03T10:15:30+01:00
* - 2007-12-03T10:15:30+01:00[Europe/Paris] * - 2007-12-03T10:15:30+01:00[Europe/Paris]
*/ */
TemporalAccessor dt = DateTimeFormatter.ISO_DATE_TIME.parseBest(valueString, Date.from(parseAsIsoDateTime(valueString).toInstant());
ZonedDateTime::from, LocalDateTime::from); case "java.time.ZonedDateTime" ->
if (dt instanceof ZonedDateTime zdt) {
yield zdt;
}
yield ((LocalDateTime) dt).atZone(timeZoneProvider.getTimeZone());
}
case "java.time.Instant" -> {
/* /*
* Accepted format is one of: * Accepted format is one of:
* - 2007-12-03T10:15:30 * - 2007-12-03T10:15:30
@@ -318,13 +308,16 @@ public class ActionInputsHelper {
* - 2007-12-03T10:15:30+01:00 * - 2007-12-03T10:15:30+01:00
* - 2007-12-03T10:15:30+01:00[Europe/Paris] * - 2007-12-03T10:15:30+01:00[Europe/Paris]
*/ */
TemporalAccessor dt = DateTimeFormatter.ISO_DATE_TIME.parseBest(valueString, parseAsIsoDateTime(valueString);
ZonedDateTime::from, LocalDateTime::from); case "java.time.Instant" ->
if (dt instanceof ZonedDateTime zdt) { /*
yield zdt.toInstant(); * Accepted format is one of:
} * - 2007-12-03T10:15:30
yield ((LocalDateTime) dt).atZone(timeZoneProvider.getTimeZone()).toInstant(); * - 2007-12-03T09:15:30Z
} * - 2007-12-03T10:15:30+01:00
* - 2007-12-03T10:15:30+01:00[Europe/Paris]
*/
parseAsIsoDateTime(valueString).toInstant();
case "java.time.Duration" -> case "java.time.Duration" ->
// Accepted format is: P2DT17H25M30.5S // Accepted format is: P2DT17H25M30.5S
Duration.parse(valueString); Duration.parse(valueString);
@@ -333,7 +326,7 @@ public class ActionInputsHelper {
} }
} }
return argument; return argument;
} catch (IllegalArgumentException | DateTimeParseException | ParseException e) { } catch (IllegalArgumentException | DateTimeParseException e) {
throw new IllegalArgumentException("Input parameter '" + input.getName() + "': converting value '" throw new IllegalArgumentException("Input parameter '" + input.getName() + "': converting value '"
+ argument.toString() + "' into type " + input.getType() + " failed!"); + argument.toString() + "' into type " + input.getType() + " failed!");
} }
@@ -346,4 +339,13 @@ public class ActionInputsHelper {
} }
return unitProvider.getUnit((Class<? extends Quantity>) dimension); return unitProvider.getUnit((Class<? extends Quantity>) dimension);
} }
private ZonedDateTime parseAsIsoDateTime(String valueString) {
TemporalAccessor dt = DateTimeFormatter.ISO_DATE_TIME.parseBest(valueString, ZonedDateTime::from,
LocalDateTime::from);
if (dt instanceof ZonedDateTime zdt) {
return zdt;
}
return ((LocalDateTime) dt).atZone(timeZoneProvider.getTimeZone());
}
} }
@@ -17,8 +17,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
@@ -456,19 +454,28 @@ public class ActionInputHelperTest {
@Test @Test
public void testMapSerializedInputToActionInputWhenDate() { public void testMapSerializedInputToActionInputWhenDate() {
String valAsString = "2024-11-05T09:45:12"; String valAsString = "2024-11-05T08:45:12Z";
Date val; Date val = Date.from(Instant.parse(valAsString));
try {
val = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(valAsString);
} catch (IllegalArgumentException | ParseException e) {
val = null;
}
assertNotNull(val);
Input input = buildInput("java.util.Date"); Input input = buildInput("java.util.Date");
assertThat(helper.mapSerializedInputToActionInput(input, val), is(val)); assertThat(helper.mapSerializedInputToActionInput(input, val), is(val));
assertThat(helper.mapSerializedInputToActionInput(input, valAsString), is(val)); assertThat(helper.mapSerializedInputToActionInput(input, valAsString), is(val));
assertThrows(IllegalArgumentException.class,
() -> helper.mapSerializedInputToActionInput(input, valAsString.replace("T", " "))); valAsString = "2024-11-05T09:45:12";
val = Date.from(LocalDateTime.parse(valAsString).atZone(timeZoneProvider.getTimeZone()).toInstant());
assertThat(helper.mapSerializedInputToActionInput(input, val), is(val));
assertThat(helper.mapSerializedInputToActionInput(input, valAsString), is(val));
String s1 = valAsString.replace("T", " ");
assertThrows(IllegalArgumentException.class, () -> helper.mapSerializedInputToActionInput(input, s1));
valAsString = "2024-11-05T09:45:12+04:00";
val = Date.from(ZonedDateTime.parse(valAsString, DateTimeFormatter.ISO_DATE_TIME).toInstant());
assertThat(helper.mapSerializedInputToActionInput(input, val), is(val));
assertThat(helper.mapSerializedInputToActionInput(input, valAsString), is(val));
valAsString = "2024-11-05T09:45:12+04:00[Europe/Kyiv]";
val = Date.from(ZonedDateTime.parse(valAsString, DateTimeFormatter.ISO_DATE_TIME).toInstant());
assertThat(helper.mapSerializedInputToActionInput(input, val), is(val));
assertThat(helper.mapSerializedInputToActionInput(input, valAsString), is(val));
} }
@Test @Test