DateTime Processing

DateUtils - Uniform API for Date Parsing and Formatting

Date and time processing is difficult due to the complexity of rules (and exceptions from rules) specific to historical changes, calendar systems, locales, time zones, and DST rules (daylight saving time).

Fusion uses com.lucidworks.apollo.common.util.DateUtils for date / time parsing and formatting, and developers are strongly encouraged to use this class for parsing date formats.

The DateUtils class uses the Joda Time library, which was the basis for the java.util.time API in JDK 8 but is compatible with earlier versions of Java. It add support for parsing abbreviated time zone names (e.g. PST). Although use of abbreviated time zone names has been deprecated because many of them are ambiguous, they are still in wide use. It also supports parsing full time zone names in any letter case (Joda Time accepts only canonical mixed-case names, e.g. "America/New_York"). Robust identification of time zone is helpful for reasoning about time intervals, because time zone rules cover phenomena like DST changes with gap and overlap hours, leap seconds, administrative changes to offsets, etc, etc, for which a simple offset from UTC is insufficient.

Supported Formats

Supported formats for date / time parsing can be divided into three disjoint groups:

  • ISO 8601 formats ("Solr formats"), represented as yyyy-MM-dd’T’HH:mm:ss.SSS’Z'. The milliseconds part is optional, with precision varying between 0-3 digits.

  • Fusion "zoned format" - a modification of a common Internet format that specifies day of week and uses full names for time zones, represented as EEE yyyy-MM-dd HH:mm:ss.SSS ZZZ in US locale. This format is useful for storing and easy processing of date/time with zone, as it’s unambiguous, exact and easy to parse.

  • Epoch formats - represented in Java API as objects of java.util.Date or the number of seconds, or the number of milliseconds since epoch (either as a number or as a String). These formats by definition don’t contain any time zone information, and if permitted they are treated as absolute instants in the default time zone (see below).

  • Common global formats - i.e. formats that explicitly specify the timezone.

  • Common local formats - i.e. formats that don’t specify the timezone.

The definition of formatting symbols used below can be found in the Joda Time DateTimeFormat documentation.

ISO 8601 / Solr Formats

      "yyyy-MM-dd'T'HH:mm:ss'Z'", // Solr format without milliseconds
      "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", // standard Solr format, with literal "Z" at the end
      "yyyy-MM-dd'T'HH:mm:ss.SS'Z'", // standard Solr format, with literal "Z" at the end
      "yyyy-MM-dd'T'HH:mm:ss.S'Z'" // standard Solr format, with literal "Z" at the end

Common Global Formats

      "EEE yyyy-MM-dd HH:mm:ss.SSS zzz",
      "yyyy-MM-dd'T'HH:mm:ss.SSSZ", // with numeric +-HHmm timezone at the end
      "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", // with numeric +-HH:mm timezone at the end
      "yyyy-MM-dd'T'HH:mm:ss.SSSz", // with symbolic XXX timezone at the end
      "yyyy-MM-dd'T'HH:mm:ssz", // with symbolic XXX timezone at the end
      "yyyy-MM-dd'T'HH:mm:ssZ", // with offset
      "EEE MMM d HH:mm:ss z yyyy",
      "EEE MMM d HH:mm:ss Z yyyy",
      "EEE MMM d HH:mm:ss z yyyy",
      "EEE MMM d HH:mm:ss.SSS z yyyy",
      "EEE, dd MMM yyyy HH:mm:ss zzz", // RFC 1123, with either short or full time zone
      "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 1036
      "yyyy-MM-dd HH:mm:ss Z",
      "yyyy-MM-dd HH:mm:ss ZZ",
      "yyyy-MM-dd HH:mm:ss z",
      "yyyy-MM-dd HH:mm:ss.SSS Z",
      "yyyy-MM-dd HH:mm:ss.SSS ZZ",
      "yyyy-MM-dd HH:mm:ss.SSS z",
      "yyyy-MM-dd HH:mm:ss zzz", // with full time zone (e.g. America/New_York)
      "yyyy-MM-dd'T'HH:mm:ss'GMT'Z", // with literal "GMT" and offset
      "yyyy-MM-dd'T'HH:mm:ss.SSS'GMT'Z", // with literal "GMT" and offset
      "yyyy-MM-dd'T'HH:mm:ss'UTC'Z", // with literal "UTC" and offset
      "yyyy-MM-dd'T'HH:mm:ss.SSS'UTC'Z", // with literal "UTC" and offset
      "yyyy-MM-dd HH:mm:ss 'UTC'Z",
      "yyyy-MM-dd HH:mm:ss.SSS 'UTC'Z",
      "yyyy-MM-dd HH:mm:ss 'GMT'Z",
      "yyyy-MM-dd HH:mm:ss.SSS 'GMT'Z"

Note: Joda-Time cannot parse ZZZ when zone name is in incorrect case (e.g. "EUROPE/WARSAW" will fail), for this reason we use zzz which accepts any letter case.

Common Local Formats

      "yyyy-MM-dd'T'HH:mm:ss",
      "yyyy-MM-dd",
      "yyyy-MM-dd hh:mm:ss",
      "yyyy-MM-dd HH:mm:ss",
      "yyyy-MM-dd HH:mm:ss.SSS",
      "EEE MMM d HH:mm:ss yyyy", // ANSI C
      "EEE MMM d HH:mm:ss.SSS yyyy" // ANSI C
Missing parts of the data are filled in with defaults - e.g. time zone is filled in with the default time zone (see below), missing time data is filled with 00:00:00.000

DateUtils Usage

Instances of DateUtils can be created with the following arguments:

  • requireTimezone - (boolean, required) when this argument is true then only patterns with timezone component are accepted (unless custom patterns are provided). Epoch formats are not accepted. If false then any recognizable pattern is used.

  • formats - (list of strings, optional) a list of formats to use instead of the built-in ones.

  • locale - (string, optional) locale to use for parsing, or null for the platform default locale.

  • defaultTimeZone - (string, optional) time zone name to use as default (when using local formats), or null for the platform default time zone. Time zone names can be provided in short or long form, or as a fixed offset [-+]HH:mm.Further information is provided in the Javadoc of the class. The default instance of DateUtils uses common global formats (with ISO8601 and epoch formats), requireTimezone == true, locale "en-US" and time zone "UTC".