2019-06-03 13:22:45 -07:00
|
|
|
[[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
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
Datetimes in Painless are most commonly represented as a numeric value, a
|
|
|
|
string value, or a complex value.
|
|
|
|
|
|
|
|
numeric:: a datetime representation as a number from a starting offset called
|
|
|
|
an epoch; in Painless this is typically a <<primitive-types, long>> as
|
|
|
|
milliseconds since an epoch of 1970-01-01 00:00:00 Zulu Time
|
|
|
|
string:: a datetime representation as a sequence of characters defined by
|
|
|
|
a standard format or a custom format; in Painless this is typically a
|
|
|
|
<<string-type, String>> of the standard format
|
|
|
|
https://en.wikipedia.org/wiki/ISO_8601[ISO 8601]
|
|
|
|
complex:: a datetime representation as a complex type
|
|
|
|
(<<reference-types, object>>) that abstracts away internal details of how the
|
|
|
|
datetime is stored and often provides utilities for modification and
|
|
|
|
comparison; in Painless this is typically a
|
|
|
|
<<painless-api-reference-shared-ZonedDateTime>>
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
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
|
2019-06-05 10:20:46 -07:00
|
|
|
numeric or string datetime to a complex datetime, modify or compare the complex
|
|
|
|
datetime, and then switch it back to a numeric or string datetime for storage
|
|
|
|
or to return a result.
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
==== Datetime Parsing and Formatting
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
Datetime parsing is a switch from a string datetime to a complex datetime, and
|
|
|
|
datetime formatting is a switch from a complex datetime to a string datetime.
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
A <<painless-api-reference-shared-DateTimeFormatter, DateTimeFormatter>> is a
|
2019-06-05 10:20:46 -07:00
|
|
|
complex type (<<reference-types, object>>) that defines the allowed sequence
|
|
|
|
of characters for a string datetime. Datetime parsing and formatting often
|
|
|
|
requires a DateTimeFormatter. For more information about how to use a
|
|
|
|
DateTimeFormatter see the
|
2019-06-03 13:22:45 -07:00
|
|
|
{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
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
* format to ISO 8601
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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.
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* format to a custom format
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
Datetime conversion is a switch from a numeric datetime to a complex datetime
|
|
|
|
and vice versa.
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
===== 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
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
Datetime representations often contain the data to extract individual datetime
|
|
|
|
pieces such as year, hour, timezone, etc. Use individual pieces of a datetime
|
|
|
|
to create a complex datetime, and use a complex datetime to extract individual
|
|
|
|
pieces.
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
===== Datetime Pieces Examples
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
* create a complex datetime from pieces
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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'));
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* extract pieces from a complex datetime
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
Use either a numeric datetime or a complex datetime to do 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 numeric datetime. Use
|
|
|
|
<<painless-api-reference-shared-ZonedDateTime, methods>> (or fields) to modify
|
|
|
|
a complex datetime. Note many complex datetimes are immutable so upon
|
|
|
|
modification a new complex datetime is created that requires
|
|
|
|
<<variable-assignment, assignment>> or immediate use.
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
===== Datetime Modification Examples
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
* Subtract three seconds from a numeric datetime in milliseconds
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[source,Painless]
|
|
|
|
----
|
|
|
|
long milliSinceEpoch = 434931330000L;
|
|
|
|
milliSinceEpoch = milliSinceEpoch - 1000L*3L;
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* Add three days to a complex datetime
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[source,Painless]
|
|
|
|
----
|
|
|
|
ZonedDateTime zdt =
|
|
|
|
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
|
ZonedDateTime updatedZdt = zdt.plusDays(3);
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* Subtract 125 minutes from a complex datetime
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[source,Painless]
|
|
|
|
----
|
|
|
|
ZonedDateTime zdt =
|
|
|
|
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
|
ZonedDateTime updatedZdt = zdt.minusMinutes(125);
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* Set the year on a complex datetime
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[source,Painless]
|
|
|
|
----
|
|
|
|
ZonedDateTime zdt =
|
|
|
|
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
|
ZonedDateTime updatedZdt = zdt.withYear(1976);
|
|
|
|
----
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
==== Datetime Difference (Elapsed Time)
|
2019-06-03 13:22:45 -07:00
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
Use either two numeric datetimes or two complex datetimes to calculate the
|
|
|
|
difference (elapsed time) between two different datetimes. Use
|
|
|
|
<<subtraction-operator, subtraction>> to calculate the difference between
|
|
|
|
between two numeric datetimes of the same time unit such as milliseconds. For
|
|
|
|
complex datetimes there is often a method or another complex type
|
|
|
|
(<<reference-types, object>>) available to calculate the difference. Use
|
|
|
|
<<painless-api-reference-shared-ChronoUnit, ChronoUnit>>
|
|
|
|
to calculate the difference between two complex datetimes if supported.
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
===== Elapsed Time Examples
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
* Difference in milliseconds between two numeric datetimes
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[source,Painless]
|
|
|
|
----
|
|
|
|
long startTimestamp = 434931327000L;
|
|
|
|
long endTimestamp = 434931330000L;
|
|
|
|
long differenceInMillis = endTimestamp - startTimestamp;
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* Difference in milliseconds between two complex datetimes
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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);
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* Difference in days between two complex datetimes
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
Use either two numeric datetimes or two complex datetimes to do a datetime
|
|
|
|
comparison. Use standard <<painless-operators-boolean, comparison operators>>
|
|
|
|
to compare two numeric datetimes of the same time unit such as milliseconds.
|
|
|
|
For complex datetimes there is often a method or another complex type
|
|
|
|
(<<reference-types, object>>) available to do the comparison.
|
2019-06-03 13:22:45 -07:00
|
|
|
|
|
|
|
===== Datetime Comparison Examples
|
|
|
|
|
2019-06-05 10:20:46 -07:00
|
|
|
* Greater than comparison of two numeric datetimes in milliseconds
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[source,Painless]
|
|
|
|
----
|
|
|
|
long timestamp1 = 434931327000L;
|
|
|
|
long timestamp2 = 434931330000L;
|
|
|
|
|
|
|
|
if (timestamp1 > timestamp2) {
|
|
|
|
// handle condition
|
|
|
|
}
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* Equality comparision of two complex datetimes
|
|
|
|
+
|
|
|
|
[source,Painless]
|
|
|
|
----
|
|
|
|
ZonedDateTime zdt1 =
|
|
|
|
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
|
ZonedDateTime zdt2 =
|
|
|
|
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
|
|
|
|
|
|
|
|
if (zdt1.equals(zdt2)) {
|
|
|
|
// handle condition
|
|
|
|
}
|
|
|
|
----
|
|
|
|
+
|
|
|
|
* Less than comparision of two complex datetimes
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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
|
|
|
|
}
|
|
|
|
----
|
|
|
|
+
|
2019-06-05 10:20:46 -07:00
|
|
|
* Greater than comparision of two complex datetimes
|
2019-06-03 13:22:45 -07:00
|
|
|
+
|
|
|
|
[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
|
|
|
|
}
|
|
|
|
----
|