Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix @QueryValue of LocalDateTime type for 3.10.x #9970

Merged
merged 5 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.micronaut.core.convert.format.Format;
import io.micronaut.core.util.StringUtils;

import java.time.DateTimeException;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
Expand All @@ -39,6 +40,7 @@
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAmount;
import java.time.temporal.TemporalQuery;
Expand Down Expand Up @@ -150,8 +152,14 @@ public void register(ConversionService<?> conversionService) {
final TypeConverter<TemporalAccessor, CharSequence> temporalConverter = (object, targetType, context) -> {
try {
DateTimeFormatter formatter = resolveFormatter(context);
if (formatter.equals(DateTimeFormatter.RFC_1123_DATE_TIME) && !object.isSupported(ChronoField.OFFSET_SECONDS)) {
// RFC 1123 is our default output but requires a zone, which LDT doesn't support. Fall back on ISO 8601.
if (object instanceof LocalDateTime) {
return Optional.of(DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(object));
}
}
return Optional.of(formatter.format(object));
} catch (DateTimeParseException e) {
} catch (DateTimeException e) {
context.reject(object, e);
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import spock.lang.Shared
import spock.lang.Specification

import javax.validation.constraints.NotNull
import java.time.LocalDateTime
import java.time.OffsetDateTime
import java.time.format.DateTimeFormatter

Expand All @@ -39,29 +40,52 @@ class DateTimeConversionSpec extends Specification {
TimeController controller = embeddedServer.getApplicationContext().getBean(TimeController)
TimeClient client = embeddedServer.getApplicationContext().getBean(TimeClient)

def now = controller.target
def result = OffsetDateTime.parse(client.time(now))
def now = controller.targetOffset
def result = OffsetDateTime.parse(client.offsetDateTime(now))

expect:
result == now
}

void "test local date time conversion"() {
given:
TimeController controller = embeddedServer.getApplicationContext().getBean(TimeController)
TimeClient client = embeddedServer.getApplicationContext().getBean(TimeClient)

def now = controller.targetLocal
def result = LocalDateTime.parse(client.localDateTime(now))

expect:
result == now
}

static interface TimeApi {
@Get(uri = "/offset", processes = MediaType.TEXT_PLAIN)
String time(@NotNull @QueryValue OffsetDateTime time)
String offsetDateTime(@NotNull @QueryValue OffsetDateTime time)

@Get(uri = "/local", processes = MediaType.TEXT_PLAIN)
String localDateTime(@NotNull @QueryValue LocalDateTime time)
}

@Client("/convert/time")
static interface TimeClient extends TimeApi {}

@Controller("/convert/time")
static class TimeController implements TimeApi {
def target = OffsetDateTime.parse("2007-12-03T10:15:30+01:00")
def targetOffset = OffsetDateTime.parse("2007-12-03T10:15:30+01:00")
def targetLocal = targetOffset.toLocalDateTime()

@Override
String time(OffsetDateTime time) {
assert target == time
String offsetDateTime(OffsetDateTime time) {
assert targetOffset == time
return time.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
}

@Override
String localDateTime(@NotNull @QueryValue LocalDateTime time) {
assert targetLocal == time
return time.format(DateTimeFormatter.ISO_DATE_TIME)
}
}


Expand Down
Loading