Browse Source

Add timezone documentation for Painless datetimes (#43768)

Jack Conradson 6 years ago
parent
commit
c1acc6931d

+ 48 - 13
docs/painless/painless-guide/painless-datetime.asciidoc

@@ -29,7 +29,7 @@ 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>>
+<<painless-api-reference-shared-ZonedDateTime, 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
@@ -335,6 +335,43 @@ if (zdt1.isAfter(zdt2)) {
 }
 ----
 
+==== Datetime Zone
+
+Both string datetimes and complex datetimes have a timezone with a default of
+`UTC`. Numeric datetimes do not have enough explicit information to
+have a timezone, so `UTC` is always assumed. Use
+<<painless-api-reference-shared-ZonedDateTime, methods>> (or fields) in
+conjunction with a <<painless-api-reference-shared-ZoneId, ZoneId>> to change
+the timezone for a complex datetime. Parse a string datetime into a complex
+datetime to change the timezone, and then format the complex datetime back into
+a desired string 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 Zone Examples
+
+* Modify the timezone for a complex datetime
++
+[source,Painless]
+----
+ZonedDateTime utc =
+        ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));
+ZonedDateTime pst = utc.withZoneSameInstant(ZoneId.of('America/Los_Angeles'));
+----
++
+* Modify the timezone for a string datetime
++
+[source,Painless]
+----
+String gmtString = 'Thu, 13 Oct 1983 22:15:30 GMT';
+ZonedDateTime gmtZdt = ZonedDateTime.parse(gmtString,
+        DateTimeFormatter.RFC_1123_DATE_TIME); <1>
+ZonedDateTime pstZdt =
+        gmtZdt.withZoneSameInstant(ZoneId.of('America/Los_Angeles'));
+String pstString = pstZdt.format(DateTimeFormatter.RFC_1123_DATE_TIME);
+----
+<1> Note the use of a built-in DateTimeFormatter.
+
 ==== Datetime Input
 
 There are several common ways datetimes are used as input for a script
@@ -513,10 +550,9 @@ String output = input.format(DateTimeFormatter.ISO_INSTANT); <1>
 +
 ** Assumptions:
 +
-*** The fields `start_datetime` and `end_datetime` may *not* exist in all
-indexes as part of the query
-*** The fields `start_datetime` and `end_datetime` may *not* have values in all
-indexed documents
+*** The fields `start` and `end` may *not* exist in all indexes as part of the
+query
+*** The fields `start` and `end` may *not* have values in all indexed documents
 +
 ** Mappings:
 +
@@ -527,10 +563,10 @@ indexed documents
         ...
         "properties": {
             ...
-            "start_datetime": {
+            "start": {
                 "type": "date"
             },
-            "end_datetime": {
+            "end": {
                 "type": "date"
             }
             ...
@@ -544,14 +580,13 @@ indexed documents
 +
 [source,Painless]
 ----
-if (doc.containsKey('start_datetime') && doc.containsKey('end_datetime')) { <1>
+if (doc.containsKey('start') && doc.containsKey('end')) { <1>
 
-    if (doc['start_datetime'].size() > 0 && doc['end_datetime'].size() > 0) { <2>
+    if (doc['start'].size() > 0 && doc['end'].size() > 0) { <2>
 
-        def startDatetime = doc['start_datetime'].value;
-        def endDatetime = doc['end_datetime'].value;
-        long differenceInMillis =
-            ChronoUnit.MILLIS.between(startDateTime, endDateTime);
+        def start = doc['start'].value;
+        def end = doc['end'].value;
+        long differenceInMillis = ChronoUnit.MILLIS.between(start, end);
 
         // handle difference in times
     } else {

+ 15 - 1
modules/lang-painless/src/test/java/org/elasticsearch/painless/DateTests.java → modules/lang-painless/src/test/java/org/elasticsearch/painless/DateTimeTests.java

@@ -22,7 +22,7 @@ package org.elasticsearch.painless;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 
-public class DateTests extends ScriptTestCase {
+public class DateTimeTests extends ScriptTestCase {
 
     public void testLongToZonedDateTime() {
         assertEquals(ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of("Z")), exec(
@@ -177,4 +177,18 @@ public class DateTests extends ScriptTestCase {
                 "return zdt1.isAfter(zdt2);"
         ));
     }
+
+    public void testTimeZone() {
+        assertEquals(ZonedDateTime.of(1983, 10, 13, 15, 15, 30, 0, ZoneId.of("America/Los_Angeles")), exec(
+                "ZonedDateTime utc = ZonedDateTime.of(1983, 10, 13, 22, 15, 30, 0, ZoneId.of('Z'));" +
+                "return utc.withZoneSameInstant(ZoneId.of('America/Los_Angeles'));"));
+
+        assertEquals("Thu, 13 Oct 1983 15:15:30 -0700", exec(
+                "String gmtString = 'Thu, 13 Oct 1983 22:15:30 GMT';" +
+                "ZonedDateTime gmtZdt = ZonedDateTime.parse(gmtString," +
+                "DateTimeFormatter.RFC_1123_DATE_TIME);" +
+                "ZonedDateTime pstZdt =" +
+                "gmtZdt.withZoneSameInstant(ZoneId.of('America/Los_Angeles'));" +
+                "return pstZdt.format(DateTimeFormatter.RFC_1123_DATE_TIME);"));
+    }
 }