OpenSearch/docs/painless/painless-guide/painless-datetime.asciidoc
Jack Conradson 790d2124f6 Clean Up Painless Datetime Docs (#42869)
This change abstracts the specific types away from the different 
representations of datetime as a datetime representation in code can be all 
kinds of different things. This defines the three most common types of 
datetimes as numeric, string, and complex while outlining the type most 
typically used for these as long, String, and ZonedDateTime, respectively. 
Documentation uses the definitions while examples use the types. This makes 
the documentation easier to consume especially for people from a non-Java 
background.
2019-06-05 10:22:00 -07:00

337 lines
10 KiB
Plaintext

[[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 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>>
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
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.
==== Datetime Parsing and Formatting
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.
A <<painless-api-reference-shared-DateTimeFormatter, DateTimeFormatter>> is a
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
{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 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 custom format
+
[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 numeric datetime to a complex datetime
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
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.
===== Datetime Pieces Examples
* create a complex datetime 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 complex datetime
+
[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 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.
===== Datetime Modification Examples
* Subtract three seconds from a numeric datetime in milliseconds
+
[source,Painless]
----
long milliSinceEpoch = 434931330000L;
milliSinceEpoch = milliSinceEpoch - 1000L*3L;
----
+
* Add three days to a complex 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 complex 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 complex datetime
+
[source,Painless]
----
ZonedDateTime zdt =
ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
ZonedDateTime updatedZdt = zdt.withYear(1976);
----
==== Datetime Difference (Elapsed Time)
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.
===== Elapsed Time Examples
* Difference in milliseconds between two numeric datetimes
+
[source,Painless]
----
long startTimestamp = 434931327000L;
long endTimestamp = 434931330000L;
long differenceInMillis = endTimestamp - startTimestamp;
----
+
* Difference in milliseconds between two complex 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);
----
+
* Difference in days between two complex 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 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.
===== Datetime Comparison Examples
* Greater than comparison of two numeric datetimes in milliseconds
+
[source,Painless]
----
long timestamp1 = 434931327000L;
long timestamp2 = 434931330000L;
if (timestamp1 > timestamp2) {
// handle condition
}
----
+
* 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
+
[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
}
----
+
* Greater than 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, 17, 22, 15, 35, 0, ZoneId.of('Z'));
if (zdt1.isAfter(zdt2)) {
// handle condition
}
----