Skip to content
Open
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 @@ -662,9 +662,10 @@ public void processOpts() {
typeMapping.put("date", "LocalDate");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalTime", "java.time.LocalTime");
typeMapping.put("date-time-local", "LocalDateTime");
importMapping.put("LocalDateTime", "java.time.LocalDateTime");
if ("java8-localdatetime".equals(dateLibrary)) {
typeMapping.put("DateTime", "LocalDateTime");
importMapping.put("LocalDateTime", "java.time.LocalDateTime");
} else {
typeMapping.put("DateTime", "OffsetDateTime");
importMapping.put("OffsetDateTime", "java.time.OffsetDateTime");
Expand Down Expand Up @@ -1411,6 +1412,13 @@ public String toDefaultValue(CodegenProperty cp, Schema schema) {
return "URI.create(\"" + escapeText(String.valueOf(schema.getDefault())) + "\")";
}
return null;
} else if (ModelUtils.isDateTimeLocalSchema(schema)) {
if (schema.getDefault() != null) {
if ("java8".equals(getDateLibrary())) {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Apr 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: date-time-local default generation is incorrectly limited to dateLibrary=java8, so java8-localdatetime silently loses declared defaults.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java, line 1417:

<comment>`date-time-local` default generation is incorrectly limited to `dateLibrary=java8`, so `java8-localdatetime` silently loses declared defaults.</comment>

<file context>
@@ -1411,6 +1412,13 @@ public String toDefaultValue(CodegenProperty cp, Schema schema) {
             return null;
+        } else if (ModelUtils.isDateTimeLocalSchema(schema)) {
+            if (schema.getDefault() != null) {
+                if ("java8".equals(getDateLibrary())) {
+                    return String.format(Locale.ROOT, "LocalDateTime.parse(\"%s\")", String.valueOf(schema.getDefault()));
+                }
</file context>
Fix with Cubic

return String.format(Locale.ROOT, "LocalDateTime.parse(\"%s\")", String.valueOf(schema.getDefault()));
}
}
return null;
} else if (ModelUtils.isStringSchema(schema)) {
if (schema.getDefault() != null) {
String _default;
Expand Down Expand Up @@ -1493,6 +1501,10 @@ public String toDefaultValue(CodegenProperty cp, Schema schema) {
value.asText(),
"java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME.withZone(java.time.ZoneId.systemDefault())");
}
} else if(ModelUtils.isDateTimeLocalSchema(propertySchema)) {
if("java8".equals(getDateLibrary())) {
defaultPropertyExpression = String.format(Locale.ROOT, "java.time.LocalDateTime.parse(\"%s\")", value.asText());
}
} else if(ModelUtils.isUUIDSchema(propertySchema)) {
defaultPropertyExpression = "java.util.UUID.fromString(\"" + value.asText() + "\")";
} else if(ModelUtils.isStringSchema(propertySchema)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,12 @@ public static boolean isDateTimeSchema(Schema schema) {
&& SchemaTypeUtil.DATE_TIME_FORMAT.equals(schema.getFormat()));
}

public static boolean isDateTimeLocalSchema(Schema schema) {
// format: date-time-local, see https://spec.openapis.org/registry/format/date-time-local.html
return (SchemaTypeUtil.STRING_TYPE.equals(getType(schema))
&& "date-time-local".equals(schema.getFormat()));
}

public static boolean isPasswordSchema(Schema schema) {
return (schema instanceof PasswordSchema) ||
// double
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,15 @@ public void toDefaultValueDateTimeLegacyTest() {

// dateLibrary <> java8
Assert.assertEquals(defaultValue, "1984-12-19T03:39:57-09:00");

// Test default value for date-time-local format
StringSchema dateTimeLocalSchema = new StringSchema();
dateTimeLocalSchema.setFormat("date-time-local");
dateTimeLocalSchema.setDefault("2007-12-03T10:15:30");
defaultValue = codegen.toDefaultValue(dateTimeLocalSchema);

// dateLibrary <> java8, should return null
Assert.assertNull(defaultValue);
}

@Test
Expand Down Expand Up @@ -593,6 +602,13 @@ public void toDefaultValueTest() {
numberSchema.setFormat("double");
defaultValue = codegen.toDefaultValue(codegen.fromProperty("", schema), numberSchema);
Assert.assertEquals(defaultValue, doubleValue + "d");

// Test default value for date-time-local format
StringSchema dateTimeLocalSchema = new StringSchema();
dateTimeLocalSchema.setFormat("date-time-local");
dateTimeLocalSchema.setDefault("2007-12-03T10:15:30");
defaultValue = codegen.toDefaultValue(codegen.fromProperty("", dateTimeLocalSchema), dateTimeLocalSchema);
Assert.assertEquals(defaultValue, "LocalDateTime.parse(\"2007-12-03T10:15:30\")");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,35 @@ public void generateFormatForDateAndDateTimeQueryParam() throws IOException {
.containsWithNameAndAttributes("DateTimeFormat", ImmutableMap.of("iso", "DateTimeFormat.ISO.DATE_TIME"));
}

@Test
public void generateLocalDateTimeForDateTimeLocalFormat() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
String outputPath = output.getAbsolutePath().replace('\\', '/');

OpenAPI openAPI = new OpenAPIParser()
.readLocation("src/test/resources/3_0/spring/date-time-parameter-types-for-testing.yml", null, new ParseOptions()).getOpenAPI();

SpringCodegen codegen = new SpringCodegen();
codegen.setOutputDir(output.getAbsolutePath());

ClientOptInput input = new ClientOptInput();
input.openAPI(openAPI);
input.config(codegen);

DefaultGenerator generator = new DefaultGenerator();
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false");
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false");
generator.setGenerateMetadata(false);
generator.opts(input).generate();

JavaFileAssert.assertThat(Paths.get(outputPath + "/src/main/java/org/openapitools/model/Pet.java"))
.hasImports("java.time.LocalDateTime")
.assertProperty("adoptionDate").withType("LocalDateTime");
}

@Test
public void interfaceDefaultImplDisableWithResponseWrapper() {
final SpringCodegen codegen = new SpringCodegen();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ components:
type: string
format: date
default: '2021-01-01'
adoptionDate:
type: string
format: date-time-local
default: '2007-12-03T10:15:30'
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.lang.Nullable;
Expand Down Expand Up @@ -40,6 +41,8 @@ public class Pet {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate dateOfBirth = LocalDate.parse("2021-01-01");

private LocalDateTime adoptionDate = LocalDateTime.parse("2007-12-03T10:15:30");

public Pet() {
super();
}
Expand Down Expand Up @@ -177,6 +180,27 @@ public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}

public Pet adoptionDate(LocalDateTime adoptionDate) {
this.adoptionDate = adoptionDate;
return this;
}

/**
* Get adoptionDate
* @return adoptionDate
*/
@Valid
@Schema(name = "adoptionDate", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonProperty("adoptionDate")
public LocalDateTime getAdoptionDate() {
return adoptionDate;
}

@JsonProperty("adoptionDate")
public void setAdoptionDate(LocalDateTime adoptionDate) {
this.adoptionDate = adoptionDate;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -191,12 +215,13 @@ public boolean equals(Object o) {
Objects.equals(this.happy, pet.happy) &&
Objects.equals(this.price, pet.price) &&
Objects.equals(this.lastFeed, pet.lastFeed) &&
Objects.equals(this.dateOfBirth, pet.dateOfBirth);
Objects.equals(this.dateOfBirth, pet.dateOfBirth) &&
Objects.equals(this.adoptionDate, pet.adoptionDate);
}

@Override
public int hashCode() {
return Objects.hash(atType, age, happy, price, lastFeed, dateOfBirth);
return Objects.hash(atType, age, happy, price, lastFeed, dateOfBirth, adoptionDate);
}

@Override
Expand All @@ -209,6 +234,7 @@ public String toString() {
sb.append(" price: ").append(toIndentedString(price)).append("\n");
sb.append(" lastFeed: ").append(toIndentedString(lastFeed)).append("\n");
sb.append(" dateOfBirth: ").append(toIndentedString(dateOfBirth)).append("\n");
sb.append(" adoptionDate: ").append(toIndentedString(adoptionDate)).append("\n");
sb.append("}");
return sb.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.lang.Nullable;
Expand Down Expand Up @@ -40,6 +41,8 @@ public class Pet {
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate dateOfBirth = LocalDate.parse("2021-01-01");

private LocalDateTime adoptionDate = LocalDateTime.parse("2007-12-03T10:15:30");

public Pet() {
super();
}
Expand Down Expand Up @@ -177,6 +180,27 @@ public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}

public Pet adoptionDate(LocalDateTime adoptionDate) {
this.adoptionDate = adoptionDate;
return this;
}

/**
* Get adoptionDate
* @return adoptionDate
*/
@Valid
@Schema(name = "adoptionDate", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonProperty("adoptionDate")
public LocalDateTime getAdoptionDate() {
return adoptionDate;
}

@JsonProperty("adoptionDate")
public void setAdoptionDate(LocalDateTime adoptionDate) {
this.adoptionDate = adoptionDate;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand All @@ -191,12 +215,13 @@ public boolean equals(Object o) {
Objects.equals(this.happy, pet.happy) &&
Objects.equals(this.price, pet.price) &&
Objects.equals(this.lastFeed, pet.lastFeed) &&
Objects.equals(this.dateOfBirth, pet.dateOfBirth);
Objects.equals(this.dateOfBirth, pet.dateOfBirth) &&
Objects.equals(this.adoptionDate, pet.adoptionDate);
}

@Override
public int hashCode() {
return Objects.hash(atType, age, happy, price, lastFeed, dateOfBirth);
return Objects.hash(atType, age, happy, price, lastFeed, dateOfBirth, adoptionDate);
}

@Override
Expand All @@ -209,6 +234,7 @@ public String toString() {
sb.append(" price: ").append(toIndentedString(price)).append("\n");
sb.append(" lastFeed: ").append(toIndentedString(lastFeed)).append("\n");
sb.append(" dateOfBirth: ").append(toIndentedString(dateOfBirth)).append("\n");
sb.append(" adoptionDate: ").append(toIndentedString(adoptionDate)).append("\n");
sb.append("}");
return sb.toString();
}
Expand Down