Skip to content

Commit

Permalink
Fix to support different date formats in the sql query without date c…
Browse files Browse the repository at this point in the history
…asting

Github Issue - #2700

Signed-off-by: Manasvini B S <manasvis@amazon.com>
  • Loading branch information
manasvinibs committed Jun 18, 2024
1 parent 7b40c2c commit 27a6c10
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package org.opensearch.sql.data.model;

import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL;
import static org.opensearch.sql.utils.DateTimeFormatters.DATE_TIME_FORMATTER_PATTERNS_NANOS_OPTIONAL;

import com.google.common.base.Objects;
import java.time.Instant;
Expand All @@ -15,6 +16,12 @@
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;
import org.opensearch.sql.data.type.ExprCoreType;
import org.opensearch.sql.data.type.ExprType;
Expand All @@ -25,20 +32,44 @@
public class ExprDateValue extends AbstractExprValue {

private final LocalDate date;
private String datePattern;
// List of cleaned patterns
private static final List<String> CLEANED_PATTERNS = Arrays.stream(DATE_TIME_FORMATTER_PATTERNS_NANOS_OPTIONAL.split("\\]\\["))
.map(pattern -> pattern.replace("[", "").replace("]", ""))
.collect(Collectors.toList());

/** Constructor of ExprDateValue. */
public ExprDateValue(String date) {
try {
this.date = LocalDate.parse(date, DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL);
this.datePattern = determineDatePattern(date);
} catch (DateTimeParseException e) {
throw new SemanticCheckException(
String.format("date:%s in unsupported format, please use 'yyyy-MM-dd'", date));
}
}

private String determineDatePattern(String date) {
for (String pattern : CLEANED_PATTERNS) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern, Locale.ROOT)
.withResolverStyle(ResolverStyle.STRICT);
LocalDate.parse(date, formatter);
return pattern;
} catch (DateTimeParseException e) {
// Ignore and try next pattern
}
}
return DateTimeFormatter.ISO_LOCAL_DATE.toString();
}

@Override
public String value() {
return DateTimeFormatter.ISO_LOCAL_DATE.format(date);
if (this.datePattern == null) {
return DateTimeFormatter.ISO_LOCAL_DATE.format(date);
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(this.datePattern , Locale.ROOT);
return this.date.format(formatter);
}

@Override
Expand Down Expand Up @@ -68,7 +99,7 @@ public boolean isDateTime() {

@Override
public String toString() {
return String.format("DATE '%s'", value());
return String.format("DATE '%s'", DateTimeFormatter.ISO_LOCAL_DATE.format(date));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public class DateTimeFormatters {
private static final int MIN_FRACTION_SECONDS = 0;
private static final int MAX_FRACTION_SECONDS = 9;

// Date patterns string
public static final String DATE_TIME_FORMATTER_PATTERNS_NANOS_OPTIONAL = "[uuuu-MM-dd HH:mm:ss][uuuu-MM-dd HH:mm][HH:mm:ss][HH:mm][uuuu-MM-dd][dd-MMM-uu]";


public static final DateTimeFormatter TIME_ZONE_FORMATTER_NO_COLON =
new DateTimeFormatterBuilder()
.appendOffset("+HHmm", "Z")
Expand Down Expand Up @@ -130,7 +134,7 @@ public class DateTimeFormatters {

public static final DateTimeFormatter DATE_TIME_FORMATTER_VARIABLE_NANOS_OPTIONAL =
new DateTimeFormatterBuilder()
.appendPattern("[uuuu-MM-dd HH:mm:ss][uuuu-MM-dd HH:mm][HH:mm:ss][HH:mm][uuuu-MM-dd]")
.appendPattern(DATE_TIME_FORMATTER_PATTERNS_NANOS_OPTIONAL)
.appendFraction(
ChronoField.NANO_OF_SECOND, MIN_FRACTION_SECONDS, MAX_FRACTION_SECONDS, true)
.toFormatter(Locale.ROOT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ public void dateValueInterfaceTest() {
assertEquals("invalid to get dateValue from value of type INTEGER", exception.getMessage());
}

@Test
public void dateValueInterfaceSupportedFormatTest() {
ExprValue dateValue = new ExprDateValue("03-Jan-21");
assertEquals(LocalDate.of(2021, 1, 3), dateValue.dateValue());
}

@Test
public void dateInUnsupportedFormat() {
SemanticCheckException exception =
Expand Down

0 comments on commit 27a6c10

Please sign in to comment.