Skip to content

Commit

Permalink
Added New DateTime parser implementation
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 71d7e4d commit ad35665
Show file tree
Hide file tree
Showing 9 changed files with 957 additions and 36 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- GHA to verify checklist items completion in PR descriptions ([#10800](https://github.com/opensearch-project/OpenSearch/pull/10800))
- Allow to pass the list settings through environment variables (like [], ["a", "b", "c"], ...) ([#10625](https://github.com/opensearch-project/OpenSearch/pull/10625))
- [Admission Control] Integrate CPU AC with ResourceUsageCollector and add CPU AC stats to nodes/stats ([#10887](https://github.com/opensearch-project/OpenSearch/pull/10887))
- New DateTime format for RFC3339 compatible date fields ([#11465](https://github.com/opensearch-project/OpenSearch/pull/11465))

### Dependencies
- Bump `log4j-core` from 2.18.0 to 2.19.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1299,6 +1299,41 @@ public class DateFormatters {
.withResolverStyle(ResolverStyle.STRICT)
);

/**
* Returns RFC 3339 a popular ISO 8601 profile compatible date time formatter and parser.
* This is not fully compatible to the existing spec, its more linient and closely follows w3c note on datetime
*/

public static final DateFormatter RFC3339_DATE_FORMATTER = new JavaDateFormatter(
"rfc3339",
new OpenSearchDateTimeFormatter(STRICT_DATE_OPTIONAL_TIME_PRINTER),
new RFC3339DateTimeFormatter(
new DateTimeFormatterBuilder().append(DATE_FORMATTER)
.optionalStart()
.appendLiteral('T')
.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()
.optionalStart()
.appendOffsetId()
.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 @@ -2152,6 +2187,8 @@ static DateFormatter forPattern(String input) {
return STRICT_YEAR_MONTH;
} else if (FormatNames.STRICT_YEAR_MONTH_DAY.matches(input)) {
return STRICT_YEAR_MONTH_DAY;
} else if (FormatNames.RFC3339.matches(input)) {
return RFC3339_DATE_FORMATTER;
} else {
try {
return new JavaDateFormatter(
Expand Down
192 changes: 192 additions & 0 deletions server/src/main/java/org/opensearch/common/time/DateTime.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

package org.opensearch.common.time;

import java.time.DateTimeException;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoField;
import java.util.Objects;
import java.util.Optional;

/**
* Container class for parsed date/date-time data.
*/
class DateTime {
private final int year;
private final int month;
private final int day;
private final int hour;
private final int minute;
private final int second;
private final int nano;
private final ZoneOffset offset;
private final int fractionDigits;

public DateTime(
final int year,
final int month,
final int day,
final int hour,
final int minute,
final int second,
final int nano,
final ZoneOffset offset,
final int fractionDigits
) {
this.year = year;
this.month = assertSize(month, 1, 12, ChronoField.MONTH_OF_YEAR);
this.day = assertSize(day, 1, 31, ChronoField.DAY_OF_MONTH);
this.hour = assertSize(hour, 0, 23, ChronoField.HOUR_OF_DAY);
this.minute = assertSize(minute, 0, 59, ChronoField.MINUTE_OF_HOUR);
this.second = assertSize(second, 0, 60, ChronoField.SECOND_OF_MINUTE);
this.nano = assertSize(nano, 0, 999_999_999, ChronoField.NANO_OF_SECOND);
this.offset = offset;
this.fractionDigits = fractionDigits;
}

/**
* Create a new instance with minute granularity from the input parameters
*/
public static DateTime of(int year, int month, int day, int hour, int minute, ZoneOffset offset) {
return new DateTime(year, month, day, hour, minute, 0, 0, offset, 0);
}

/**
* Create a new instance with second granularity from the input parameters
*/
public static DateTime of(int year, int month, int day, int hour, int minute, int second, ZoneOffset offset) {
return new DateTime(year, month, day, hour, minute, second, 0, offset, 0);
}

/**
* Create a new instance with nanosecond granularity from the input parameters
*/
public static DateTime of(
int year,
int month,
int day,
int hour,
int minute,
int second,
int nanos,
ZoneOffset offset,
final int fractionDigits
) {
return new DateTime(year, month, day, hour, minute, second, nanos, offset, fractionDigits);
}

/**
* Create a new instance with year granularity from the input parameters
*/
public static DateTime ofYear(int year) {
return new DateTime(year, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC, 0);
}

/**
* Create a new instance with year-month granularity from the input parameters
*/
public static DateTime ofYearMonth(int years, int months) {
return new DateTime(years, months, 1, 0, 0, 0, 0, ZoneOffset.UTC, 0);
}

/**
* Create a new instance with day granularity from the input parameters
*/
public static DateTime ofDate(int years, int months, int days) {
return new DateTime(years, months, days, 0, 0, 0, 0, ZoneOffset.UTC, 0);
}

private int assertSize(int value, int min, int max, ChronoField field) {
if (value > max) {
throw new DateTimeException("Field " + field.name() + " out of bounds. Expected " + min + "-" + max + ", got " + value);
}
return value;
}

public int getYear() {
return year;

Check warning on line 114 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L114

Added line #L114 was not covered by tests
}

public int getMonth() {
return month;

Check warning on line 118 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L118

Added line #L118 was not covered by tests
}

public int getDayOfMonth() {
return day;

Check warning on line 122 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L122

Added line #L122 was not covered by tests
}

public int getHour() {
return hour;

Check warning on line 126 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L126

Added line #L126 was not covered by tests
}

public int getMinute() {
return minute;

Check warning on line 130 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L130

Added line #L130 was not covered by tests
}

public int getSecond() {
return second;

Check warning on line 134 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L134

Added line #L134 was not covered by tests
}

public int getNano() {
return nano;

Check warning on line 138 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L138

Added line #L138 was not covered by tests
}

/**
* Returns the time offset, if available
*
* @return the time offset, if available
*/
public Optional<ZoneOffset> getOffset() {
return Optional.ofNullable(offset);

Check warning on line 147 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L147

Added line #L147 was not covered by tests
}

/**
* Creates an {@link OffsetDateTime}
*
* @return the {@link OffsetDateTime}
*/
public OffsetDateTime toOffsetDatetime() {
if (offset != null) {
return OffsetDateTime.of(year, month, day, hour, minute, second, nano, offset);
}
throw new DateTimeException("No zone offset information found");
}

/**
* * @hidden
*/
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;

Check warning on line 168 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L168

Added line #L168 was not covered by tests
}
if (o == null || getClass() != o.getClass()) {
return false;

Check warning on line 171 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L171

Added line #L171 was not covered by tests
}
DateTime dateTime = (DateTime) o;

Check warning on line 173 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L173

Added line #L173 was not covered by tests
return year == dateTime.year
&& month == dateTime.month
&& day == dateTime.day
&& hour == dateTime.hour
&& minute == dateTime.minute
&& second == dateTime.second
&& nano == dateTime.nano
&& fractionDigits == dateTime.fractionDigits
&& Objects.equals(offset, dateTime.offset);
}

/**
* @hidden
*/
@Override
public int hashCode() {
return Objects.hash(year, month, day, hour, minute, second, nano, offset, fractionDigits);

Check warning on line 190 in server/src/main/java/org/opensearch/common/time/DateTime.java

View check run for this annotation

Codecov / codecov/patch

server/src/main/java/org/opensearch/common/time/DateTime.java#L190

Added line #L190 was not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
*/
public enum FormatNames {
ISO8601(null, "iso8601"),
RFC3339(null, "rfc3339"),
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 ad35665

Please sign in to comment.