anchor.diff:  ----
   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.
  +        DateTimeFormatter.RFC_1123_DATE_TIME); <1>
  +----
  +<1> Note the use of a built-in DateTimeFormatter.
   +
   * parse from a custom format
   +
  
positive.code: 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
  
  
negative.code:     // handle condition
  }
  ----
  
  ==== Datetime Input
  
  There are several common ways datetimes are used as input for a script
  determined by the <<painless-contexts, Painless context>>. Typically, datetime
  input will be accessed from parameters specified by the user, from an original
  source document, or from an indexed document.
  
  ===== Datetime Input From User Parameters
  
  Use the {ref}/modules-scripting-using.html#_script_parameters[params section]
  during script specification to pass in a numeric datetime or string datetime as
  a script input. Access to user-defined parameters within a script is dependent
  on the Painless context, though, the parameters are most commonly accessible
  through an input called `params`.
  
  *Examples*
  
  * Parse a numeric datetime from user parameters to a complex datetime
  +
  ** Input:
  +
  [source,JSON]
  ----
  ...
  "script": {
      ...
      "params": {
          "input_datetime": 434931327000
      }
  }
  ...
  ----
  +
  ** Script:
  +
  [source,Painless]
  ----
  long inputDatetime = params['input_datetime'];
  Instant instant = Instant.ofEpochMilli(inputDateTime);
  ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
  ----
  +
  * Parse a string datetime from user parameters to a complex datetime
  +
  ** Input:
  +
  [source,JSON]
  ----
  ...
  "script": {
      ...
      "params": {
          "input_datetime": "custom y 1983 m 10 d 13 22:15:30 Z"
      }
  }
  ...
  ----
  +
  ** Script:
  +
  [source,Painless]
  ----
  String datetime = params['input_datetime'];
  DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
          "'custom' 'y' yyyy 'm' MM 'd' dd HH:mm:ss VV");
  ZonedDateTime zdt = ZonedDateTime.parse(datetime, dtf); <1>
  ----
  <1> Note the use of a custom DateTimeFormatter.
  
  ===== Datetime Input From a Source Document
  
  Use an original {ref}/mapping-source-field.html[source] document as a script
  input to access a numeric datetime or string datetime for a specific field
  within that document. Access to an original source document within a script is
  dependent on the Painless context and is not always available. An original
  source document is most commonly accessible through an input called
  `ctx['_source']` or `params['_source']`.
  
  *Examples*
  
  * Parse a numeric datetime from a sourced document to a complex datetime
  +
  ** Input:
  +
  [source,JSON]
  ----
  {
      ...
      "input_datetime": 434931327000
      ...
  }
  ----
  +
  ** Script:
  +
  [source,Painless]
  ----
  long inputDatetime = ctx['_source']['input_datetime']; <1>
  Instant instant = Instant.ofEpochMilli(inputDateTime);
  ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.of('Z'));
  ----
  <1> Note access to `_source` is dependent on the Painless context.
  +
  * Parse a string datetime from a sourced document to a complex datetime
  +
  ** Input:
  +
  [source,JSON]
  ----
  {
      ...
      "input_datetime": "1983-10-13T22:15:30Z"
      ...
  }
  ----
  +
  ** Script:
  +
  [source,Painless]
  ----
  String datetime = params['_source']['input_datetime']; <1>
  ZonedDateTime zdt = ZonedDateTime.parse(datetime); <2>
  ----
  <1> Note access to `_source` is dependent on the Painless context.
  <2> Note the parse method uses ISO 8601 by default.
  
  ===== Datetime Input From an Indexed Document
  
  Use an indexed document as a script input to access a complex datetime for a
  specific field within that document where the field is mapped as a
  {ref}/date.html[standard date] or a {ref}/date_nanos.html[nanosecond date].
  Numeric datetime fields mapped as {ref}/number.html[numeric] and string
  datetime fields mapped as {ref}/keyword.html[keyword] are accessible through an
  indexed document as well. Access to an indexed document within a script is
  dependent on the Painless context and is not always available. An indexed
  document is most commonly accessible through an input called `doc`.
  
  *Examples*
  
  * Format a complex datetime from an indexed document to a string datetime
  +
  ** Assumptions:
  +
  *** The field `input_datetime` exists in all indexes as part of the query
  *** All indexed documents contain the field `input_datetime`
  +
  ** Mappings:
  +
  [source,JSON]
  ----
  {
      "mappings": {
          ...
          "properties": {
              ...
              "input_datetime": {
                  "type": "date"
              }
              ...
          }
          ...
      }
  }
  ----
  +
  ** Script:
  +
  [source,Painless]
  ----
  def input = doc['input_datetime'].value;
  String output = input.format(DateTimeFormatter.ISO_INSTANT); <1>
  ----
  <1> Note the use of a built-in DateTimeFormatter.
  +
  * Find the difference between two complex datetimes from an indexed document
  +
  ** 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
  +
  ** Mappings:
  +
  [source,JSON]
  ----
  {
      "mappings": {
          ...
          "properties": {
              ...
              "start_datetime": {
                  "type": "date"
              },
              "end_datetime": {
                  "type": "date"
              }
              ...
          }
          ...
      }
  }
  ----
  +
  ** Script:
  +
  [source,Painless]
  ----
  if (doc.containsKey('start_datetime') && doc.containsKey('end_datetime')) { <1>
  
      if (doc['start_datetime'].size() > 0 && doc['end_datetime'].size() > 0) { <2>
  
          def startDatetime = doc['start_datetime'].value;
          def endDatetime = doc['end_datetime'].value;
          long differenceInMillis =
              ChronoUnit.MILLIS.between(startDateTime, endDateTime);
  
          // handle difference in times
      } else {
          // handle fields without values
      }
  } else {
      // handle index with missing fields
  }
  ----
  <1> When a query's results span multiple indexes, some indexes may not
  contain a specific field. Use the `containsKey` method call on the `doc` input
  to ensure a field exists as part of the index for the current document.
  <2> Some field's within a document may have no values. Use the `size` method
  call on a field within the `doc` input to ensure that field has at least one
  value for the current document.
  