|
@@ -0,0 +1,320 @@
|
|
|
+[[painless-datetime]]
|
|
|
+=== Using Datetime in Painless
|
|
|
+
|
|
|
+==== Datetime API
|
|
|
+
|
|
|
+Datetimes in Painless use the standard Java libraries and are available through
|
|
|
+the Painless <<painless-api-reference-shared, Shared API>>. Most of the classes
|
|
|
+from the following Java packages are available to use in Painless scripts:
|
|
|
+
|
|
|
+* <<painless-api-reference-shared-java-time, java.time>>
|
|
|
+* <<painless-api-reference-shared-java-time-chrono, java.time.chrono>>
|
|
|
+* <<painless-api-reference-shared-java-time-format, java.time.format>>
|
|
|
+* <<painless-api-reference-shared-java-time-temporal, java.time.temporal>>
|
|
|
+* <<painless-api-reference-shared-java-time-zone, java.time.zone>>
|
|
|
+
|
|
|
+==== Datetime Representation
|
|
|
+
|
|
|
+Datetimes in Painless are most commonly represented as a
|
|
|
+<<primitive-types, long>>, a <<string-type, String>>, or a
|
|
|
+<<painless-api-reference-shared-ZonedDateTime, ZonedDateTime>>.
|
|
|
+
|
|
|
+long:: represents a datetime as the number of milliseconds or nanoseconds since
|
|
|
+epoch (1970-01-01T00:00:00Z)
|
|
|
+String:: represents a datetime as a sequence of characters defined by a
|
|
|
+well-known standard such as https://en.wikipedia.org/wiki/ISO_8601[ISO 8601] or
|
|
|
+defined by the source of input in a custom way
|
|
|
+ZonedDateTime:: a <<reference-types, reference type>> (object) that contains an
|
|
|
+internal representation of a datetime and provides numerous
|
|
|
+<<painless-api-reference-shared-ZonedDateTime, methods>> for
|
|
|
+modification and comparison.
|
|
|
+
|
|
|
+Switching between different representations of datetimes is often necessary to
|
|
|
+achieve a script's objective(s). A typical pattern in a script is to switch a
|
|
|
+long or String representation of a datetime to a ZonedDateTime representation,
|
|
|
+modify or compare the ZonedDateTime representation, and then switch it back to
|
|
|
+a long or String representation for storage or as a returned result.
|
|
|
+
|
|
|
+==== Datetime Parsing and Formatting
|
|
|
+
|
|
|
+Datetime parsing is a switch from a String representation to a ZonedDateTime
|
|
|
+representation, and datetime formatting is a switch from a ZonedDateTime
|
|
|
+representation to a String representation.
|
|
|
+
|
|
|
+A <<painless-api-reference-shared-DateTimeFormatter, DateTimeFormatter>> is a
|
|
|
+<<reference-types, reference type>> (object) that defines the allowed sequence
|
|
|
+of characters for a String representation of a datetime. Datetime parsing and
|
|
|
+formatting often requires a DateTimeFormatter. For more information about how
|
|
|
+to use a DateTimeFormatter see the
|
|
|
+{java11-javadoc}/java.base/java/time/format/DateTimeFormatter.html[Java documentation].
|
|
|
+
|
|
|
+===== Datetime Parsing Examples
|
|
|
+
|
|
|
+* parse from milliseconds
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+String milliSinceEpochString = "434931330000";
|
|
|
+long milliSinceEpoch = Long.parseLong(milliSinceEpochString);
|
|
|
+Instant instant = Instant.ofEpochMilli(milliSinceEpoch);
|
|
|
+ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
|
|
|
+----
|
|
|
++
|
|
|
+* parse from ISO 8601
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+String datetime = '1983-10-13T22:15:30Z';
|
|
|
+ZonedDateTime zdt = ZonedDateTime.parse(datetime);
|
|
|
+----
|
|
|
+Note the parse method uses ISO 8601 by default.
|
|
|
++
|
|
|
+* parse from RFC 1123
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+String datetime = 'Thu, 13 Oct 1983 22:15:30 GMT';
|
|
|
+ZonedDateTime zdt = ZonedDateTime.parse(datetime,
|
|
|
+ DateTimeFormatter.RFC_1123_DATE_TIME);
|
|
|
+----
|
|
|
+Note the use of a built-in DateTimeFormatter.
|
|
|
++
|
|
|
+* parse from a custom format
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+String datetime = 'custom y 1983 m 10 d 13 22:15:30 Z';
|
|
|
+DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
|
|
|
+ "'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV");
|
|
|
+ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf);
|
|
|
+----
|
|
|
+Note the use of a custom DateTimeFormatter.
|
|
|
+
|
|
|
+===== Datetime Formatting Examples
|
|
|
+
|
|
|
+* format to a String (ISO 8601)
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+String datetime = zdt.format(DateTimeFormatter.ISO_INSTANT);
|
|
|
+----
|
|
|
+Note the use of a built-in DateTimeFormatter.
|
|
|
++
|
|
|
+* format to a String (custom)
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
|
|
|
+ "'date:' yyyy/MM/dd 'time:' HH:mm:ss");
|
|
|
+String datetime = zdt.format(dtf);
|
|
|
+----
|
|
|
+Note the use of a custom DateTimeFormatter.
|
|
|
+
|
|
|
+==== Datetime Conversion
|
|
|
+
|
|
|
+Datetime conversion is a switch from a long representation to a ZonedDateTime
|
|
|
+representation and vice versa.
|
|
|
+
|
|
|
+===== Datetime Conversion Examples
|
|
|
+
|
|
|
+* convert from milliseconds
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+long milliSinceEpoch = 434931330000L;
|
|
|
+Instant instant = Instant.ofEpochMilli(milliSinceEpoch);
|
|
|
+ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
|
|
|
+----
|
|
|
++
|
|
|
+* convert to milliseconds
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+-----
|
|
|
+ZonedDateTime zdt =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+long milliSinceEpoch = zdt.toInstant().toEpochMilli();
|
|
|
+-----
|
|
|
+
|
|
|
+==== Datetime Pieces
|
|
|
+
|
|
|
+Use the ZonedDateTime
|
|
|
+<<painless-api-reference-shared-ZonedDateTime, method of>> to create a new
|
|
|
+ZonedDateTime from pieces (year, month, day, hour, minute, second, nano,
|
|
|
+time zone). Use ZonedDateTime
|
|
|
+<<painless-api-reference-shared-ZonedDateTime, methods>> to extract pieces from
|
|
|
+a ZonedDateTime.
|
|
|
+
|
|
|
+===== Datetime Pieces Examples
|
|
|
+
|
|
|
+* create a ZonedDateTime from pieces
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+int year = 1983;
|
|
|
+int month = 10;
|
|
|
+int day = 13;
|
|
|
+int hour = 22;
|
|
|
+int minutes = 15;
|
|
|
+int seconds = 30;
|
|
|
+int nanos = 0;
|
|
|
+ZonedDateTime zdt = ZonedDateTime.of(
|
|
|
+ year, month, day, hour, minutes, seconds, nanos, ZoneId.of('Z'));
|
|
|
+----
|
|
|
++
|
|
|
+* extract pieces from a ZonedDateTime
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 100, ZoneId.of(tz));
|
|
|
+int year = zdt.getYear();
|
|
|
+int month = zdt.getMonthValue();
|
|
|
+int day = zdt.getDayOfMonth();
|
|
|
+int hour = zdt.getHour();
|
|
|
+int minutes = zdt.getMinute();
|
|
|
+int seconds = zdt.getSecond();
|
|
|
+int nanos = zdt.getNano();
|
|
|
+----
|
|
|
+
|
|
|
+==== Datetime Modification
|
|
|
+
|
|
|
+Use either a long or a ZonedDateTime to do datetime modification such as adding
|
|
|
+several seconds to a datetime or subtracting several days from a datetime. Use
|
|
|
+standard <<painless-operators-numeric, numeric operators>> to modify a long
|
|
|
+representation of a datetime. Use ZonedDateTime
|
|
|
+<<painless-api-reference-shared-ZonedDateTime, methods>> to modify a
|
|
|
+ZonedDateTime representation of a datetime. Note most modification methods for
|
|
|
+a ZonedDateTime return a new instance for assignment or immediate use.
|
|
|
+
|
|
|
+===== Datetime Modification Examples
|
|
|
+
|
|
|
+* Subtract three seconds from milliseconds
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+long milliSinceEpoch = 434931330000L;
|
|
|
+milliSinceEpoch = milliSinceEpoch - 1000L*3L;
|
|
|
+----
|
|
|
++
|
|
|
+* Add three days to a datetime
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+ZonedDateTime updatedZdt = zdt.plusDays(3);
|
|
|
+----
|
|
|
++
|
|
|
+* Subtract 125 minutes from a datetime
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+ZonedDateTime updatedZdt = zdt.minusMinutes(125);
|
|
|
+----
|
|
|
++
|
|
|
+* Set the year on a datetime
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+ZonedDateTime updatedZdt = zdt.withYear(1976);
|
|
|
+----
|
|
|
+
|
|
|
+==== Elapsed Time
|
|
|
+
|
|
|
+Use either two longs or two ZonedDateTimes to calculate an elapsed
|
|
|
+time (difference) between two datetimes. Use
|
|
|
+<<subtraction-operator, subtraction>> to calculate an elapsed time
|
|
|
+between two longs of the same time unit such as milliseconds. For more complex
|
|
|
+datetimes. use <<painless-api-reference-shared-ChronoUnit, ChronoUnit>> to
|
|
|
+calculate the difference between two ZonedDateTimes.
|
|
|
+
|
|
|
+===== Elapsed Time Examples
|
|
|
+
|
|
|
+* Elapsed time for two millisecond datetimes
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+long startTimestamp = 434931327000L;
|
|
|
+long endTimestamp = 434931330000L;
|
|
|
+long differenceInMillis = endTimestamp - startTimestamp;
|
|
|
+----
|
|
|
++
|
|
|
+* Elapsed time in milliseconds for two datetimes
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt1 =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 11000000, ZoneId.of('Z'));
|
|
|
+ZonedDateTime zdt2 =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 35, 0, ZoneId.of('Z'));
|
|
|
+long differenceInMillis = ChronoUnit.MILLIS.between(zdt1, zdt2);
|
|
|
+----
|
|
|
++
|
|
|
+* Elapsed time in days for two datetimes
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt1 =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 11000000, ZoneId.of('Z'));
|
|
|
+ZonedDateTime zdt2 =
|
|
|
+ ZonedDateTime.of(1983, 10, 17, 22, 15, 35, 0, ZoneId.of('Z'));
|
|
|
+long differenceInDays = ChronoUnit.DAYS.between(zdt1, zdt2);
|
|
|
+----
|
|
|
+
|
|
|
+==== Datetime Comparison
|
|
|
+
|
|
|
+Use either two longs or two ZonedDateTimes to do a datetime comparison. Use
|
|
|
+standard <<painless-operators-boolean, comparison operators>> to compare two
|
|
|
+longs of the same time unit such as milliseconds. For more complex datetimes,
|
|
|
+use ZonedDateTime <<painless-api-reference-shared-ZonedDateTime, methods>> to
|
|
|
+compare two ZonedDateTimes.
|
|
|
+
|
|
|
+===== Datetime Comparison Examples
|
|
|
+
|
|
|
+* Comparison of two millisecond datetimes
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+long timestamp1 = 434931327000L;
|
|
|
+long timestamp2 = 434931330000L;
|
|
|
+
|
|
|
+if (timestamp1 > timestamp2) {
|
|
|
+ // handle condition
|
|
|
+}
|
|
|
+----
|
|
|
++
|
|
|
+* Before comparision of two datetimes
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt1 =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+ZonedDateTime zdt2 =
|
|
|
+ ZonedDateTime.of(1983, 10, 17, 22, 15, 35, 0, ZoneId.of('Z'));
|
|
|
+
|
|
|
+if (zdt1.isBefore(zdt2)) {
|
|
|
+ // handle condition
|
|
|
+}
|
|
|
+----
|
|
|
++
|
|
|
+* After comparision of two datetimes
|
|
|
++
|
|
|
+[source,Painless]
|
|
|
+----
|
|
|
+ZonedDateTime zdt1 =
|
|
|
+ ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
+ZonedDateTime zdt2 =
|
|
|
+ ZonedDateTime.of(1983, 10, 17, 22, 15, 35, 0, ZoneId.of('Z'));
|
|
|
+
|
|
|
+if (zdt1.isAfter(zdt2)) {
|
|
|
+ // handle condition
|
|
|
+}
|
|
|
+----
|