Skip to content

Commit

Permalink
Added local datetime formatter
Browse files Browse the repository at this point in the history
Signed-off-by: Prabhat Sharma <[email protected]>
  • Loading branch information
Prabhat Sharma committed Dec 27, 2023
1 parent ad35665 commit f8dd4a2
Show file tree
Hide file tree
Showing 7 changed files with 509 additions and 174 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1334,6 +1334,38 @@ public class DateFormatters {
)
);

public static final DateFormatter LOCAL_DATETIME_FORMATTER = new JavaDateFormatter(
"local_datetime",
new OpenSearchDateTimeFormatter(STRICT_DATE_OPTIONAL_TIME_PRINTER),
new LocalDateTimeFormatter(
new DateTimeFormatterBuilder().append(DATE_FORMATTER)
.optionalStart()
.optionalStart()
.appendLiteral(' ')
.optionalEnd()
.optionalStart()
.appendLiteral('T')
.optionalEnd()
.appendValue(HOUR_OF_DAY, 1, 2, SignStyle.NOT_NEGATIVE)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 1, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 1, 2, SignStyle.NOT_NEGATIVE)
.optionalStart()
.appendFraction(NANO_OF_SECOND, 1, 9, true)
.optionalEnd()
.optionalStart()
.appendLiteral(',')
.appendFraction(NANO_OF_SECOND, 1, 9, false)
.optionalEnd()
.optionalEnd()
.optionalEnd()
.toFormatter(Locale.ROOT)
.withResolverStyle(ResolverStyle.STRICT)
)
);

private static final DateTimeFormatter HOUR_MINUTE_SECOND_FORMATTER = new DateTimeFormatterBuilder().append(HOUR_MINUTE_FORMATTER)
.appendLiteral(":")
.appendValue(SECOND_OF_MINUTE, 1, 2, SignStyle.NOT_NEGATIVE)
Expand Down Expand Up @@ -2189,6 +2221,8 @@ static DateFormatter forPattern(String input) {
return STRICT_YEAR_MONTH_DAY;
} else if (FormatNames.RFC3339.matches(input)) {
return RFC3339_DATE_FORMATTER;
} else if (FormatNames.LOCAL_DATE_TIME.matches(input)) {
return LOCAL_DATETIME_FORMATTER;
} else {
try {
return new JavaDateFormatter(
Expand Down
10 changes: 10 additions & 0 deletions server/src/main/java/org/opensearch/common/time/DateTime.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package org.opensearch.common.time;

import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoField;
Expand Down Expand Up @@ -159,6 +160,15 @@ public OffsetDateTime toOffsetDatetime() {
throw new DateTimeException("No zone offset information found");
}

/**
* Creates an {@link java.time.LocalDateTime}
*
* return the {@link java.time.LocalDateTime}
*/
public LocalDateTime toLocalDatetime() {
return LocalDateTime.of(year, month, day, hour, minute, second, nano);
}

/**
* * @hidden
*/
Expand Down
146 changes: 146 additions & 0 deletions server/src/main/java/org/opensearch/common/time/DateUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,15 @@
import org.opensearch.common.logging.DeprecationLogger;
import org.joda.time.DateTimeZone;

import java.text.ParsePosition;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -57,6 +60,18 @@
* @opensearch.internal
*/
public class DateUtils {
public static final char DATE_SEPARATOR = '-';
public static final char TIME_SEPARATOR = ':';
public static final char SEPARATOR_UPPER = 'T';
static final char PLUS = '+';
static final char MINUS = '-';
static final char SEPARATOR_LOWER = 't';
static final char SEPARATOR_SPACE = ' ';
static final char FRACTION_SEPARATOR_1 = '.';
static final char FRACTION_SEPARATOR_2 = ',';
static final char ZULU_UPPER = 'Z';
static final char ZULU_LOWER = 'z';

public static DateTimeZone zoneIdToDateTimeZone(ZoneId zoneId) {
if (zoneId == null) {
return null;
Expand Down Expand Up @@ -430,4 +445,135 @@ public static ZonedDateTime nowWithMillisResolution(Clock clock) {
Clock millisResolutionClock = Clock.tick(clock, Duration.ofMillis(1));
return ZonedDateTime.now(millisResolutionClock);
}

private static boolean isDigit(char c) {
return (c >= '0' && c <= '9');
}

private static int digit(char c) {
return c - '0';
}

static int readInt(final char[] strNum, ParsePosition pos, int n) {
int start = pos.getIndex(), end = start + n;
if (end > strNum.length) {
pos.setErrorIndex(end);
throw new DateTimeParseException("Unexpected end of expression at position " + strNum.length, new String(strNum), end);
}

int result = 0;
for (int i = start; i < end; i++) {
final char c = strNum[i];
if (isDigit(c) == false) {
pos.setErrorIndex(i);
throw new DateTimeParseException("Character " + c + " is not a digit", new String(strNum), i);
}
int digit = digit(c);
result = result * 10 + digit;
}
pos.setIndex(end);
return result;
}

static int readIntUnchecked(final char[] strNum, ParsePosition pos, int n) {
int start = pos.getIndex(), end = start + n;
int result = 0;
for (int i = start; i < end; i++) {
final char c = strNum[i];
int digit = digit(c);
result = result * 10 + digit;
}
pos.setIndex(end);
return result;
}

private static boolean isValidOffset(char[] chars, int offset) {
if (offset >= chars.length) {
return false;
}
return true;
}

static void consumeChar(char[] chars, ParsePosition pos, char expected) {
int offset = pos.getIndex();
if (isValidOffset(chars, offset) == false) {
throw new DateTimeParseException("Unexpected end of input", new String(chars), offset);
}

if (chars[offset] != expected) {
throw new DateTimeParseException("Expected character " + expected + " at position " + offset, new String(chars), offset);
}
pos.setIndex(offset + 1);
}

static void consumeNextChar(char[] chars, ParsePosition pos) {
int offset = pos.getIndex();
if (isValidOffset(chars, offset) == false) {
throw new DateTimeParseException("Unexpected end of input", new String(chars), offset);
}
pos.setIndex(offset + 1);
}

static boolean checkPositionContains(char[] chars, ParsePosition pos, char... expected) {
int offset = pos.getIndex();
if (offset >= chars.length) {
throw new DateTimeParseException("Unexpected end of input", new String(chars), offset);
}

boolean found = false;
for (char e : expected) {
if (chars[offset] == e) {
found = true;
break;
}
}
return found;
}

static void consumeChar(char[] chars, ParsePosition pos, char... expected) {
int offset = pos.getIndex();
if (offset >= chars.length) {
throw new DateTimeParseException("Unexpected end of input", new String(chars), offset);
}

boolean found = false;
for (char e : expected) {
if (chars[offset] == e) {
found = true;
pos.setIndex(offset + 1);
break;
}
}
if (!found) {
throw new DateTimeParseException(
"Expected character " + Arrays.toString(expected) + " at position " + offset,
new String(chars),
offset
);
}
}

static void assertNoMoreChars(char[] chars, ParsePosition pos) {
if (chars.length > pos.getIndex()) {
throw new DateTimeParseException("Trailing junk data after position " + pos.getIndex(), new String(chars), pos.getIndex());
}
}

public static int indexOfNonDigit(final char[] text, int offset) {
for (int i = offset; i < text.length; i++) {
if (isDigit(text[i]) == false) {
return i;
}
}
return -1;
}

public static void consumeDigits(final char[] text, ParsePosition pos) {
final int idx = indexOfNonDigit(text, pos.getIndex());
if (idx == -1) {
pos.setErrorIndex(text.length);
} else {
pos.setIndex(idx);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
public enum FormatNames {
ISO8601(null, "iso8601"),
RFC3339(null, "rfc3339"),
LOCAL_DATE_TIME("localDateTime", "local_date_time"),
BASIC_DATE("basicDate", "basic_date"),
BASIC_DATE_TIME("basicDateTime", "basic_date_time"),
BASIC_DATE_TIME_NO_MILLIS("basicDateTimeNoMillis", "basic_date_time_no_millis"),
Expand Down
Loading

0 comments on commit f8dd4a2

Please sign in to comment.