Skip to content

Commit

Permalink
[incubator-kie-issues#1829] Fix zero-seconds truncation on date time (#…
Browse files Browse the repository at this point in the history
…6255)

Co-authored-by: Gabriele-Cardosi <[email protected]>
  • Loading branch information
gitgabrio and Gabriele-Cardosi authored Feb 17, 2025
1 parent 452c37b commit 8419e52
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
Expand Down Expand Up @@ -107,7 +107,8 @@ private ZoneTime(LocalTime localTime, ZoneId zoneId, boolean hasSeconds) {
this.offsetTime = OffsetTime.of(localTime, offset);
this.zoneId = zoneId;
this.hasSeconds = hasSeconds;
this.stringRepresentation = String.format("%s@%s", localTime, zoneId);
String localTimeString = localTime.format(DateTimeFormatter.ISO_LOCAL_TIME);
this.stringRepresentation = String.format("%s@%s", localTimeString, zoneId);
}

// package default for testing purpose
Expand Down Expand Up @@ -146,14 +147,12 @@ public Temporal plus(TemporalAmount amount) {

@Override
public Temporal minus(long amountToSubtract, TemporalUnit unit) {
return
getNewZoneOffset(offsetTime.minus(amountToSubtract, unit));
return getNewZoneOffset(offsetTime.minus(amountToSubtract, unit));
}

@Override
public Temporal minus(TemporalAmount amount) {
return
getNewZoneOffset(offsetTime.minus(amount));
return getNewZoneOffset(offsetTime.minus(amount));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
Expand Down Expand Up @@ -68,7 +68,13 @@ public static boolean timeStringWithSeconds(String val) {
return timePattern.matcher(val).find();
}

private static final BigDecimal NANO_MULT = BigDecimal.valueOf( 1000000000 );
static String getFormattedStringFromTemporalAccessorAndZone(TemporalAccessor date, ZoneId zone) {
LocalTime localTime = date.query(TemporalQueries.localTime());
String localTimeString = localTime.format(DateTimeFormatter.ISO_LOCAL_TIME);
return String.format("%s@%s", localTimeString, zone);
}

private static final BigDecimal NANO_MULT = BigDecimal.valueOf(1000000000);


protected TimeFunction() {
Expand Down Expand Up @@ -161,7 +167,7 @@ public FEELFnResult<TemporalAccessor> invoke(@ParameterName("from") TemporalAcce
if (!(zone instanceof ZoneOffset)) {
// TZ is a ZoneRegion, so do NOT normalize (although the result will be unreversible, but will keep what was supplied originally).
// Unfortunately java.time.Parsed is a package-private class, hence will need to re-parse in order to have it instantiated.
return invoke(date.query(TemporalQueries.localTime()) + "@" + zone);
return invoke(getFormattedStringFromTemporalAccessorAndZone(date, zone));
} else {
return FEELFnResult.ofResult(OffsetTime.from(date));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,6 @@ void composite5() {
assertThat(timeOnDateTime.query(TemporalQueries.localTime())).isEqualTo(LocalTime.of(10, 20, 0));
assertThat(timeOnDateTime.query(TemporalQueries.zone())).isEqualTo(ZoneId.of("Europe/Paris"));

FunctionTestUtil.assertResult(stringFunction.invoke(timeOnDateTime), "10:20@Europe/Paris");
FunctionTestUtil.assertResult(stringFunction.invoke(timeOnDateTime), "10:20:00@Europe/Paris");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.kie.dmn.feel.runtime.functions;

import static org.assertj.core.api.Assertions.assertThat;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor;
import org.junit.jupiter.api.Test;

class DateAndTimeFunctionTest {

private final DateAndTimeFunction dateTimeFunction = DateAndTimeFunction.INSTANCE;

@Test
void invokeFromString() {
FEELFnResult<TemporalAccessor> retrievedResult = dateTimeFunction.invoke("2017-08-10T10:20:00@Europe/Paris");
assertThat(retrievedResult).isNotNull();
assertThat(retrievedResult.isRight()).isTrue();
TemporalAccessor retrieved = retrievedResult.getOrElse(null);
assertThat(retrieved).isNotNull().isInstanceOf(ZonedDateTime.class);
ZonedDateTime retrievedZonedDateTime = (ZonedDateTime) retrieved;
assertThat(retrievedZonedDateTime.getYear()).isEqualTo(2017);
assertThat(retrievedZonedDateTime.getMonthValue()).isEqualTo(8);
assertThat(retrievedZonedDateTime.getDayOfMonth()).isEqualTo(10);
assertThat(retrievedZonedDateTime.getHour()).isEqualTo(10);
assertThat(retrievedZonedDateTime.getMinute()).isEqualTo(20);
assertThat(retrievedZonedDateTime.getSecond()).isZero();
assertThat(retrievedZonedDateTime.getZone()).isEqualTo(ZoneId.of("Europe/Paris"));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
Expand Down Expand Up @@ -27,10 +27,11 @@
import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;

import org.junit.jupiter.api.Test;
import org.kie.dmn.feel.runtime.custom.ZoneTime;
import org.kie.dmn.feel.runtime.events.InvalidParametersEvent;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -185,6 +186,20 @@ void invokeTimeUnitsParamsWithOffsetWithNanoseconds() {
OffsetTime.of(10, 43, 15, 154000000, ZoneOffset.ofHours(-1)));
}

@Test
void invokeWithZonedDateTime() {
ZonedDateTime from = (ZonedDateTime) DateAndTimeFunction.INSTANCE.invoke("2017-08-10T10:20:00@Europe/Paris")
.getOrElse(null);
assertThat(from).isNotNull();
FEELFnResult<TemporalAccessor> retrievedResult = timeFunction.invoke(from);
assertThat(retrievedResult.isRight()).isTrue();
TemporalAccessor retrieved = retrievedResult.getOrElse(null);
assertThat(retrieved).isNotNull().isInstanceOf(ZoneTime.class);
ZoneTime retrievedZoneTime = (ZoneTime) retrieved;
assertThat(retrievedZoneTime).isNotNull();
assertThat(retrievedZoneTime).hasToString("10:20:00@Europe/Paris");
}

@Test
void timeStringWithSeconds() {
assertThat(TimeFunction.timeStringWithSeconds("10:10:00@Australia/Melbourne")).isTrue();
Expand All @@ -194,4 +209,19 @@ void timeStringWithSeconds() {
assertThat(TimeFunction.timeStringWithSeconds("10:10@Australia/Melbourne")).isFalse();
assertThat(TimeFunction.timeStringWithSeconds("10:10+10:00")).isFalse();
}

@Test
void getFormattedStringFromTemporalAccessorAndZone() {
ZonedDateTime date = (ZonedDateTime) DateAndTimeFunction.INSTANCE.invoke("2017-08-10T10:20:10@Europe/Paris")
.getOrElse(null);
assertThat(date).isNotNull();
ZoneId zone = date.query(TemporalQueries.zoneId());
assertThat(TimeFunction.getFormattedStringFromTemporalAccessorAndZone(date, zone))
.isEqualTo("10:20:10@Europe/Paris");
date = (ZonedDateTime) DateAndTimeFunction.INSTANCE.invoke("2017-08-10T10:20:00@Europe/Paris").getOrElse(null);
assertThat(date).isNotNull();
zone = date.query(TemporalQueries.zoneId());
assertThat(TimeFunction.getFormattedStringFromTemporalAccessorAndZone(date, zone))
.isEqualTo("10:20:00@Europe/Paris");
}
}

0 comments on commit 8419e52

Please sign in to comment.