All Downloads are FREE. Search and download functionalities are using the official Maven repository.

co.elastic.clients.util.DateTime Maven / Gradle / Ivy

/*
 * Licensed to Elasticsearch B.V. under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch B.V. licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package co.elastic.clients.util;

import co.elastic.clients.json.JsonpDeserializable;
import co.elastic.clients.json.JsonpDeserializer;
import co.elastic.clients.json.JsonpDeserializerBase;
import co.elastic.clients.json.JsonpMapper;
import co.elastic.clients.json.JsonpSerializable;
import jakarta.json.stream.JsonGenerator;
import jakarta.json.stream.JsonParser;

import javax.annotation.Nullable;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.util.EnumSet;
import java.util.Locale;

/**
 * A date-time that can be represented either as a string or a number of milliseconds since the Epoch.
 * 

* The string for can also be used to represent date-math expressions where applicable. */ @JsonpDeserializable public class DateTime implements JsonpSerializable { private final long millis; @Nullable private final String str; // Visible for testing @Nullable final DateTimeFormatter formatter; private DateTime(long epochMillis, String str, DateTimeFormatter format) { this.millis = epochMillis; this.str = str; this.formatter = format; } /** * Create a new date-time from Epoch milliseconds. It will be serialized to JSON as a string. * * @param epochMilli the timestamp * @param format the format used to format the date-time as a JSON string */ public static DateTime ofEpochMilli(long epochMilli, DateTimeFormatter format) { return new DateTime(epochMilli, null, format); } /** * Create a new date-time from Epoch milliseconds. It will be serialized to JSON as a number. * * @param epochMilli the timestamp */ public static DateTime ofEpochMilli(long epochMilli) { return ofEpochMilli(epochMilli, null); } /** * Create a new date-time or a date-math expression from a string. It will be serialized to JSON as is, * conversion to an Instant will use the default parsers. * * @param text the date-time as a string, or a date-math expression. If a date-math expression, * the result will fail to be converted to another type. */ public static DateTime of(String text) { return of(text, null); } /** * Create a new date-time from a string and parser. It will be serialized to JSON as is. * * @param text the date-time as a string * @param parser the parser used to convert the date-time to an Instant */ public static DateTime of(String text, DateTimeFormatter parser) { return new DateTime(0, text, parser); } /** * Create a new date-time from a Temporal object. It will be serialized to JSON as milliseconds since the Epoch. * * @param instant the date-time */ public static DateTime of(Temporal instant) { return of(instant, null); } /** * Create a new date-time from a Temporal object. It will be serialized to JSON as a string. * * @param instant the date-time * @param format the format used to convert to a JSON string */ public static DateTime of(Temporal instant, DateTimeFormatter format) { long millis = instant.getLong(ChronoField.INSTANT_SECONDS)*1000L + instant.getLong(ChronoField.MILLI_OF_SECOND); return new DateTime(millis, null, format); } /** * Get the string that was used to create this date-time, or null * if it was created with a number of milliseconds. */ @Nullable public String getString() { return str; } /** * Get the formatter associated with this date-time, if any. */ @Nullable DateTimeFormatter getFormatter() { return formatter; } /** * Converts this object to an Instant. * * @throws DateTimeParseException if this object was created from a string which can not be parsed */ public Instant toInstant() { if (str == null) { return Instant.ofEpochMilli(millis); } else { if (formatter == null) { try { ZonedDateTime zdt = DateTimeUtil.from( DateTimeUtil.STRICT_DATE_OPTIONAL_TIME_FORMATTER.parse(str), Locale.ROOT, ZoneOffset.UTC ); return zdt.toInstant(); } catch(DateTimeParseException dtpe) { // Ignore } // Try milliseconds as string try { long ms = Long.parseLong(str); return Instant.ofEpochMilli(ms); } catch(NumberFormatException nfe) { throw new DateTimeParseException( "Cannot parse date-time with format [strict_date_optional_time||epoch_millis]", str, 0 ); } } else { return formatter.parse(str, Instant::from); } } } /** * Converts this object to an Instant, using a given format. * * @param parser the parser to use if this object was created from a string * @throws DateTimeParseException if this object was created from a string which can not be parsed */ public Instant toInstant(DateTimeFormatter parser) { if (str == null) { return Instant.ofEpochMilli(millis); } else { return parser.parse(str, Instant::from); } } /** * Converts this object to an ZonedDateTime. * * @throws DateTimeParseException if this object was created from a string which can not be parsed */ public ZonedDateTime toZonedDateTime() { if (str == null) { return ZonedDateTime.ofInstant(toInstant(), ZoneOffset.UTC); } else { try { return DateTimeUtil.from( DateTimeUtil.STRICT_DATE_OPTIONAL_TIME_FORMATTER.parse(str), Locale.ROOT, ZoneOffset.UTC ); } catch(DateTimeParseException dtpe) { // Ignore } // Try milliseconds as string try { long ms = Long.parseLong(str); return ZonedDateTime.ofInstant(Instant.ofEpochMilli(ms), ZoneOffset.UTC); } catch(NumberFormatException nfe) { throw new DateTimeParseException("Cannot parse date-time with format [strict_date_optional_time||epoch_millis]", str, 0); } } } /** * Converts this object to an ZonedDateTime, using a given format. * * @param parser the parser to use if this object was created from a string * @throws DateTimeParseException if this object was created from a string which can not be parsed */ public ZonedDateTime toZonedDateTime(DateTimeFormatter parser) { if (str == null) { return ZonedDateTime.ofInstant(toInstant(), ZoneOffset.UTC); } else { return parser.parse(str, ZonedDateTime::from); } } /** * Get the milliseconds since the Epoch for represented by this object. If it was created from a string, * it is first converted using {@link #toInstant()}. * * @throws DateTimeParseException if this object was created from a string which can not be parsed */ public long toEpochMilli() { if (str == null) { return millis; } else { return toInstant().toEpochMilli(); } } /** * Get the milliseconds since the Epoch for represented by this object. If it was created from a string, * it is first converted using {@link #toInstant(DateTimeFormatter)}. * * @param format the parser to use if this object was created from a string * @throws DateTimeParseException if this object was created from a string which can not be parsed */ public long toEpochMilli(DateTimeFormatter format) { if (str == null) { return millis; } else { return toInstant(format).toEpochMilli(); } } @Override public void serialize(JsonGenerator generator, JsonpMapper mapper) { if (str == null) { if (formatter == null) { generator.write(millis); } else { generator.write(formatter.format(Instant.ofEpochMilli(millis).atZone(ZoneOffset.UTC))); } } else { generator.write(str); } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; return this.toInstant().equals(((DateTime) o).toInstant()); } @Override public int hashCode() { return toInstant().hashCode(); } @Override public String toString() { if (str == null) { if (formatter == null) { return String.valueOf(millis); } else { return formatter.format(Instant.ofEpochMilli(millis).atZone(ZoneOffset.UTC)); } } else { return str; } } public static JsonpDeserializer _DESERIALIZER = new TimestampDeserializer(); private static class TimestampDeserializer extends JsonpDeserializerBase { TimestampDeserializer() { super(EnumSet.of(JsonParser.Event.VALUE_NUMBER, JsonParser.Event.VALUE_STRING)); } @Override public DateTime deserialize(JsonParser parser, JsonpMapper mapper, JsonParser.Event event) { if (event == JsonParser.Event.VALUE_NUMBER) { return DateTime.ofEpochMilli(parser.getLong()); } else { return DateTime.of(parser.getString()); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy