@@ -541,7 +541,7 @@ document is most commonly accessible through an input called `doc`.
541541+
542542[source,Painless]
543543----
544- def input = doc['input_datetime'].value;
544+ ZonedDateTime input = doc['input_datetime'].value;
545545String output = input.format(DateTimeFormatter.ISO_INSTANT); <1>
546546----
547547<1> Note the use of a built-in DateTimeFormatter.
@@ -584,8 +584,8 @@ if (doc.containsKey('start') && doc.containsKey('end')) { <1>
584584
585585 if (doc['start'].size() > 0 && doc['end'].size() > 0) { <2>
586586
587- def start = doc['start'].value;
588- def end = doc['end'].value;
587+ ZonedDateTime start = doc['start'].value;
588+ ZonedDateTime end = doc['end'].value;
589589 long differenceInMillis = ChronoUnit.MILLIS.between(start, end);
590590
591591 // handle difference in times
@@ -660,7 +660,7 @@ preferred as there is no need to parse it for comparision.
660660[source,Painless]
661661----
662662long now = params['now'];
663- def inputDateTime = doc['input_datetime'];
663+ ZonedDateTime inputDateTime = doc['input_datetime'];
664664long millisDateTime = zdt.toInstant().toEpochMilli();
665665long elapsedTime = now - millisDateTime;
666666----
@@ -712,9 +712,194 @@ long elapsedTime = now - millisDateTime;
712712String nowString = params['now'];
713713ZonedDateTime nowZdt = ZonedDateTime.parse(datetime); <1>
714714long now = ZonedDateTime.toInstant().toEpochMilli();
715- def inputDateTime = doc['input_datetime'];
715+ ZonedDateTime inputDateTime = doc['input_datetime'];
716716long millisDateTime = zdt.toInstant().toEpochMilli();
717717long elapsedTime = now - millisDateTime;
718718----
719719<1> Note this parses the same string datetime every time the script runs. Use a
720720numeric datetime to avoid a significant performance hit.
721+
722+ ==== Datetime Examples in Contexts
723+
724+ ===== Load the Example Data
725+
726+ Run the following curl commands to load the data necessary for the context
727+ examples into an Elasticsearch cluster:
728+
729+ . Create {ref}/mapping.html[mappings] for the sample data.
730+ +
731+ [source,js]
732+ ----
733+ PUT /messages
734+ {
735+ "mappings": {
736+ "properties": {
737+ "priority": {
738+ "type": "integer"
739+ },
740+ "datetime": {
741+ "type": "date"
742+ },
743+ "message": {
744+ "type": "text"
745+ }
746+ }
747+ }
748+ }
749+ ----
750+ +
751+ // CONSOLE
752+ +
753+ . Load the sample data.
754+ +
755+ [source,js]
756+ ----
757+ POST /_bulk
758+ { "index" : { "_index" : "messages", "_id" : "1" } }
759+ { "priority": 1, "datetime": "2019-07-17T12:13:14Z", "message": "m1" }
760+ { "index" : { "_index" : "messages", "_id" : "2" } }
761+ { "priority": 1, "datetime": "2019-07-24T01:14:59Z", "message": "m2" }
762+ { "index" : { "_index" : "messages", "_id" : "3" } }
763+ { "priority": 2, "datetime": "1983-10-14T00:36:42Z", "message": "m3" }
764+ { "index" : { "_index" : "messages", "_id" : "4" } }
765+ { "priority": 3, "datetime": "1983-10-10T02:15:15Z", "message": "m4" }
766+ { "index" : { "_index" : "messages", "_id" : "5" } }
767+ { "priority": 3, "datetime": "1983-10-10T17:18:19Z", "message": "m5" }
768+ { "index" : { "_index" : "messages", "_id" : "6" } }
769+ { "priority": 1, "datetime": "2019-08-03T17:19:31Z", "message": "m6" }
770+ { "index" : { "_index" : "messages", "_id" : "7" } }
771+ { "priority": 3, "datetime": "2019-08-04T17:20:00Z", "message": "m7" }
772+ { "index" : { "_index" : "messages", "_id" : "8" } }
773+ { "priority": 2, "datetime": "2019-08-04T18:01:01Z", "message": "m8" }
774+ { "index" : { "_index" : "messages", "_id" : "9" } }
775+ { "priority": 3, "datetime": "1983-10-10T19:00:45Z", "message": "m9" }
776+ { "index" : { "_index" : "messages", "_id" : "10" } }
777+ { "priority": 2, "datetime": "2019-07-23T23:39:54Z", "message": "m10" }
778+ ----
779+ +
780+ // CONSOLE
781+ // TEST[continued]
782+
783+ ===== Day-of-the-Week Bucket Aggregation Example
784+
785+ The following example uses a
786+ {ref}/search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-script[terms aggregation]
787+ as part of the
788+ <<painless-bucket-script-agg-context, bucket script aggregation context>> to
789+ display the number of messages from each day-of-the-week.
790+
791+ [source,js]
792+ ----
793+ GET /messages/_search?pretty=true
794+ {
795+ "aggs": {
796+ "day-of-week-count": {
797+ "terms": {
798+ "script": "return doc[\"datetime\"].value.getDayOfWeekEnum();"
799+ }
800+ }
801+ }
802+ }
803+ ----
804+ // CONSOLE
805+ // TEST[continued]
806+
807+ ===== Morning/Evening Bucket Aggregation Example
808+
809+ The following example uses a
810+ {ref}/search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-script[terms aggregation]
811+ as part of the
812+ <<painless-bucket-script-agg-context, bucket script aggregation context>> to
813+ display the number of messages received in the morning versus the evening.
814+
815+ [source,js]
816+ ----
817+ GET /messages/_search?pretty=true
818+ {
819+ "aggs": {
820+ "am-pm-count": {
821+ "terms": {
822+ "script": "return doc[\"datetime\"].value.getHour() < 12 ? \"AM\" : \"PM\";"
823+ }
824+ }
825+ }
826+ }
827+ ----
828+ // CONSOLE
829+ // TEST[continued]
830+
831+ ===== Age of a Message Script Field Example
832+
833+ The following example uses a
834+ {ref}/search-request-script-fields.html[script field] as part of the
835+ <<painless-field-context, field context>> to display the elapsed time between
836+ "now" and when a message was received.
837+
838+ [source,js]
839+ ----
840+ GET /_search?pretty=true
841+ {
842+ "query" : {
843+ "match_all": {}
844+ },
845+ "script_fields" : {
846+ "message_age" : {
847+ "script" : {
848+ "source": "ZonedDateTime now = ZonedDateTime.ofInstant(Instant.ofEpochMilli(params[\"now\"]), ZoneId.of(\"Z\")); ZonedDateTime mdt = doc[\"datetime\"].value; String age; long years = mdt.until(now, ChronoUnit.YEARS); age = years + \"Y \"; mdt = mdt.plusYears(years); long months = mdt.until(now, ChronoUnit.MONTHS); age += months + \"M \"; mdt = mdt.plusMonths(months); long days = mdt.until(now, ChronoUnit.DAYS); age += days + \"D \"; mdt = mdt.plusDays(days); long hours = mdt.until(now, ChronoUnit.HOURS); age += hours + \"h \"; mdt = mdt.plusHours(hours); long minutes = mdt.until(now, ChronoUnit.MINUTES); age += minutes + \"m \"; mdt = mdt.plusMinutes(minutes); long seconds = mdt.until(now, ChronoUnit.SECONDS); age += hours + \"s\"; return age;",
849+ "params": {
850+ "now": 1574005645830
851+ }
852+ }
853+ }
854+ }
855+ }
856+ ----
857+ // CONSOLE
858+ // TEST[continued]
859+
860+ The following shows the script broken into multiple lines:
861+
862+ [source,Painless]
863+ ----
864+ ZonedDateTime now = ZonedDateTime.ofInstant(
865+ Instant.ofEpochMilli(params['now']), ZoneId.of('Z')); <1>
866+ ZonedDateTime mdt = doc['datetime'].value; <2>
867+
868+ String age;
869+
870+ long years = mdt.until(now, ChronoUnit.YEARS); <3>
871+ age = years + 'Y '; <4>
872+ mdt = mdt.plusYears(years); <5>
873+
874+ long months = mdt.until(now, ChronoUnit.MONTHS);
875+ age += months + 'M ';
876+ mdt = mdt.plusMonths(months);
877+
878+ long days = mdt.until(now, ChronoUnit.DAYS);
879+ age += days + 'D ';
880+ mdt = mdt.plusDays(days);
881+
882+ long hours = mdt.until(now, ChronoUnit.HOURS);
883+ age += hours + 'h ';
884+ mdt = mdt.plusHours(hours);
885+
886+ long minutes = mdt.until(now, ChronoUnit.MINUTES);
887+ age += minutes + 'm ';
888+ mdt = mdt.plusMinutes(minutes);
889+
890+ long seconds = mdt.until(now, ChronoUnit.SECONDS);
891+ age += hours + 's';
892+
893+ return age; <6>
894+ ----
895+ <1> Parse the datetime "now" as input from the user-defined params.
896+ <2> Store the datetime the message was received as a `ZonedDateTime`.
897+ <3> Find the difference in years between "now" and the datetime the message was
898+ received.
899+ <4> Add the difference in years later returned in the format
900+ `Y <years> ...` for the age of a message.
901+ <5> Add the years so only the remainder of the months, days, etc. remain as the
902+ difference between "now" and the datetime the message was received. Repeat this
903+ pattern until the desired granularity is reached (seconds in this example).
904+ <6> Return the age of the message in the format
905+ `Y <years> M <months> D <days> h <hours> m <minutes> s <seconds>`.
0 commit comments