fields, boolean strictISO) {
+ if (strictISO) {
+ throw new IllegalArgumentException("No valid ISO8601 format for fields: " + fields);
+ }
+ }
+
+ /**
+ * Appends the separator if necessary.
+ *
+ * @param bld the builder
+ * @param extended whether to append the separator
+ * @since 1.1
+ */
+ private static void appendSeparator(DateTimeFormatterBuilder bld, boolean extended) {
+ if (extended) {
+ bld.appendLiteral('-');
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a generic ISO date parser for parsing dates with a possible zone.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * date = date-element ['T' offset]
+ * date-element = std-date-element | ord-date-element | week-date-element
+ * std-date-element = yyyy ['-' MM ['-' dd]]
+ * ord-date-element = yyyy ['-' DDD]
+ * week-date-element = xxxx '-W' ww ['-' e]
+ * offset = 'Z' | (('+' | '-') HH [':' mm [':' ss [('.' | ',') SSS]]])
+ *
+ */
+ public static DateTimeFormatter dateParser() {
+ return Constants.dp;
+ }
+
+ /**
+ * Returns a generic ISO date parser for parsing local dates.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * This parser is initialised with the local (UTC) time zone.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * date-element = std-date-element | ord-date-element | week-date-element
+ * std-date-element = yyyy ['-' MM ['-' dd]]
+ * ord-date-element = yyyy ['-' DDD]
+ * week-date-element = xxxx '-W' ww ['-' e]
+ *
+ * @since 1.3
+ */
+ public static DateTimeFormatter localDateParser() {
+ return Constants.ldp;
+ }
+
+ /**
+ * Returns a generic ISO date parser for parsing dates.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * date-element = std-date-element | ord-date-element | week-date-element
+ * std-date-element = yyyy ['-' MM ['-' dd]]
+ * ord-date-element = yyyy ['-' DDD]
+ * week-date-element = xxxx '-W' ww ['-' e]
+ *
+ */
+ public static DateTimeFormatter dateElementParser() {
+ return Constants.dpe;
+ }
+
+ /**
+ * Returns a generic ISO time parser for parsing times with a possible zone.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * time = ['T'] time-element [offset]
+ * time-element = HH [minute-element] | [fraction]
+ * minute-element = ':' mm [second-element] | [fraction]
+ * second-element = ':' ss [fraction]
+ * fraction = ('.' | ',') digit+
+ * offset = 'Z' | (('+' | '-') HH [':' mm [':' ss [('.' | ',') SSS]]])
+ *
+ */
+ public static DateTimeFormatter timeParser() {
+ return Constants.tp;
+ }
+
+ /**
+ * Returns a generic ISO time parser for parsing local times.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * This parser is initialised with the local (UTC) time zone.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * time = ['T'] time-element
+ * time-element = HH [minute-element] | [fraction]
+ * minute-element = ':' mm [second-element] | [fraction]
+ * second-element = ':' ss [fraction]
+ * fraction = ('.' | ',') digit+
+ *
+ * @since 1.3
+ */
+ public static DateTimeFormatter localTimeParser() {
+ return Constants.ltp;
+ }
+
+ /**
+ * Returns a generic ISO time parser.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * time-element = HH [minute-element] | [fraction]
+ * minute-element = ':' mm [second-element] | [fraction]
+ * second-element = ':' ss [fraction]
+ * fraction = ('.' | ',') digit+
+ *
+ */
+ public static DateTimeFormatter timeElementParser() {
+ return Constants.tpe;
+ }
+
+ /**
+ * Returns a generic ISO datetime parser which parses either a date or a time or both.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * datetime = time | date-opt-time
+ * time = 'T' time-element [offset]
+ * date-opt-time = date-element ['T' [time-element] [offset]]
+ * date-element = std-date-element | ord-date-element | week-date-element
+ * std-date-element = yyyy ['-' MM ['-' dd]]
+ * ord-date-element = yyyy ['-' DDD]
+ * week-date-element = xxxx '-W' ww ['-' e]
+ * time-element = HH [minute-element] | [fraction]
+ * minute-element = ':' mm [second-element] | [fraction]
+ * second-element = ':' ss [fraction]
+ * fraction = ('.' | ',') digit+
+ * offset = 'Z' | (('+' | '-') HH [':' mm [':' ss [('.' | ',') SSS]]])
+ *
+ */
+ public static DateTimeFormatter dateTimeParser() {
+ return Constants.dtp;
+ }
+
+ /**
+ * Returns a generic ISO datetime parser where the date is mandatory and the time is optional.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * This parser can parse zoned datetimes.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * date-opt-time = date-element ['T' [time-element] [offset]]
+ * date-element = std-date-element | ord-date-element | week-date-element
+ * std-date-element = yyyy ['-' MM ['-' dd]]
+ * ord-date-element = yyyy ['-' DDD]
+ * week-date-element = xxxx '-W' ww ['-' e]
+ * time-element = HH [minute-element] | [fraction]
+ * minute-element = ':' mm [second-element] | [fraction]
+ * second-element = ':' ss [fraction]
+ * fraction = ('.' | ',') digit+
+ *
+ * @since 1.3
+ */
+ public static DateTimeFormatter dateOptionalTimeParser() {
+ return Constants.dotp;
+ }
+
+ /**
+ * Returns a generic ISO datetime parser where the date is mandatory and the time is optional.
+ *
+ * The returned formatter can only be used for parsing, printing is unsupported.
+ *
+ * This parser only parses local datetimes.
+ * This parser is initialised with the local (UTC) time zone.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * It accepts formats described by the following syntax:
+ *
+ * datetime = date-element ['T' time-element]
+ * date-element = std-date-element | ord-date-element | week-date-element
+ * std-date-element = yyyy ['-' MM ['-' dd]]
+ * ord-date-element = yyyy ['-' DDD]
+ * week-date-element = xxxx '-W' ww ['-' e]
+ * time-element = HH [minute-element] | [fraction]
+ * minute-element = ':' mm [second-element] | [fraction]
+ * second-element = ':' ss [fraction]
+ * fraction = ('.' | ',') digit+
+ *
+ * @since 1.3
+ */
+ public static DateTimeFormatter localDateOptionalTimeParser() {
+ return Constants.ldotp;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a formatter for a full date as four digit year, two digit month
+ * of year, and two digit day of month (yyyy-MM-dd).
+ *
+ * The returned formatter prints and parses only this format.
+ * See {@link #dateParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for yyyy-MM-dd
+ */
+ public static DateTimeFormatter date() {
+ return yearMonthDay();
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day, two digit minute of
+ * hour, two digit second of minute, three digit fraction of second, and
+ * time zone offset (HH:mm:ss.SSSZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ * See {@link #timeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for HH:mm:ss.SSSZZ
+ */
+ public static DateTimeFormatter time() {
+ return Constants.t;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day, two digit minute of
+ * hour, two digit second of minute, and time zone offset (HH:mm:ssZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ * See {@link #timeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for HH:mm:ssZZ
+ */
+ public static DateTimeFormatter timeNoMillis() {
+ return Constants.tx;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day, two digit minute of
+ * hour, two digit second of minute, three digit fraction of second, and
+ * time zone offset prefixed by 'T' ('T'HH:mm:ss.SSSZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ * See {@link #timeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for 'T'HH:mm:ss.SSSZZ
+ */
+ public static DateTimeFormatter tTime() {
+ return Constants.tt;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day, two digit minute of
+ * hour, two digit second of minute, and time zone offset prefixed
+ * by 'T' ('T'HH:mm:ssZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ * See {@link #timeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for 'T'HH:mm:ssZZ
+ */
+ public static DateTimeFormatter tTimeNoMillis() {
+ return Constants.ttx;
+ }
+
+ /**
+ * Returns a formatter that combines a full date and time, separated by a 'T'
+ * (yyyy-MM-dd'T'HH:mm:ss.SSSZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ * See {@link #dateTimeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for yyyy-MM-dd'T'HH:mm:ss.SSSZZ
+ */
+ public static DateTimeFormatter dateTime() {
+ return Constants.dt;
+ }
+
+ /**
+ * Returns a formatter that combines a full date and time without millis,
+ * separated by a 'T' (yyyy-MM-dd'T'HH:mm:ssZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ * See {@link #dateTimeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for yyyy-MM-dd'T'HH:mm:ssZZ
+ */
+ public static DateTimeFormatter dateTimeNoMillis() {
+ return Constants.dtx;
+ }
+
+ /**
+ * Returns a formatter for a full ordinal date, using a four
+ * digit year and three digit dayOfYear (yyyy-DDD).
+ *
+ * The returned formatter prints and parses only this format.
+ * See {@link #dateParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for yyyy-DDD
+ * @since 1.1
+ */
+ public static DateTimeFormatter ordinalDate() {
+ return Constants.od;
+ }
+
+ /**
+ * Returns a formatter for a full ordinal date and time, using a four
+ * digit year and three digit dayOfYear (yyyy-DDD'T'HH:mm:ss.SSSZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ * See {@link #dateTimeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for yyyy-DDD'T'HH:mm:ss.SSSZZ
+ * @since 1.1
+ */
+ public static DateTimeFormatter ordinalDateTime() {
+ return Constants.odt;
+ }
+
+ /**
+ * Returns a formatter for a full ordinal date and time without millis,
+ * using a four digit year and three digit dayOfYear (yyyy-DDD'T'HH:mm:ssZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ * See {@link #dateTimeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for yyyy-DDD'T'HH:mm:ssZZ
+ * @since 1.1
+ */
+ public static DateTimeFormatter ordinalDateTimeNoMillis() {
+ return Constants.odtx;
+ }
+
+ /**
+ * Returns a formatter for a full date as four digit weekyear, two digit
+ * week of weekyear, and one digit day of week (xxxx-'W'ww-e).
+ *
+ * The returned formatter prints and parses only this format.
+ * See {@link #dateParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for xxxx-'W'ww-e
+ */
+ public static DateTimeFormatter weekDate() {
+ return Constants.wwd;
+ }
+
+ /**
+ * Returns a formatter that combines a full weekyear date and time,
+ * separated by a 'T' (xxxx-'W'ww-e'T'HH:mm:ss.SSSZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ * See {@link #dateTimeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for xxxx-'W'ww-e'T'HH:mm:ss.SSSZZ
+ */
+ public static DateTimeFormatter weekDateTime() {
+ return Constants.wdt;
+ }
+
+ /**
+ * Returns a formatter that combines a full weekyear date and time without millis,
+ * separated by a 'T' (xxxx-'W'ww-e'T'HH:mm:ssZZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HH:mm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ * See {@link #dateTimeParser()} for a more flexible parser that accepts different formats.
+ *
+ * @return a formatter for xxxx-'W'ww-e'T'HH:mm:ssZZ
+ */
+ public static DateTimeFormatter weekDateTimeNoMillis() {
+ return Constants.wdtx;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a basic formatter for a full date as four digit year, two digit
+ * month of year, and two digit day of month (yyyyMMdd).
+ *
+ * The returned formatter prints and parses only this format.
+ *
+ * @return a formatter for yyyyMMdd
+ */
+ public static DateTimeFormatter basicDate() {
+ return Constants.bd;
+ }
+
+ /**
+ * Returns a basic formatter for a two digit hour of day, two digit minute
+ * of hour, two digit second of minute, three digit millis, and time zone
+ * offset (HHmmss.SSSZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ *
+ * @return a formatter for HHmmss.SSSZ
+ */
+ public static DateTimeFormatter basicTime() {
+ return Constants.bt;
+ }
+
+ /**
+ * Returns a basic formatter for a two digit hour of day, two digit minute
+ * of hour, two digit second of minute, and time zone offset (HHmmssZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ *
+ * @return a formatter for HHmmssZ
+ */
+ public static DateTimeFormatter basicTimeNoMillis() {
+ return Constants.btx;
+ }
+
+ /**
+ * Returns a basic formatter for a two digit hour of day, two digit minute
+ * of hour, two digit second of minute, three digit millis, and time zone
+ * offset prefixed by 'T' ('T'HHmmss.SSSZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ *
+ * @return a formatter for 'T'HHmmss.SSSZ
+ */
+ public static DateTimeFormatter basicTTime() {
+ return Constants.btt;
+ }
+
+ /**
+ * Returns a basic formatter for a two digit hour of day, two digit minute
+ * of hour, two digit second of minute, and time zone offset prefixed by 'T'
+ * ('T'HHmmssZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ *
+ * @return a formatter for 'T'HHmmssZ
+ */
+ public static DateTimeFormatter basicTTimeNoMillis() {
+ return Constants.bttx;
+ }
+
+ /**
+ * Returns a basic formatter that combines a basic date and time, separated
+ * by a 'T' (yyyyMMdd'T'HHmmss.SSSZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ *
+ * @return a formatter for yyyyMMdd'T'HHmmss.SSSZ
+ */
+ public static DateTimeFormatter basicDateTime() {
+ return Constants.bdt;
+ }
+
+ /**
+ * Returns a basic formatter that combines a basic date and time without millis,
+ * separated by a 'T' (yyyyMMdd'T'HHmmssZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ *
+ * @return a formatter for yyyyMMdd'T'HHmmssZ
+ */
+ public static DateTimeFormatter basicDateTimeNoMillis() {
+ return Constants.bdtx;
+ }
+
+ /**
+ * Returns a formatter for a full ordinal date, using a four
+ * digit year and three digit dayOfYear (yyyyDDD).
+ *
+ * The returned formatter prints and parses only this format.
+ *
+ * @return a formatter for yyyyDDD
+ * @since 1.1
+ */
+ public static DateTimeFormatter basicOrdinalDate() {
+ return Constants.bod;
+ }
+
+ /**
+ * Returns a formatter for a full ordinal date and time, using a four
+ * digit year and three digit dayOfYear (yyyyDDD'T'HHmmss.SSSZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ *
+ * @return a formatter for yyyyDDD'T'HHmmss.SSSZ
+ * @since 1.1
+ */
+ public static DateTimeFormatter basicOrdinalDateTime() {
+ return Constants.bodt;
+ }
+
+ /**
+ * Returns a formatter for a full ordinal date and time without millis,
+ * using a four digit year and three digit dayOfYear (yyyyDDD'T'HHmmssZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ *
+ * @return a formatter for yyyyDDD'T'HHmmssZ
+ * @since 1.1
+ */
+ public static DateTimeFormatter basicOrdinalDateTimeNoMillis() {
+ return Constants.bodtx;
+ }
+
+ /**
+ * Returns a basic formatter for a full date as four digit weekyear, two
+ * digit week of weekyear, and one digit day of week (xxxx'W'wwe).
+ *
+ * The returned formatter prints and parses only this format.
+ *
+ * @return a formatter for xxxx'W'wwe
+ */
+ public static DateTimeFormatter basicWeekDate() {
+ return Constants.bwd;
+ }
+
+ /**
+ * Returns a basic formatter that combines a basic weekyear date and time,
+ * separated by a 'T' (xxxx'W'wwe'T'HHmmss.SSSZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which includes milliseconds.
+ *
+ * @return a formatter for xxxx'W'wwe'T'HHmmss.SSSZ
+ */
+ public static DateTimeFormatter basicWeekDateTime() {
+ return Constants.bwdt;
+ }
+
+ /**
+ * Returns a basic formatter that combines a basic weekyear date and time
+ * without millis, separated by a 'T' (xxxx'W'wwe'T'HHmmssZ).
+ *
+ * The time zone offset is 'Z' for zero, and of the form '\u00b1HHmm' for non-zero.
+ * The parser is strict by default, thus time string {@code 24:00} cannot be parsed.
+ *
+ * The returned formatter prints and parses only this format, which excludes milliseconds.
+ *
+ * @return a formatter for xxxx'W'wwe'T'HHmmssZ
+ */
+ public static DateTimeFormatter basicWeekDateTimeNoMillis() {
+ return Constants.bwdtx;
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a formatter for a four digit year. (yyyy)
+ *
+ * @return a formatter for yyyy
+ */
+ public static DateTimeFormatter year() {
+ return Constants.ye;
+ }
+
+ /**
+ * Returns a formatter for a four digit year and two digit month of
+ * year. (yyyy-MM)
+ *
+ * @return a formatter for yyyy-MM
+ */
+ public static DateTimeFormatter yearMonth() {
+ return Constants.ym;
+ }
+
+ /**
+ * Returns a formatter for a four digit year, two digit month of year, and
+ * two digit day of month. (yyyy-MM-dd)
+ *
+ * @return a formatter for yyyy-MM-dd
+ */
+ public static DateTimeFormatter yearMonthDay() {
+ return Constants.ymd;
+ }
+
+ /**
+ * Returns a formatter for a four digit weekyear. (xxxx)
+ *
+ * @return a formatter for xxxx
+ */
+ public static DateTimeFormatter weekyear() {
+ return Constants.we;
+ }
+
+ /**
+ * Returns a formatter for a four digit weekyear and two digit week of
+ * weekyear. (xxxx-'W'ww)
+ *
+ * @return a formatter for xxxx-'W'ww
+ */
+ public static DateTimeFormatter weekyearWeek() {
+ return Constants.ww;
+ }
+
+ /**
+ * Returns a formatter for a four digit weekyear, two digit week of
+ * weekyear, and one digit day of week. (xxxx-'W'ww-e)
+ *
+ * @return a formatter for xxxx-'W'ww-e
+ */
+ public static DateTimeFormatter weekyearWeekDay() {
+ return Constants.wwd;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day. (HH)
+ *
+ * @return a formatter for HH
+ */
+ public static DateTimeFormatter hour() {
+ return Constants.hde;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day and two digit minute of
+ * hour. (HH:mm)
+ *
+ * @return a formatter for HH:mm
+ */
+ public static DateTimeFormatter hourMinute() {
+ return Constants.hm;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day, two digit minute of
+ * hour, and two digit second of minute. (HH:mm:ss)
+ *
+ * @return a formatter for HH:mm:ss
+ */
+ public static DateTimeFormatter hourMinuteSecond() {
+ return Constants.hms;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day, two digit minute of
+ * hour, two digit second of minute, and three digit fraction of
+ * second (HH:mm:ss.SSS). Parsing will parse up to 3 fractional second
+ * digits.
+ *
+ * @return a formatter for HH:mm:ss.SSS
+ */
+ public static DateTimeFormatter hourMinuteSecondMillis() {
+ return Constants.hmsl;
+ }
+
+ /**
+ * Returns a formatter for a two digit hour of day, two digit minute of
+ * hour, two digit second of minute, and three digit fraction of
+ * second (HH:mm:ss.SSS). Parsing will parse up to 9 fractional second
+ * digits, throwing away all except the first three.
+ *
+ * @return a formatter for HH:mm:ss.SSS
+ */
+ public static DateTimeFormatter hourMinuteSecondFraction() {
+ return Constants.hmsf;
+ }
+
+ /**
+ * Returns a formatter that combines a full date and two digit hour of
+ * day. (yyyy-MM-dd'T'HH)
+ *
+ * @return a formatter for yyyy-MM-dd'T'HH
+ */
+ public static DateTimeFormatter dateHour() {
+ return Constants.dh;
+ }
+
+ /**
+ * Returns a formatter that combines a full date, two digit hour of day,
+ * and two digit minute of hour. (yyyy-MM-dd'T'HH:mm)
+ *
+ * @return a formatter for yyyy-MM-dd'T'HH:mm
+ */
+ public static DateTimeFormatter dateHourMinute() {
+ return Constants.dhm;
+ }
+
+ /**
+ * Returns a formatter that combines a full date, two digit hour of day,
+ * two digit minute of hour, and two digit second of
+ * minute. (yyyy-MM-dd'T'HH:mm:ss)
+ *
+ * @return a formatter for yyyy-MM-dd'T'HH:mm:ss
+ */
+ public static DateTimeFormatter dateHourMinuteSecond() {
+ return Constants.dhms;
+ }
+
+ /**
+ * Returns a formatter that combines a full date, two digit hour of day,
+ * two digit minute of hour, two digit second of minute, and three digit
+ * fraction of second (yyyy-MM-dd'T'HH:mm:ss.SSS). Parsing will parse up
+ * to 3 fractional second digits.
+ *
+ * @return a formatter for yyyy-MM-dd'T'HH:mm:ss.SSS
+ */
+ public static DateTimeFormatter dateHourMinuteSecondMillis() {
+ return Constants.dhmsl;
+ }
+
+ /**
+ * Returns a formatter that combines a full date, two digit hour of day,
+ * two digit minute of hour, two digit second of minute, and three digit
+ * fraction of second (yyyy-MM-dd'T'HH:mm:ss.SSS). Parsing will parse up
+ * to 9 fractional second digits, throwing away all except the first three.
+ *
+ * @return a formatter for yyyy-MM-dd'T'HH:mm:ss.SSS
+ */
+ public static DateTimeFormatter dateHourMinuteSecondFraction() {
+ return Constants.dhmsf;
+ }
+
+ //-----------------------------------------------------------------------
+ static final class Constants {
+ private static final DateTimeFormatter
+ ye = yearElement(), // year element (yyyy)
+ mye = monthElement(), // monthOfYear element (-MM)
+ dme = dayOfMonthElement(), // dayOfMonth element (-dd)
+ we = weekyearElement(), // weekyear element (xxxx)
+ wwe = weekElement(), // weekOfWeekyear element (-ww)
+ dwe = dayOfWeekElement(), // dayOfWeek element (-ee)
+ dye = dayOfYearElement(), // dayOfYear element (-DDD)
+ hde = hourElement(), // hourOfDay element (HH)
+ mhe = minuteElement(), // minuteOfHour element (:mm)
+ sme = secondElement(), // secondOfMinute element (:ss)
+ fse = fractionElement(), // fractionOfSecond element (.SSSSSSSSS)
+ ze = offsetElement(), // zone offset element
+ lte = literalTElement(), // literal 'T' element
+
+ //y, // year (same as year element)
+ ym = yearMonth(), // year month
+ ymd = yearMonthDay(), // year month day
+
+ //w, // weekyear (same as weekyear element)
+ ww = weekyearWeek(), // weekyear week
+ wwd = weekyearWeekDay(), // weekyear week day
+
+ //h, // hour (same as hour element)
+ hm = hourMinute(), // hour minute
+ hms = hourMinuteSecond(), // hour minute second
+ hmsl = hourMinuteSecondMillis(), // hour minute second millis
+ hmsf = hourMinuteSecondFraction(), // hour minute second fraction
+
+ dh = dateHour(), // date hour
+ dhm = dateHourMinute(), // date hour minute
+ dhms = dateHourMinuteSecond(), // date hour minute second
+ dhmsl = dateHourMinuteSecondMillis(), // date hour minute second millis
+ dhmsf = dateHourMinuteSecondFraction(), // date hour minute second fraction
+
+ //d, // date (same as ymd)
+ t = time(), // time
+ tx = timeNoMillis(), // time no millis
+ tt = tTime(), // Ttime
+ ttx = tTimeNoMillis(), // Ttime no millis
+ dt = dateTime(), // date time
+ dtx = dateTimeNoMillis(), // date time no millis
+
+ //wd, // week date (same as wwd)
+ wdt = weekDateTime(), // week date time
+ wdtx = weekDateTimeNoMillis(), // week date time no millis
+
+ od = ordinalDate(), // ordinal date (same as yd)
+ odt = ordinalDateTime(), // ordinal date time
+ odtx = ordinalDateTimeNoMillis(), // ordinal date time no millis
+
+ bd = basicDate(), // basic date
+ bt = basicTime(), // basic time
+ btx = basicTimeNoMillis(), // basic time no millis
+ btt = basicTTime(), // basic Ttime
+ bttx = basicTTimeNoMillis(), // basic Ttime no millis
+ bdt = basicDateTime(), // basic date time
+ bdtx = basicDateTimeNoMillis(), // basic date time no millis
+
+ bod = basicOrdinalDate(), // basic ordinal date
+ bodt = basicOrdinalDateTime(), // basic ordinal date time
+ bodtx = basicOrdinalDateTimeNoMillis(), // basic ordinal date time no millis
+
+ bwd = basicWeekDate(), // basic week date
+ bwdt = basicWeekDateTime(), // basic week date time
+ bwdtx = basicWeekDateTimeNoMillis(), // basic week date time no millis
+
+ dpe = dateElementParser(), // date parser element
+ tpe = timeElementParser(), // time parser element
+ dp = dateParser(), // date parser
+ ldp = localDateParser(), // local date parser
+ tp = timeParser(), // time parser
+ ltp = localTimeParser(), // local time parser
+ dtp = dateTimeParser(), // date time parser
+ dotp = dateOptionalTimeParser(), // date optional time parser
+ ldotp = localDateOptionalTimeParser(); // local date optional time parser
+
+ //-----------------------------------------------------------------------
+ private static DateTimeFormatter dateParser() {
+ if (dp == null) {
+ DateTimeParser tOffset = new DateTimeFormatterBuilder()
+ .appendLiteral('T')
+ .append(offsetElement()).toParser();
+ return new DateTimeFormatterBuilder()
+ .append(dateElementParser())
+ .appendOptional(tOffset)
+ .toFormatter();
+ }
+ return dp;
+ }
+
+ private static DateTimeFormatter localDateParser() {
+ if (ldp == null) {
+ return dateElementParser().withZoneUTC();
+ }
+ return ldp;
+ }
+
+ private static DateTimeFormatter dateElementParser() {
+ if (dpe == null) {
+ return new DateTimeFormatterBuilder()
+ .append(null, new DateTimeParser[] {
+ new DateTimeFormatterBuilder()
+ .append(yearElement())
+ .appendOptional
+ (new DateTimeFormatterBuilder()
+ .append(monthElement())
+ .appendOptional(dayOfMonthElement().getParser())
+ .toParser())
+ .toParser(),
+ new DateTimeFormatterBuilder()
+ .append(weekyearElement())
+ .append(weekElement())
+ .appendOptional(dayOfWeekElement().getParser())
+ .toParser(),
+ new DateTimeFormatterBuilder()
+ .append(yearElement())
+ .append(dayOfYearElement())
+ .toParser()
+ })
+ .toFormatter();
+ }
+ return dpe;
+ }
+
+ private static DateTimeFormatter timeParser() {
+ if (tp == null) {
+ return new DateTimeFormatterBuilder()
+ .appendOptional(literalTElement().getParser())
+ .append(timeElementParser())
+ .appendOptional(offsetElement().getParser())
+ .toFormatter();
+ }
+ return tp;
+ }
+
+ private static DateTimeFormatter localTimeParser() {
+ if (ltp == null) {
+ return new DateTimeFormatterBuilder()
+ .appendOptional(literalTElement().getParser())
+ .append(timeElementParser())
+ .toFormatter().withZoneUTC();
+ }
+ return ltp;
+ }
+
+ private static DateTimeFormatter timeElementParser() {
+ if (tpe == null) {
+ // Decimal point can be either '.' or ','
+ DateTimeParser decimalPoint = new DateTimeFormatterBuilder()
+ .append(null, new DateTimeParser[] {
+ new DateTimeFormatterBuilder()
+ .appendLiteral('.')
+ .toParser(),
+ new DateTimeFormatterBuilder()
+ .appendLiteral(',')
+ .toParser()
+ })
+ .toParser();
+
+ return new DateTimeFormatterBuilder()
+ // time-element
+ .append(hourElement())
+ .append
+ (null, new DateTimeParser[] {
+ new DateTimeFormatterBuilder()
+ // minute-element
+ .append(minuteElement())
+ .append
+ (null, new DateTimeParser[] {
+ new DateTimeFormatterBuilder()
+ // second-element
+ .append(secondElement())
+ // second fraction
+ .appendOptional(new DateTimeFormatterBuilder()
+ .append(decimalPoint)
+ .appendFractionOfSecond(1, 9)
+ .toParser())
+ .toParser(),
+ // minute fraction
+ new DateTimeFormatterBuilder()
+ .append(decimalPoint)
+ .appendFractionOfMinute(1, 9)
+ .toParser(),
+ null
+ })
+ .toParser(),
+ // hour fraction
+ new DateTimeFormatterBuilder()
+ .append(decimalPoint)
+ .appendFractionOfHour(1, 9)
+ .toParser(),
+ null
+ })
+ .toFormatter();
+ }
+ return tpe;
+ }
+
+ private static DateTimeFormatter dateTimeParser() {
+ if (dtp == null) {
+ // This is different from the general time parser in that the 'T'
+ // is required.
+ DateTimeParser time = new DateTimeFormatterBuilder()
+ .appendLiteral('T')
+ .append(timeElementParser())
+ .appendOptional(offsetElement().getParser())
+ .toParser();
+ return new DateTimeFormatterBuilder()
+ .append(null, new DateTimeParser[] {time, dateOptionalTimeParser().getParser()})
+ .toFormatter();
+ }
+ return dtp;
+ }
+
+ private static DateTimeFormatter dateOptionalTimeParser() {
+ if (dotp == null) {
+ DateTimeParser timeOrOffset = new DateTimeFormatterBuilder()
+ .appendLiteral('T')
+ .appendOptional(timeElementParser().getParser())
+ .appendOptional(offsetElement().getParser())
+ .toParser();
+ return new DateTimeFormatterBuilder()
+ .append(dateElementParser())
+ .appendOptional(timeOrOffset)
+ .toFormatter();
+ }
+ return dotp;
+ }
+
+ private static DateTimeFormatter localDateOptionalTimeParser() {
+ if (ldotp == null) {
+ DateTimeParser time = new DateTimeFormatterBuilder()
+ .appendLiteral('T')
+ .append(timeElementParser())
+ .toParser();
+ return new DateTimeFormatterBuilder()
+ .append(dateElementParser())
+ .appendOptional(time)
+ .toFormatter().withZoneUTC();
+ }
+ return ldotp;
+ }
+
+ //-----------------------------------------------------------------------
+ private static DateTimeFormatter time() {
+ if (t == null) {
+ return new DateTimeFormatterBuilder()
+ .append(hourMinuteSecondFraction())
+ .append(offsetElement())
+ .toFormatter();
+ }
+ return t;
+ }
+
+ private static DateTimeFormatter timeNoMillis() {
+ if (tx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(hourMinuteSecond())
+ .append(offsetElement())
+ .toFormatter();
+ }
+ return tx;
+ }
+
+ private static DateTimeFormatter tTime() {
+ if (tt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(literalTElement())
+ .append(time())
+ .toFormatter();
+ }
+ return tt;
+ }
+
+ private static DateTimeFormatter tTimeNoMillis() {
+ if (ttx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(literalTElement())
+ .append(timeNoMillis())
+ .toFormatter();
+ }
+ return ttx;
+ }
+
+ private static DateTimeFormatter dateTime() {
+ if (dt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(date())
+ .append(tTime())
+ .toFormatter();
+ }
+ return dt;
+ }
+
+ private static DateTimeFormatter dateTimeNoMillis() {
+ if (dtx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(date())
+ .append(tTimeNoMillis())
+ .toFormatter();
+ }
+ return dtx;
+ }
+
+ private static DateTimeFormatter ordinalDate() {
+ if (od == null) {
+ return new DateTimeFormatterBuilder()
+ .append(yearElement())
+ .append(dayOfYearElement())
+ .toFormatter();
+ }
+ return od;
+ }
+
+ private static DateTimeFormatter ordinalDateTime() {
+ if (odt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(ordinalDate())
+ .append(tTime())
+ .toFormatter();
+ }
+ return odt;
+ }
+
+ private static DateTimeFormatter ordinalDateTimeNoMillis() {
+ if (odtx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(ordinalDate())
+ .append(tTimeNoMillis())
+ .toFormatter();
+ }
+ return odtx;
+ }
+
+ private static DateTimeFormatter weekDateTime() {
+ if (wdt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(weekDate())
+ .append(tTime())
+ .toFormatter();
+ }
+ return wdt;
+ }
+
+ private static DateTimeFormatter weekDateTimeNoMillis() {
+ if (wdtx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(weekDate())
+ .append(tTimeNoMillis())
+ .toFormatter();
+ }
+ return wdtx;
+ }
+
+ //-----------------------------------------------------------------------
+ private static DateTimeFormatter basicDate() {
+ if (bd == null) {
+ return new DateTimeFormatterBuilder()
+ .appendYear(4, 4)
+ .appendFixedDecimal(DateTimeFieldType.monthOfYear(), 2)
+ .appendFixedDecimal(DateTimeFieldType.dayOfMonth(), 2)
+ .toFormatter();
+ }
+ return bd;
+ }
+
+ private static DateTimeFormatter basicTime() {
+ if (bt == null) {
+ return new DateTimeFormatterBuilder()
+ .appendFixedDecimal(DateTimeFieldType.hourOfDay(), 2)
+ .appendFixedDecimal(DateTimeFieldType.minuteOfHour(), 2)
+ .appendFixedDecimal(DateTimeFieldType.secondOfMinute(), 2)
+ .appendLiteral('.')
+ .appendFractionOfSecond(3, 9)
+ .appendTimeZoneOffset("Z", false, 2, 2)
+ .toFormatter();
+ }
+ return bt;
+ }
+
+ private static DateTimeFormatter basicTimeNoMillis() {
+ if (btx == null) {
+ return new DateTimeFormatterBuilder()
+ .appendFixedDecimal(DateTimeFieldType.hourOfDay(), 2)
+ .appendFixedDecimal(DateTimeFieldType.minuteOfHour(), 2)
+ .appendFixedDecimal(DateTimeFieldType.secondOfMinute(), 2)
+ .appendTimeZoneOffset("Z", false, 2, 2)
+ .toFormatter();
+ }
+ return btx;
+ }
+
+ private static DateTimeFormatter basicTTime() {
+ if (btt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(literalTElement())
+ .append(basicTime())
+ .toFormatter();
+ }
+ return btt;
+ }
+
+ private static DateTimeFormatter basicTTimeNoMillis() {
+ if (bttx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(literalTElement())
+ .append(basicTimeNoMillis())
+ .toFormatter();
+ }
+ return bttx;
+ }
+
+ private static DateTimeFormatter basicDateTime() {
+ if (bdt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(basicDate())
+ .append(basicTTime())
+ .toFormatter();
+ }
+ return bdt;
+ }
+
+ private static DateTimeFormatter basicDateTimeNoMillis() {
+ if (bdtx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(basicDate())
+ .append(basicTTimeNoMillis())
+ .toFormatter();
+ }
+ return bdtx;
+ }
+
+ private static DateTimeFormatter basicOrdinalDate() {
+ if (bod == null) {
+ return new DateTimeFormatterBuilder()
+ .appendYear(4, 4)
+ .appendFixedDecimal(DateTimeFieldType.dayOfYear(), 3)
+ .toFormatter();
+ }
+ return bod;
+ }
+
+ private static DateTimeFormatter basicOrdinalDateTime() {
+ if (bodt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(basicOrdinalDate())
+ .append(basicTTime())
+ .toFormatter();
+ }
+ return bodt;
+ }
+
+ private static DateTimeFormatter basicOrdinalDateTimeNoMillis() {
+ if (bodtx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(basicOrdinalDate())
+ .append(basicTTimeNoMillis())
+ .toFormatter();
+ }
+ return bodtx;
+ }
+
+ private static DateTimeFormatter basicWeekDate() {
+ if (bwd == null) {
+ return new DateTimeFormatterBuilder()
+ .appendFixedSignedDecimal(DateTimeFieldType.weekyear(), 4) // ES change, was .appendWeekyear(4, 4)
+ .appendLiteral('W')
+ .appendFixedDecimal(DateTimeFieldType.weekOfWeekyear(), 2)
+ .appendFixedDecimal(DateTimeFieldType.dayOfWeek(), 1)
+ .toFormatter();
+ }
+ return bwd;
+ }
+
+ private static DateTimeFormatter basicWeekDateTime() {
+ if (bwdt == null) {
+ return new DateTimeFormatterBuilder()
+ .append(basicWeekDate())
+ .append(basicTTime())
+ .toFormatter();
+ }
+ return bwdt;
+ }
+
+ private static DateTimeFormatter basicWeekDateTimeNoMillis() {
+ if (bwdtx == null) {
+ return new DateTimeFormatterBuilder()
+ .append(basicWeekDate())
+ .append(basicTTimeNoMillis())
+ .toFormatter();
+ }
+ return bwdtx;
+ }
+
+ //-----------------------------------------------------------------------
+ private static DateTimeFormatter yearMonth() {
+ if (ym == null) {
+ return new DateTimeFormatterBuilder()
+ .append(yearElement())
+ .append(monthElement())
+ .toFormatter();
+ }
+ return ym;
+ }
+
+ private static DateTimeFormatter yearMonthDay() {
+ if (ymd == null) {
+ return new DateTimeFormatterBuilder()
+ .append(yearElement())
+ .append(monthElement())
+ .append(dayOfMonthElement())
+ .toFormatter();
+ }
+ return ymd;
+ }
+
+ private static DateTimeFormatter weekyearWeek() {
+ if (ww == null) {
+ return new DateTimeFormatterBuilder()
+ .append(weekyearElement())
+ .append(weekElement())
+ .toFormatter();
+ }
+ return ww;
+ }
+
+ private static DateTimeFormatter weekyearWeekDay() {
+ if (wwd == null) {
+ return new DateTimeFormatterBuilder()
+ .append(weekyearElement())
+ .append(weekElement())
+ .append(dayOfWeekElement())
+ .toFormatter();
+ }
+ return wwd;
+ }
+
+ private static DateTimeFormatter hourMinute() {
+ if (hm == null) {
+ return new DateTimeFormatterBuilder()
+ .append(hourElement())
+ .append(minuteElement())
+ .toFormatter();
+ }
+ return hm;
+ }
+
+ private static DateTimeFormatter hourMinuteSecond() {
+ if (hms == null) {
+ return new DateTimeFormatterBuilder()
+ .append(hourElement())
+ .append(minuteElement())
+ .append(secondElement())
+ .toFormatter();
+ }
+ return hms;
+ }
+
+ private static DateTimeFormatter hourMinuteSecondMillis() {
+ if (hmsl == null) {
+ return new DateTimeFormatterBuilder()
+ .append(hourElement())
+ .append(minuteElement())
+ .append(secondElement())
+ .appendLiteral('.')
+ .appendFractionOfSecond(3, 3)
+ .toFormatter();
+ }
+ return hmsl;
+ }
+
+ private static DateTimeFormatter hourMinuteSecondFraction() {
+ if (hmsf == null) {
+ return new DateTimeFormatterBuilder()
+ .append(hourElement())
+ .append(minuteElement())
+ .append(secondElement())
+ .append(fractionElement())
+ .toFormatter();
+ }
+ return hmsf;
+ }
+
+ private static DateTimeFormatter dateHour() {
+ if (dh == null) {
+ return new DateTimeFormatterBuilder()
+ .append(date())
+ .append(literalTElement())
+ .append(hour())
+ .toFormatter();
+ }
+ return dh;
+ }
+
+ private static DateTimeFormatter dateHourMinute() {
+ if (dhm == null) {
+ return new DateTimeFormatterBuilder()
+ .append(date())
+ .append(literalTElement())
+ .append(hourMinute())
+ .toFormatter();
+ }
+ return dhm;
+ }
+
+ private static DateTimeFormatter dateHourMinuteSecond() {
+ if (dhms == null) {
+ return new DateTimeFormatterBuilder()
+ .append(date())
+ .append(literalTElement())
+ .append(hourMinuteSecond())
+ .toFormatter();
+ }
+ return dhms;
+ }
+
+ private static DateTimeFormatter dateHourMinuteSecondMillis() {
+ if (dhmsl == null) {
+ return new DateTimeFormatterBuilder()
+ .append(date())
+ .append(literalTElement())
+ .append(hourMinuteSecondMillis())
+ .toFormatter();
+ }
+ return dhmsl;
+ }
+
+ private static DateTimeFormatter dateHourMinuteSecondFraction() {
+ if (dhmsf == null) {
+ return new DateTimeFormatterBuilder()
+ .append(date())
+ .append(literalTElement())
+ .append(hourMinuteSecondFraction())
+ .toFormatter();
+ }
+ return dhmsf;
+ }
+
+ //-----------------------------------------------------------------------
+ private static DateTimeFormatter yearElement() {
+ if (ye == null) {
+ return new DateTimeFormatterBuilder()
+ .appendFixedSignedDecimal(DateTimeFieldType.year(), 4) // ES change, was .appendYear(4, 9)
+ .toFormatter();
+ }
+ return ye;
+ }
+
+ private static DateTimeFormatter monthElement() {
+ if (mye == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral('-')
+ .appendFixedSignedDecimal(DateTimeFieldType.monthOfYear(), 2) // ES change, was .appendMonthOfYear(2)
+ .toFormatter();
+ }
+ return mye;
+ }
+
+ private static DateTimeFormatter dayOfMonthElement() {
+ if (dme == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral('-')
+ .appendFixedSignedDecimal(DateTimeFieldType.dayOfMonth(), 2) // ES change, was .appendDayOfMonth(2)
+ .toFormatter();
+ }
+ return dme;
+ }
+
+ private static DateTimeFormatter weekyearElement() {
+ if (we == null) {
+ return new DateTimeFormatterBuilder()
+ .appendFixedSignedDecimal(DateTimeFieldType.weekyear(), 4) // ES change, was .appendWeekyear(4, 9)
+ .toFormatter();
+ }
+ return we;
+ }
+
+ private static DateTimeFormatter weekElement() {
+ if (wwe == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral("-W")
+ .appendFixedSignedDecimal(DateTimeFieldType.weekOfWeekyear(), 2) // ES change, was .appendWeekOfWeekyear(2)
+ .toFormatter();
+ }
+ return wwe;
+ }
+
+ private static DateTimeFormatter dayOfWeekElement() {
+ if (dwe == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral('-')
+ .appendDayOfWeek(1)
+ .toFormatter();
+ }
+ return dwe;
+ }
+
+ private static DateTimeFormatter dayOfYearElement() {
+ if (dye == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral('-')
+ .appendFixedSignedDecimal(DateTimeFieldType.dayOfYear(), 3) // ES change, was .appendDayOfYear(3)
+ .toFormatter();
+ }
+ return dye;
+ }
+
+ private static DateTimeFormatter literalTElement() {
+ if (lte == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral('T')
+ .toFormatter();
+ }
+ return lte;
+ }
+
+ private static DateTimeFormatter hourElement() {
+ if (hde == null) {
+ return new DateTimeFormatterBuilder()
+ .appendFixedSignedDecimal(DateTimeFieldType.hourOfDay(), 2) // ES change, was .appendHourOfDay(2)
+ .toFormatter();
+ }
+ return hde;
+ }
+
+ private static DateTimeFormatter minuteElement() {
+ if (mhe == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral(':')
+ .appendFixedSignedDecimal(DateTimeFieldType.minuteOfHour(), 2) // ES change, was .appendMinuteOfHour(2)
+ .toFormatter();
+ }
+ return mhe;
+ }
+
+ private static DateTimeFormatter secondElement() {
+ if (sme == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral(':')
+ .appendFixedSignedDecimal(DateTimeFieldType.secondOfMinute(), 2) // ES change, was .appendSecondOfMinute(2)
+ .toFormatter();
+ }
+ return sme;
+ }
+
+ private static DateTimeFormatter fractionElement() {
+ if (fse == null) {
+ return new DateTimeFormatterBuilder()
+ .appendLiteral('.')
+ // Support parsing up to nanosecond precision even though
+ // those extra digits will be dropped.
+ .appendFractionOfSecond(3, 9)
+ .toFormatter();
+ }
+ return fse;
+ }
+
+ private static DateTimeFormatter offsetElement() {
+ if (ze == null) {
+ return new DateTimeFormatterBuilder()
+ .appendTimeZoneOffset("Z", true, 2, 4)
+ .toFormatter();
+ }
+ return ze;
+ }
+
+ }
+
+}
diff --git a/core/src/main/resources/org/elasticsearch/bootstrap/security.policy b/core/src/main/resources/org/elasticsearch/bootstrap/security.policy
index 0434bf5be31aa..157c3cffeb07f 100644
--- a/core/src/main/resources/org/elasticsearch/bootstrap/security.policy
+++ b/core/src/main/resources/org/elasticsearch/bootstrap/security.policy
@@ -47,6 +47,11 @@ grant codeBase "${es.security.jar.elasticsearch.securemock}" {
permission java.lang.RuntimePermission "reflectionFactoryAccess";
};
+grant codeBase "${es.security.jar.bouncycastle.bcprov}" {
+ // needed to allow installation of bouncycastle crypto provider
+ permission java.security.SecurityPermission "putProviderProperty.BC";
+};
+
//// Everything else:
grant {
diff --git a/core/src/test/java/org/elasticsearch/NamingConventionTests.java b/core/src/test/java/org/elasticsearch/NamingConventionTests.java
index db39c66f30bab..11a87671433f6 100644
--- a/core/src/test/java/org/elasticsearch/NamingConventionTests.java
+++ b/core/src/test/java/org/elasticsearch/NamingConventionTests.java
@@ -75,7 +75,10 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
if (filename.endsWith(".class")) {
Class> clazz = loadClass(filename);
if (Modifier.isAbstract(clazz.getModifiers()) == false && Modifier.isInterface(clazz.getModifiers()) == false) {
- if ((clazz.getName().endsWith("Tests") || clazz.getName().endsWith("Test"))) { // don't worry about the ones that match the pattern
+ if (clazz.getName().endsWith("Tests") ||
+ clazz.getName().endsWith("IT") ||
+ clazz.getName().endsWith("Test")) { // don't worry about the ones that match the pattern
+
if (isTestCase(clazz) == false) {
notImplementing.add(clazz);
}
diff --git a/core/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsTests.java b/core/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsTests.java
index 12467ecef5925..a78c8b6e7a162 100644
--- a/core/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsTests.java
+++ b/core/src/test/java/org/elasticsearch/action/termvectors/GetTermVectorsTests.java
@@ -37,7 +37,7 @@
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.engine.VersionConflictEngineException;
-import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
+import org.elasticsearch.index.mapper.FieldMapper;
import org.hamcrest.Matcher;
import org.junit.Test;
@@ -273,7 +273,7 @@ public void testRandomSingleTermVectors() throws IOException {
ft.setStoreTermVectorPayloads(storePayloads);
ft.setStoreTermVectorPositions(storePositions);
- String optionString = AbstractFieldMapper.termVectorOptionsToString(ft);
+ String optionString = FieldMapper.termVectorOptionsToString(ft);
XContentBuilder mapping = jsonBuilder().startObject().startObject("type1")
.startObject("properties")
.startObject("field")
diff --git a/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java b/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java
index a981aaff1e073..f9c4d2f39f0e3 100644
--- a/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java
+++ b/core/src/test/java/org/elasticsearch/action/termvectors/TermVectorsUnitTests.java
@@ -37,8 +37,8 @@
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperParsingException;
-import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
import org.elasticsearch.index.mapper.core.TypeParsers;
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
import org.elasticsearch.rest.action.termvectors.RestTermVectorsAction;
@@ -266,7 +266,7 @@ public void testFieldTypeToTermVectorString() throws Exception {
ft.setStoreTermVectorPayloads(true);
ft.setStoreTermVectors(true);
ft.setStoreTermVectorPositions(true);
- String ftOpts = AbstractFieldMapper.termVectorOptionsToString(ft);
+ String ftOpts = FieldMapper.termVectorOptionsToString(ft);
assertThat("with_positions_payloads", equalTo(ftOpts));
AllFieldMapper.Builder builder = new AllFieldMapper.Builder(null);
boolean exceptiontrown = false;
@@ -285,7 +285,7 @@ public void testTermVectorStringGenerationWithoutPositions() throws Exception {
ft.setStoreTermVectorPayloads(true);
ft.setStoreTermVectors(true);
ft.setStoreTermVectorPositions(false);
- String ftOpts = AbstractFieldMapper.termVectorOptionsToString(ft);
+ String ftOpts = FieldMapper.termVectorOptionsToString(ft);
assertThat(ftOpts, equalTo("with_offsets"));
}
diff --git a/core/src/test/java/org/elasticsearch/action/update/UpdateRequestTests.java b/core/src/test/java/org/elasticsearch/action/update/UpdateRequestTests.java
index b5b8d63a2a90e..e127ec81511a8 100644
--- a/core/src/test/java/org/elasticsearch/action/update/UpdateRequestTests.java
+++ b/core/src/test/java/org/elasticsearch/action/update/UpdateRequestTests.java
@@ -19,8 +19,13 @@
package org.elasticsearch.action.update;
+import org.elasticsearch.Version;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.common.io.stream.Streamable;
+import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
+import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.test.ElasticsearchTestCase;
@@ -28,9 +33,10 @@
import java.util.Map;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.hamcrest.Matchers.nullValue;
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
public class UpdateRequestTests extends ElasticsearchTestCase {
@@ -119,4 +125,45 @@ public void testUpdateRequest() throws Exception {
assertThat(doc.get("field1").toString(), equalTo("value1"));
assertThat(((Map) doc.get("compound")).get("field2").toString(), equalTo("value2"));
}
+
+ @Test // Related to issue 3256
+ public void testUpdateRequestWithTTL() throws Exception {
+ long providedTTLValue = randomIntBetween(500, 1000);
+ Settings settings = settings(Version.CURRENT).build();
+
+ UpdateHelper updateHelper = new UpdateHelper(settings, null);
+
+ // We just upsert one document with ttl
+ IndexRequest indexRequest = new IndexRequest("test", "type1", "1")
+ .source(jsonBuilder().startObject().field("foo", "bar").endObject())
+ .ttl(providedTTLValue);
+ UpdateRequest updateRequest = new UpdateRequest("test", "type1", "1")
+ .doc(jsonBuilder().startObject().field("fooz", "baz").endObject())
+ .upsert(indexRequest);
+
+ // We simulate that the document is not existing yet
+ GetResult getResult = new GetResult("test", "type1", "1", 0, false, null, null);
+ UpdateHelper.Result result = updateHelper.prepare(updateRequest, getResult);
+ Streamable action = result.action();
+ assertThat(action, instanceOf(IndexRequest.class));
+ IndexRequest indexAction = (IndexRequest) action;
+ assertThat(indexAction.ttl(), is(providedTTLValue));
+
+ // We just upsert one document with ttl using a script
+ indexRequest = new IndexRequest("test", "type1", "2")
+ .source(jsonBuilder().startObject().field("foo", "bar").endObject())
+ .ttl(providedTTLValue);
+ updateRequest = new UpdateRequest("test", "type1", "2")
+ .upsert(indexRequest)
+ .script(new Script(";"))
+ .scriptedUpsert(true);
+
+ // We simulate that the document is not existing yet
+ getResult = new GetResult("test", "type1", "2", 0, false, null, null);
+ result = updateHelper.prepare(updateRequest, getResult);
+ action = result.action();
+ assertThat(action, instanceOf(IndexRequest.class));
+ indexAction = (IndexRequest) action;
+ assertThat(indexAction.ttl(), is(providedTTLValue));
+ }
}
diff --git a/core/src/test/java/org/elasticsearch/bootstrap/JarHellTests.java b/core/src/test/java/org/elasticsearch/bootstrap/JarHellTests.java
new file mode 100644
index 0000000000000..d87a7e295f185
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/bootstrap/JarHellTests.java
@@ -0,0 +1,206 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.bootstrap;
+
+import org.elasticsearch.test.ElasticsearchTestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.jar.Attributes;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public class JarHellTests extends ElasticsearchTestCase {
+
+ URL makeJar(Path dir, String name, Manifest manifest, String... files) throws IOException {
+ Path jarpath = dir.resolve(name);
+ ZipOutputStream out;
+ if (manifest == null) {
+ out = new JarOutputStream(Files.newOutputStream(jarpath, StandardOpenOption.CREATE));
+ } else {
+ out = new JarOutputStream(Files.newOutputStream(jarpath, StandardOpenOption.CREATE), manifest);
+ }
+ for (String file : files) {
+ out.putNextEntry(new ZipEntry(file));
+ }
+ out.close();
+ return jarpath.toUri().toURL();
+ }
+
+ URL makeFile(Path dir, String name) throws IOException {
+ Path filepath = dir.resolve(name);
+ Files.newOutputStream(filepath, StandardOpenOption.CREATE).close();
+ return filepath.toUri().toURL();
+ }
+
+ public void testDifferentJars() throws Exception {
+ Path dir = createTempDir();
+ URL[] jars = {makeJar(dir, "foo.jar", null, "DuplicateClass.class"), makeJar(dir, "bar.jar", null, "DuplicateClass.class")};
+ try {
+ JarHell.checkJarHell(jars);
+ } catch (IllegalStateException e) {
+ assertTrue(e.getMessage().contains("jar hell!"));
+ assertTrue(e.getMessage().contains("DuplicateClass"));
+ assertTrue(e.getMessage().contains("foo.jar"));
+ assertTrue(e.getMessage().contains("bar.jar"));
+ }
+ }
+
+ public void testBootclasspathLeniency() throws Exception {
+ Path dir = createTempDir();
+ String previousJavaHome = System.getProperty("java.home");
+ System.setProperty("java.home", dir.toString());
+ URL[] jars = {makeJar(dir, "foo.jar", null, "DuplicateClass.class"), makeJar(dir, "bar.jar", null, "DuplicateClass.class")};
+ try {
+ JarHell.checkJarHell(jars);
+ } finally {
+ System.setProperty("java.home", previousJavaHome);
+ }
+ }
+
+ public void testDuplicateClasspathLeniency() throws Exception {
+ Path dir = createTempDir();
+ URL jar = makeJar(dir, "foo.jar", null, "Foo.class");
+ URL[] jars = {jar, jar};
+ JarHell.checkJarHell(jars);
+ }
+
+ public void testDirsOnClasspath() throws Exception {
+ Path dir1 = createTempDir();
+ Path dir2 = createTempDir();
+ URL[] dirs = {makeFile(dir1, "DuplicateClass.class"), makeFile(dir2, "DuplicateClass.class")};
+ try {
+ JarHell.checkJarHell(dirs);
+ } catch (IllegalStateException e) {
+ assertTrue(e.getMessage().contains("jar hell!"));
+ assertTrue(e.getMessage().contains("DuplicateClass"));
+ assertTrue(e.getMessage().contains(dir1.toString()));
+ assertTrue(e.getMessage().contains(dir2.toString()));
+ }
+ }
+
+ public void testDirAndJar() throws Exception {
+ Path dir1 = createTempDir();
+ Path dir2 = createTempDir();
+ URL[] dirs = {makeJar(dir1, "foo.jar", null, "DuplicateClass.class"), makeFile(dir2, "DuplicateClass.class")};
+ try {
+ JarHell.checkJarHell(dirs);
+ } catch (IllegalStateException e) {
+ assertTrue(e.getMessage().contains("jar hell!"));
+ assertTrue(e.getMessage().contains("DuplicateClass"));
+ assertTrue(e.getMessage().contains("foo.jar"));
+ assertTrue(e.getMessage().contains(dir2.toString()));
+ }
+ }
+
+ public void testLog4jLeniency() throws Exception {
+ Path dir = createTempDir();
+ URL[] jars = {makeJar(dir, "foo.jar", null, "org/apache/log4j/DuplicateClass.class"), makeJar(dir, "bar.jar", null, "org/apache/log4j/DuplicateClass.class")};
+ JarHell.checkJarHell(jars);
+ }
+
+ public void testBaseDateTimeLeniency() throws Exception {
+ Path dir = createTempDir();
+ URL[] jars = {makeJar(dir, "foo.jar", null, "org/joda/time/base/BaseDateTime.class"), makeJar(dir, "bar.jar", null, "org/joda/time/base/BaseDateTime.class")};
+ JarHell.checkJarHell(jars);
+ }
+
+ public void testWithinSingleJar() throws Exception {
+ // the java api for zip file does not allow creating duplicate entries (good!) so
+ // this bogus jar had to be constructed with ant
+ URL[] jars = {JarHellTests.class.getResource("duplicate-classes.jar")};
+ try {
+ JarHell.checkJarHell(jars);
+ } catch (IllegalStateException e) {
+ assertTrue(e.getMessage().contains("jar hell!"));
+ assertTrue(e.getMessage().contains("DuplicateClass"));
+ assertTrue(e.getMessage().contains("duplicate-classes.jar"));
+ assertTrue(e.getMessage().contains("exists multiple times in jar"));
+ }
+ }
+
+ public void testXmlBeansLeniency() throws Exception {
+ URL[] jars = {JarHellTests.class.getResource("duplicate-xmlbeans-classes.jar")};
+ JarHell.checkJarHell(jars);
+ }
+
+ public void testRequiredJDKVersionTooOld() throws Exception {
+ Path dir = createTempDir();
+ String previousJavaVersion = System.getProperty("java.specification.version");
+ System.setProperty("java.specification.version", "1.7");
+
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "1.8");
+ URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
+ try {
+ JarHell.checkJarHell(jars);
+ } catch (IllegalStateException e) {
+ assertTrue(e.getMessage().contains("requires java 1.8"));
+ assertTrue(e.getMessage().contains("your system: 1.7"));
+ } finally {
+ System.setProperty("java.specification.version", previousJavaVersion);
+ }
+ }
+
+ public void testRequiredJDKVersionIsOK() throws Exception {
+ Path dir = createTempDir();
+ String previousJavaVersion = System.getProperty("java.specification.version");
+ System.setProperty("java.specification.version", "1.7");
+
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "1.7");
+ URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
+ try {
+ JarHell.checkJarHell(jars);
+ } finally {
+ System.setProperty("java.specification.version", previousJavaVersion);
+ }
+ }
+
+ public void testBadJDKVersionProperty() throws Exception {
+ Path dir = createTempDir();
+ String previousJavaVersion = System.getProperty("java.specification.version");
+ System.setProperty("java.specification.version", "bogus");
+
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "1.7");
+ URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
+ try {
+ JarHell.checkJarHell(jars);
+ } finally {
+ System.setProperty("java.specification.version", previousJavaVersion);
+ }
+ }
+
+ public void testBadJDKVersionInJar() throws Exception {
+ Path dir = createTempDir();
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "bogus");
+ URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
+ JarHell.checkJarHell(jars);
+ }
+}
diff --git a/core/src/test/java/org/elasticsearch/bootstrap/SecurityTests.java b/core/src/test/java/org/elasticsearch/bootstrap/SecurityTests.java
index 980e9dca3419b..51d08d05bf73a 100644
--- a/core/src/test/java/org/elasticsearch/bootstrap/SecurityTests.java
+++ b/core/src/test/java/org/elasticsearch/bootstrap/SecurityTests.java
@@ -204,4 +204,28 @@ public void testProcessExecution() throws Exception {
fail("didn't get expected exception");
} catch (SecurityException expected) {}
}
+
+ /** When a configured dir is a symlink, test that permissions work on link target */
+ public void testSymlinkPermissions() throws IOException {
+ Path dir = createTempDir();
+
+ Path target = dir.resolve("target");
+ Files.createDirectory(target);
+
+ // symlink
+ Path link = dir.resolve("link");
+ try {
+ Files.createSymbolicLink(link, target);
+ } catch (UnsupportedOperationException | IOException e) {
+ assumeNoException("test requires filesystem that supports symbolic links", e);
+ } catch (SecurityException e) {
+ assumeNoException("test cannot create symbolic links with security manager enabled", e);
+ }
+ Permissions permissions = new Permissions();
+ Security.addPath(permissions, link, "read");
+ assertTrue(permissions.implies(new FilePermission(link.toString(), "read")));
+ assertTrue(permissions.implies(new FilePermission(link.resolve("foo").toString(), "read")));
+ assertTrue(permissions.implies(new FilePermission(target.toString(), "read")));
+ assertTrue(permissions.implies(new FilePermission(target.resolve("foo").toString(), "read")));
+ }
}
diff --git a/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesTests.java b/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesTests.java
index db4bb5765522e..1db310c477087 100644
--- a/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesTests.java
+++ b/core/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/MockDiskUsagesTests.java
@@ -32,7 +32,7 @@
import org.elasticsearch.cluster.routing.RoutingNode;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.monitor.fs.FsStats;
+import org.elasticsearch.monitor.fs.FsInfo;
import org.elasticsearch.node.settings.NodeSettingsService;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.threadpool.ThreadPool;
@@ -141,15 +141,15 @@ public void run() {
/** Create a fake NodeStats for the given node and usage */
public static NodeStats makeStats(String nodeName, DiskUsage usage) {
- FsStats.Info[] infos = new FsStats.Info[1];
- FsStats.Info info = new FsStats.Info("/path.data", null, null,
- usage.getTotalBytes(), usage.getFreeBytes(), usage.getFreeBytes(), -1, -1, -1, -1, -1, -1);
- infos[0] = info;
- FsStats fsStats = new FsStats(System.currentTimeMillis(), infos);
+ FsInfo.Path[] paths = new FsInfo.Path[1];
+ FsInfo.Path path = new FsInfo.Path("/path.data", null,
+ usage.getTotalBytes(), usage.getFreeBytes(), usage.getFreeBytes());
+ paths[0] = path;
+ FsInfo fsInfo = new FsInfo(System.currentTimeMillis(), paths);
return new NodeStats(new DiscoveryNode(nodeName, null, Version.V_2_0_0),
System.currentTimeMillis(),
- null, null, null, null, null, null,
- fsStats,
+ null, null, null, null, null,
+ fsInfo,
null, null, null);
}
diff --git a/core/src/test/java/org/elasticsearch/deps/joda/SimpleJodaTests.java b/core/src/test/java/org/elasticsearch/deps/joda/SimpleJodaTests.java
index 748573db00775..21c16d81b4aa2 100644
--- a/core/src/test/java/org/elasticsearch/deps/joda/SimpleJodaTests.java
+++ b/core/src/test/java/org/elasticsearch/deps/joda/SimpleJodaTests.java
@@ -22,8 +22,11 @@
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.index.mapper.core.DateFieldMapper;
+import org.elasticsearch.index.mapper.object.RootObjectMapper;
import org.elasticsearch.test.ElasticsearchTestCase;
import org.joda.time.DateTime;
+import org.joda.time.DateTimeFieldType;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.joda.time.MutableDateTime;
@@ -361,6 +364,368 @@ public void testThatEpochParserIsIdempotent() {
assertThat(secondsDateTime.getMillis(), is(1234567890000l));
}
+ public void testThatDefaultFormatterChecksForCorrectYearLength() throws Exception {
+ // if no strict version is tested, this means the date format is already strict by itself
+ // yyyyMMdd
+ assertValidDateFormatParsing("basicDate", "20140303");
+ assertDateFormatParsingThrowingException("basicDate", "2010303");
+
+ // yyyyMMdd’T'HHmmss.SSSZ
+ assertValidDateFormatParsing("basicDateTime", "20140303T124343.123Z");
+ assertValidDateFormatParsing("basicDateTime", "00050303T124343.123Z");
+ assertDateFormatParsingThrowingException("basicDateTime", "50303T124343.123Z");
+
+ // yyyyMMdd’T'HHmmssZ
+ assertValidDateFormatParsing("basicDateTimeNoMillis", "20140303T124343Z");
+ assertValidDateFormatParsing("basicDateTimeNoMillis", "00050303T124343Z");
+ assertDateFormatParsingThrowingException("basicDateTimeNoMillis", "50303T124343Z");
+
+ // yyyyDDD
+ assertValidDateFormatParsing("basicOrdinalDate", "0005165");
+ assertDateFormatParsingThrowingException("basicOrdinalDate", "5165");
+
+ // yyyyDDD’T'HHmmss.SSSZ
+ assertValidDateFormatParsing("basicOrdinalDateTime", "0005165T124343.123Z");
+ assertValidDateFormatParsing("basicOrdinalDateTime", "0005165T124343.123Z");
+ assertDateFormatParsingThrowingException("basicOrdinalDateTime", "5165T124343.123Z");
+
+ // yyyyDDD’T'HHmmssZ
+ assertValidDateFormatParsing("basicOrdinalDateTimeNoMillis", "0005165T124343Z");
+ assertValidDateFormatParsing("basicOrdinalDateTimeNoMillis", "0005165T124343Z");
+ assertDateFormatParsingThrowingException("basicOrdinalDateTimeNoMillis", "5165T124343Z");
+
+ // HHmmss.SSSZ
+ assertValidDateFormatParsing("basicTime", "090909.123Z");
+ assertDateFormatParsingThrowingException("basicTime", "90909.123Z");
+
+ // HHmmssZ
+ assertValidDateFormatParsing("basicTimeNoMillis", "090909Z");
+ assertDateFormatParsingThrowingException("basicTimeNoMillis", "90909Z");
+
+ // 'T’HHmmss.SSSZ
+ assertValidDateFormatParsing("basicTTime", "T090909.123Z");
+ assertDateFormatParsingThrowingException("basicTTime", "T90909.123Z");
+
+ // T’HHmmssZ
+ assertValidDateFormatParsing("basicTTimeNoMillis", "T090909Z");
+ assertDateFormatParsingThrowingException("basicTTimeNoMillis", "T90909Z");
+
+ // xxxx’W'wwe
+ assertValidDateFormatParsing("basicWeekDate", "0005W414");
+ assertValidDateFormatParsing("basicWeekDate", "5W414", "0005W414");
+ assertDateFormatParsingThrowingException("basicWeekDate", "5W14");
+
+ assertValidDateFormatParsing("strictBasicWeekDate", "0005W414");
+ assertDateFormatParsingThrowingException("strictBasicWeekDate", "0005W47");
+ assertDateFormatParsingThrowingException("strictBasicWeekDate", "5W414");
+ assertDateFormatParsingThrowingException("strictBasicWeekDate", "5W14");
+
+ // xxxx’W'wwe’T'HHmmss.SSSZ
+ assertValidDateFormatParsing("basicWeekDateTime", "0005W414T124343.123Z");
+ assertValidDateFormatParsing("basicWeekDateTime", "5W414T124343.123Z", "0005W414T124343.123Z");
+ assertDateFormatParsingThrowingException("basicWeekDateTime", "5W14T124343.123Z");
+
+ assertValidDateFormatParsing("strictBasicWeekDateTime", "0005W414T124343.123Z");
+ assertDateFormatParsingThrowingException("strictBasicWeekDateTime", "0005W47T124343.123Z");
+ assertDateFormatParsingThrowingException("strictBasicWeekDateTime", "5W414T124343.123Z");
+ assertDateFormatParsingThrowingException("strictBasicWeekDateTime", "5W14T124343.123Z");
+
+ // xxxx’W'wwe’T'HHmmssZ
+ assertValidDateFormatParsing("basicWeekDateTimeNoMillis", "0005W414T124343Z");
+ assertValidDateFormatParsing("basicWeekDateTimeNoMillis", "5W414T124343Z", "0005W414T124343Z");
+ assertDateFormatParsingThrowingException("basicWeekDateTimeNoMillis", "5W14T124343Z");
+
+ assertValidDateFormatParsing("strictBasicWeekDateTimeNoMillis", "0005W414T124343Z");
+ assertDateFormatParsingThrowingException("strictBasicWeekDateTimeNoMillis", "0005W47T124343Z");
+ assertDateFormatParsingThrowingException("strictBasicWeekDateTimeNoMillis", "5W414T124343Z");
+ assertDateFormatParsingThrowingException("strictBasicWeekDateTimeNoMillis", "5W14T124343Z");
+
+ // yyyy-MM-dd
+ assertValidDateFormatParsing("date", "0005-06-03");
+ assertValidDateFormatParsing("date", "5-6-3", "0005-06-03");
+
+ assertValidDateFormatParsing("strictDate", "0005-06-03");
+ assertDateFormatParsingThrowingException("strictDate", "5-6-3");
+ assertDateFormatParsingThrowingException("strictDate", "0005-06-3");
+ assertDateFormatParsingThrowingException("strictDate", "0005-6-03");
+ assertDateFormatParsingThrowingException("strictDate", "5-06-03");
+
+ // yyyy-MM-dd'T'HH
+ assertValidDateFormatParsing("dateHour", "0005-06-03T12");
+ assertValidDateFormatParsing("dateHour", "5-6-3T1", "0005-06-03T01");
+
+ assertValidDateFormatParsing("strictDateHour", "0005-06-03T12");
+ assertDateFormatParsingThrowingException("strictDateHour", "5-6-3T1");
+
+ // yyyy-MM-dd'T'HH:mm
+ assertValidDateFormatParsing("dateHourMinute", "0005-06-03T12:12");
+ assertValidDateFormatParsing("dateHourMinute", "5-6-3T12:1", "0005-06-03T12:01");
+
+ assertValidDateFormatParsing("strictDateHourMinute", "0005-06-03T12:12");
+ assertDateFormatParsingThrowingException("strictDateHourMinute", "5-6-3T12:1");
+
+ // yyyy-MM-dd'T'HH:mm:ss
+ assertValidDateFormatParsing("dateHourMinuteSecond", "0005-06-03T12:12:12");
+ assertValidDateFormatParsing("dateHourMinuteSecond", "5-6-3T12:12:1", "0005-06-03T12:12:01");
+
+ assertValidDateFormatParsing("strictDateHourMinuteSecond", "0005-06-03T12:12:12");
+ assertDateFormatParsingThrowingException("strictDateHourMinuteSecond", "5-6-3T12:12:1");
+
+ // yyyy-MM-dd’T'HH:mm:ss.SSS
+ assertValidDateFormatParsing("dateHourMinuteSecondFraction", "0005-06-03T12:12:12.123");
+ assertValidDateFormatParsing("dateHourMinuteSecondFraction", "5-6-3T12:12:1.123", "0005-06-03T12:12:01.123");
+ assertValidDateFormatParsing("dateHourMinuteSecondFraction", "5-6-3T12:12:1.1", "0005-06-03T12:12:01.100");
+
+ assertValidDateFormatParsing("strictDateHourMinuteSecondFraction", "0005-06-03T12:12:12.123");
+ assertDateFormatParsingThrowingException("strictDateHourMinuteSecondFraction", "5-6-3T12:12:12.1");
+ assertDateFormatParsingThrowingException("strictDateHourMinuteSecondFraction", "5-6-3T12:12:12.12");
+
+ assertValidDateFormatParsing("dateHourMinuteSecondMillis", "0005-06-03T12:12:12.123");
+ assertValidDateFormatParsing("dateHourMinuteSecondMillis", "5-6-3T12:12:1.123", "0005-06-03T12:12:01.123");
+ assertValidDateFormatParsing("dateHourMinuteSecondMillis", "5-6-3T12:12:1.1", "0005-06-03T12:12:01.100");
+
+ assertValidDateFormatParsing("strictDateHourMinuteSecondMillis", "0005-06-03T12:12:12.123");
+ assertDateFormatParsingThrowingException("strictDateHourMinuteSecondMillis", "5-6-3T12:12:12.1");
+ assertDateFormatParsingThrowingException("strictDateHourMinuteSecondMillis", "5-6-3T12:12:12.12");
+
+ // yyyy-MM-dd'T'HH:mm:ss.SSSZ
+ assertValidDateFormatParsing("dateOptionalTime", "2014-03-03", "2014-03-03T00:00:00.000Z");
+ assertValidDateFormatParsing("dateOptionalTime", "1257-3-03", "1257-03-03T00:00:00.000Z");
+ assertValidDateFormatParsing("dateOptionalTime", "0005-03-3", "0005-03-03T00:00:00.000Z");
+ assertValidDateFormatParsing("dateOptionalTime", "5-03-03", "0005-03-03T00:00:00.000Z");
+ assertValidDateFormatParsing("dateOptionalTime", "5-03-03T1:1:1.1", "0005-03-03T01:01:01.100Z");
+ assertValidDateFormatParsing("strictDateOptionalTime", "2014-03-03", "2014-03-03T00:00:00.000Z");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "0005-3-03");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "0005-03-3");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T1:1:1.1");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T01:01:01.1");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T01:01:1.100");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T01:1:01.100");
+ assertDateFormatParsingThrowingException("strictDateOptionalTime", "5-03-03T1:01:01.100");
+
+ // yyyy-MM-dd’T'HH:mm:ss.SSSZZ
+ assertValidDateFormatParsing("dateTime", "5-03-03T1:1:1.1Z", "0005-03-03T01:01:01.100Z");
+ assertValidDateFormatParsing("strictDateTime", "2014-03-03T11:11:11.100Z", "2014-03-03T11:11:11.100Z");
+ assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T1:1:1.1Z");
+ assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T01:01:1.100Z");
+ assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T01:1:01.100Z");
+ assertDateFormatParsingThrowingException("strictDateTime", "0005-03-03T1:01:01.100Z");
+
+ // yyyy-MM-dd’T'HH:mm:ssZZ
+ assertValidDateFormatParsing("dateTimeNoMillis", "5-03-03T1:1:1Z", "0005-03-03T01:01:01Z");
+ assertValidDateFormatParsing("strictDateTimeNoMillis", "2014-03-03T11:11:11Z", "2014-03-03T11:11:11Z");
+ assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T1:1:1Z");
+ assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T01:01:1Z");
+ assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T01:1:01Z");
+ assertDateFormatParsingThrowingException("strictDateTimeNoMillis", "0005-03-03T1:01:01Z");
+
+ // HH
+ assertValidDateFormatParsing("hour", "12");
+ assertValidDateFormatParsing("hour", "1", "01");
+ assertValidDateFormatParsing("strictHour", "12");
+ assertValidDateFormatParsing("strictHour", "01");
+ assertDateFormatParsingThrowingException("strictHour", "1");
+
+ // HH:mm
+ assertValidDateFormatParsing("hourMinute", "12:12");
+ assertValidDateFormatParsing("hourMinute", "12:1", "12:01");
+ assertValidDateFormatParsing("strictHourMinute", "12:12");
+ assertValidDateFormatParsing("strictHourMinute", "12:01");
+ assertDateFormatParsingThrowingException("strictHourMinute", "12:1");
+
+ // HH:mm:ss
+ assertValidDateFormatParsing("hourMinuteSecond", "12:12:12");
+ assertValidDateFormatParsing("hourMinuteSecond", "12:12:1", "12:12:01");
+ assertValidDateFormatParsing("strictHourMinuteSecond", "12:12:12");
+ assertValidDateFormatParsing("strictHourMinuteSecond", "12:12:01");
+ assertDateFormatParsingThrowingException("strictHourMinuteSecond", "12:12:1");
+
+ // HH:mm:ss.SSS
+ assertValidDateFormatParsing("hourMinuteSecondFraction", "12:12:12.123");
+ assertValidDateFormatParsing("hourMinuteSecondFraction", "12:12:12.1", "12:12:12.100");
+ assertValidDateFormatParsing("strictHourMinuteSecondFraction", "12:12:12.123");
+ assertValidDateFormatParsing("strictHourMinuteSecondFraction", "12:12:12.1", "12:12:12.100");
+
+ assertValidDateFormatParsing("hourMinuteSecondMillis", "12:12:12.123");
+ assertValidDateFormatParsing("hourMinuteSecondMillis", "12:12:12.1", "12:12:12.100");
+ assertValidDateFormatParsing("strictHourMinuteSecondMillis", "12:12:12.123");
+ assertValidDateFormatParsing("strictHourMinuteSecondMillis", "12:12:12.1", "12:12:12.100");
+
+ // yyyy-DDD
+ assertValidDateFormatParsing("ordinalDate", "5-3", "0005-003");
+ assertValidDateFormatParsing("strictOrdinalDate", "0005-003");
+ assertDateFormatParsingThrowingException("strictOrdinalDate", "5-3");
+ assertDateFormatParsingThrowingException("strictOrdinalDate", "0005-3");
+ assertDateFormatParsingThrowingException("strictOrdinalDate", "5-003");
+
+ // yyyy-DDD’T'HH:mm:ss.SSSZZ
+ assertValidDateFormatParsing("ordinalDateTime", "5-3T12:12:12.100Z", "0005-003T12:12:12.100Z");
+ assertValidDateFormatParsing("strictOrdinalDateTime", "0005-003T12:12:12.100Z");
+ assertDateFormatParsingThrowingException("strictOrdinalDateTime", "5-3T1:12:12.123Z");
+ assertDateFormatParsingThrowingException("strictOrdinalDateTime", "5-3T12:1:12.123Z");
+ assertDateFormatParsingThrowingException("strictOrdinalDateTime", "5-3T12:12:1.123Z");
+
+ // yyyy-DDD’T'HH:mm:ssZZ
+ assertValidDateFormatParsing("ordinalDateTimeNoMillis", "5-3T12:12:12Z", "0005-003T12:12:12Z");
+ assertValidDateFormatParsing("strictOrdinalDateTimeNoMillis", "0005-003T12:12:12Z");
+ assertDateFormatParsingThrowingException("strictOrdinalDateTimeNoMillis", "5-3T1:12:12Z");
+ assertDateFormatParsingThrowingException("strictOrdinalDateTimeNoMillis", "5-3T12:1:12Z");
+ assertDateFormatParsingThrowingException("strictOrdinalDateTimeNoMillis", "5-3T12:12:1Z");
+
+
+ // HH:mm:ss.SSSZZ
+ assertValidDateFormatParsing("time", "12:12:12.100Z");
+ assertValidDateFormatParsing("time", "01:01:01.1Z", "01:01:01.100Z");
+ assertValidDateFormatParsing("time", "1:1:1.1Z", "01:01:01.100Z");
+ assertValidDateFormatParsing("strictTime", "12:12:12.100Z");
+ assertDateFormatParsingThrowingException("strictTime", "12:12:1.100Z");
+ assertDateFormatParsingThrowingException("strictTime", "12:1:12.100Z");
+ assertDateFormatParsingThrowingException("strictTime", "1:12:12.100Z");
+
+ // HH:mm:ssZZ
+ assertValidDateFormatParsing("timeNoMillis", "12:12:12Z");
+ assertValidDateFormatParsing("timeNoMillis", "01:01:01Z", "01:01:01Z");
+ assertValidDateFormatParsing("timeNoMillis", "1:1:1Z", "01:01:01Z");
+ assertValidDateFormatParsing("strictTimeNoMillis", "12:12:12Z");
+ assertDateFormatParsingThrowingException("strictTimeNoMillis", "12:12:1Z");
+ assertDateFormatParsingThrowingException("strictTimeNoMillis", "12:1:12Z");
+ assertDateFormatParsingThrowingException("strictTimeNoMillis", "1:12:12Z");
+
+ // 'T’HH:mm:ss.SSSZZ
+ assertValidDateFormatParsing("tTime", "T12:12:12.100Z");
+ assertValidDateFormatParsing("tTime", "T01:01:01.1Z", "T01:01:01.100Z");
+ assertValidDateFormatParsing("tTime", "T1:1:1.1Z", "T01:01:01.100Z");
+ assertValidDateFormatParsing("strictTTime", "T12:12:12.100Z");
+ assertDateFormatParsingThrowingException("strictTTime", "T12:12:1.100Z");
+ assertDateFormatParsingThrowingException("strictTTime", "T12:1:12.100Z");
+ assertDateFormatParsingThrowingException("strictTTime", "T1:12:12.100Z");
+
+ // 'T’HH:mm:ssZZ
+ assertValidDateFormatParsing("tTimeNoMillis", "T12:12:12Z");
+ assertValidDateFormatParsing("tTimeNoMillis", "T01:01:01Z", "T01:01:01Z");
+ assertValidDateFormatParsing("tTimeNoMillis", "T1:1:1Z", "T01:01:01Z");
+ assertValidDateFormatParsing("strictTTimeNoMillis", "T12:12:12Z");
+ assertDateFormatParsingThrowingException("strictTTimeNoMillis", "T12:12:1Z");
+ assertDateFormatParsingThrowingException("strictTTimeNoMillis", "T12:1:12Z");
+ assertDateFormatParsingThrowingException("strictTTimeNoMillis", "T1:12:12Z");
+
+ // xxxx-'W’ww-e
+ assertValidDateFormatParsing("weekDate", "0005-W4-1", "0005-W04-1");
+ assertValidDateFormatParsing("strictWeekDate", "0005-W04-1");
+ assertDateFormatParsingThrowingException("strictWeekDate", "0005-W4-1");
+
+ // xxxx-'W’ww-e’T'HH:mm:ss.SSSZZ
+ assertValidDateFormatParsing("weekDateTime", "0005-W41-4T12:43:43.123Z");
+ assertValidDateFormatParsing("weekDateTime", "5-W41-4T12:43:43.123Z", "0005-W41-4T12:43:43.123Z");
+ assertValidDateFormatParsing("strictWeekDateTime", "0005-W41-4T12:43:43.123Z");
+ assertValidDateFormatParsing("strictWeekDateTime", "0005-W06-4T12:43:43.123Z");
+ assertDateFormatParsingThrowingException("strictWeekDateTime", "0005-W4-7T12:43:43.123Z");
+ assertDateFormatParsingThrowingException("strictWeekDateTime", "5-W41-4T12:43:43.123Z");
+ assertDateFormatParsingThrowingException("strictWeekDateTime", "5-W1-4T12:43:43.123Z");
+
+ // xxxx-'W’ww-e’T'HH:mm:ssZZ
+ assertValidDateFormatParsing("weekDateTimeNoMillis", "0005-W41-4T12:43:43Z");
+ assertValidDateFormatParsing("weekDateTimeNoMillis", "5-W41-4T12:43:43Z", "0005-W41-4T12:43:43Z");
+ assertValidDateFormatParsing("strictWeekDateTimeNoMillis", "0005-W41-4T12:43:43Z");
+ assertValidDateFormatParsing("strictWeekDateTimeNoMillis", "0005-W06-4T12:43:43Z");
+ assertDateFormatParsingThrowingException("strictWeekDateTimeNoMillis", "0005-W4-7T12:43:43Z");
+ assertDateFormatParsingThrowingException("strictWeekDateTimeNoMillis", "5-W41-4T12:43:43Z");
+ assertDateFormatParsingThrowingException("strictWeekDateTimeNoMillis", "5-W1-4T12:43:43Z");
+
+ // yyyy
+ assertValidDateFormatParsing("weekyear", "2014");
+ assertValidDateFormatParsing("weekyear", "5", "0005");
+ assertValidDateFormatParsing("weekyear", "0005");
+ assertValidDateFormatParsing("strictWeekyear", "2014");
+ assertValidDateFormatParsing("strictWeekyear", "0005");
+ assertDateFormatParsingThrowingException("strictWeekyear", "5");
+
+ // yyyy-'W'ee
+ assertValidDateFormatParsing("weekyearWeek", "2014-W41");
+ assertValidDateFormatParsing("weekyearWeek", "2014-W1", "2014-W01");
+ assertValidDateFormatParsing("strictWeekyearWeek", "2014-W41");
+ assertDateFormatParsingThrowingException("strictWeekyearWeek", "2014-W1");
+
+ // weekyearWeekDay
+ assertValidDateFormatParsing("weekyearWeekDay", "2014-W41-1");
+ assertValidDateFormatParsing("weekyearWeekDay", "2014-W1-1", "2014-W01-1");
+ assertValidDateFormatParsing("strictWeekyearWeekDay", "2014-W41-1");
+ assertDateFormatParsingThrowingException("strictWeekyearWeekDay", "2014-W1-1");
+
+ // yyyy
+ assertValidDateFormatParsing("year", "2014");
+ assertValidDateFormatParsing("year", "5", "0005");
+ assertValidDateFormatParsing("strictYear", "2014");
+ assertDateFormatParsingThrowingException("strictYear", "5");
+
+ // yyyy-mm
+ assertValidDateFormatParsing("yearMonth", "2014-12");
+ assertValidDateFormatParsing("yearMonth", "2014-5", "2014-05");
+ assertValidDateFormatParsing("strictYearMonth", "2014-12");
+ assertDateFormatParsingThrowingException("strictYearMonth", "2014-5");
+
+ // yyyy-mm-dd
+ assertValidDateFormatParsing("yearMonthDay", "2014-12-12");
+ assertValidDateFormatParsing("yearMonthDay", "2014-05-5", "2014-05-05");
+ assertValidDateFormatParsing("strictYearMonthDay", "2014-12-12");
+ assertDateFormatParsingThrowingException("strictYearMonthDay", "2014-05-5");
+ }
+
+ @Test
+ public void testThatRootObjectParsingIsStrict() throws Exception {
+ String[] datesThatWork = new String[] { "2014/10/10", "2014/10/10 12:12:12", "2014-05-05", "2014-05-05T12:12:12.123Z" };
+ String[] datesThatShouldNotWork = new String[]{ "5-05-05", "2014-5-05", "2014-05-5",
+ "2014-05-05T1:12:12.123Z", "2014-05-05T12:1:12.123Z", "2014-05-05T12:12:1.123Z",
+ "4/10/10", "2014/1/10", "2014/10/1",
+ "2014/10/10 1:12:12", "2014/10/10 12:1:12", "2014/10/10 12:12:1"
+ };
+
+ // good case
+ for (String date : datesThatWork) {
+ boolean dateParsingSuccessful = false;
+ for (FormatDateTimeFormatter dateTimeFormatter : RootObjectMapper.Defaults.DYNAMIC_DATE_TIME_FORMATTERS) {
+ try {
+ dateTimeFormatter.parser().parseMillis(date);
+ dateParsingSuccessful = true;
+ break;
+ } catch (Exception e) {}
+ }
+ if (!dateParsingSuccessful) {
+ fail("Parsing for date " + date + " in root object mapper failed, but shouldnt");
+ }
+ }
+
+ // bad case
+ for (String date : datesThatShouldNotWork) {
+ for (FormatDateTimeFormatter dateTimeFormatter : RootObjectMapper.Defaults.DYNAMIC_DATE_TIME_FORMATTERS) {
+ try {
+ dateTimeFormatter.parser().parseMillis(date);
+ fail(String.format(Locale.ROOT, "Expected exception when parsing date %s in root mapper", date));
+ } catch (Exception e) {}
+ }
+ }
+ }
+
+ private void assertValidDateFormatParsing(String pattern, String dateToParse) {
+ assertValidDateFormatParsing(pattern, dateToParse, dateToParse);
+ }
+
+ private void assertValidDateFormatParsing(String pattern, String dateToParse, String expectedDate) {
+ FormatDateTimeFormatter formatter = Joda.forPattern(pattern);
+ assertThat(formatter.printer().print(formatter.parser().parseMillis(dateToParse)), is(expectedDate));
+ }
+
+ private void assertDateFormatParsingThrowingException(String pattern, String invalidDate) {
+ try {
+ FormatDateTimeFormatter formatter = Joda.forPattern(pattern);
+ DateTimeFormatter parser = formatter.parser();
+ parser.parseMillis(invalidDate);
+ fail(String.format(Locale.ROOT, "Expected parsing exception for pattern [%s] with date [%s], but did not happen", pattern, invalidDate));
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
private long utcTimeInMillis(String time) {
return ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC).parseMillis(time);
}
diff --git a/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsTests.java b/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsTests.java
index 6792298bab2b0..c12f57dfb0f86 100644
--- a/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsTests.java
+++ b/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsTests.java
@@ -371,7 +371,9 @@ public void testIsolateMasterAndVerifyClusterStateConsensus() throws Exception {
// restore isolation
networkPartition.stopDisrupting();
- ensureStableCluster(3, new TimeValue(DISRUPTION_HEALING_OVERHEAD.millis() + networkPartition.expectedTimeToHeal().millis()));
+ for (String node : nodes) {
+ ensureStableCluster(3, new TimeValue(DISRUPTION_HEALING_OVERHEAD.millis() + networkPartition.expectedTimeToHeal().millis()), true, node);
+ }
logger.info("issue a reroute");
// trigger a reroute now, instead of waiting for the background reroute of RerouteService
@@ -578,7 +580,7 @@ public void testMasterNodeGCs() throws Exception {
// restore GC
masterNodeDisruption.stopDisrupting();
- ensureStableCluster(3, new TimeValue(DISRUPTION_HEALING_OVERHEAD.millis() + masterNodeDisruption.expectedTimeToHeal().millis()),
+ ensureStableCluster(3, new TimeValue(DISRUPTION_HEALING_OVERHEAD.millis() + masterNodeDisruption.expectedTimeToHeal().millis()), false,
oldNonMasterNodes.get(0));
// make sure all nodes agree on master
@@ -987,18 +989,18 @@ private ServiceDisruptionScheme addRandomDisruptionScheme() {
}
private void ensureStableCluster(int nodeCount) {
- ensureStableCluster(nodeCount, TimeValue.timeValueSeconds(30), null);
+ ensureStableCluster(nodeCount, TimeValue.timeValueSeconds(30));
}
private void ensureStableCluster(int nodeCount, TimeValue timeValue) {
- ensureStableCluster(nodeCount, timeValue, null);
+ ensureStableCluster(nodeCount, timeValue, false, null);
}
private void ensureStableCluster(int nodeCount, @Nullable String viaNode) {
- ensureStableCluster(nodeCount, TimeValue.timeValueSeconds(30), viaNode);
+ ensureStableCluster(nodeCount, TimeValue.timeValueSeconds(30), false, viaNode);
}
- private void ensureStableCluster(int nodeCount, TimeValue timeValue, @Nullable String viaNode) {
+ private void ensureStableCluster(int nodeCount, TimeValue timeValue, boolean local, @Nullable String viaNode) {
if (viaNode == null) {
viaNode = randomFrom(internalCluster().getNodeNames());
}
@@ -1007,6 +1009,7 @@ private void ensureStableCluster(int nodeCount, TimeValue timeValue, @Nullable S
.setWaitForEvents(Priority.LANGUID)
.setWaitForNodes(Integer.toString(nodeCount))
.setTimeout(timeValue)
+ .setLocal(local)
.setWaitForRelocatingShards(0)
.get();
if (clusterHealthResponse.isTimedOut()) {
diff --git a/core/src/test/java/org/elasticsearch/document/BulkTests.java b/core/src/test/java/org/elasticsearch/document/BulkTests.java
index 8be32de6feb83..e4d3af7cdcc16 100644
--- a/core/src/test/java/org/elasticsearch/document/BulkTests.java
+++ b/core/src/test/java/org/elasticsearch/document/BulkTests.java
@@ -725,5 +725,39 @@ public void testThatMissingIndexDoesNotAbortFullBulkRequest() throws Exception{
assertThat(bulkResponse.hasFailures(), is(true));
assertThat(bulkResponse.getItems().length, is(5));
}
+
+ @Test // issue 9821
+ public void testFailedRequestsOnClosedIndex() throws Exception {
+ createIndex("bulkindex1");
+ ensureYellow();
+
+ client().prepareIndex("bulkindex1", "index1_type", "1").setSource("text", "test").get();
+ assertAcked(client().admin().indices().prepareClose("bulkindex1"));
+
+ BulkRequest bulkRequest = new BulkRequest();
+ bulkRequest.add(new IndexRequest("bulkindex1", "index1_type", "1").source("text", "hallo1"))
+ .add(new UpdateRequest("bulkindex1", "index1_type", "1").doc("foo", "bar"))
+ .add(new DeleteRequest("bulkindex1", "index1_type", "1")).refresh(true);
+
+ BulkResponse bulkResponse = client().bulk(bulkRequest).get();
+ assertThat(bulkResponse.hasFailures(), is(true));
+ BulkItemResponse[] responseItems = bulkResponse.getItems();
+ assertThat(responseItems.length, is(3));
+ assertThat(responseItems[0].getOpType(), is("index"));
+ assertThat(responseItems[1].getOpType(), is("update"));
+ assertThat(responseItems[2].getOpType(), is("delete"));
+ }
+
+ @Test // issue 9821
+ public void testInvalidIndexNamesCorrectOpType() {
+ BulkResponse bulkResponse = client().prepareBulk()
+ .add(client().prepareIndex().setIndex("INVALID.NAME").setType("type1").setId("1").setSource("field", 1))
+ .add(client().prepareUpdate().setIndex("INVALID.NAME").setType("type1").setId("1").setDoc("field", randomInt()))
+ .add(client().prepareDelete().setIndex("INVALID.NAME").setType("type1").setId("1")).get();
+ assertThat(bulkResponse.getItems().length, is(3));
+ assertThat(bulkResponse.getItems()[0].getOpType(), is("index"));
+ assertThat(bulkResponse.getItems()[1].getOpType(), is("update"));
+ assertThat(bulkResponse.getItems()[2].getOpType(), is("delete"));
+ }
}
diff --git a/core/src/test/java/org/elasticsearch/gateway/PriorityComparatorTests.java b/core/src/test/java/org/elasticsearch/gateway/PriorityComparatorTests.java
new file mode 100644
index 0000000000000..a39a6ad8a1f26
--- /dev/null
+++ b/core/src/test/java/org/elasticsearch/gateway/PriorityComparatorTests.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.gateway;
+
+import org.elasticsearch.cluster.metadata.IndexMetaData;
+import org.elasticsearch.cluster.routing.RoutingNodes;
+import org.elasticsearch.cluster.routing.ShardRouting;
+import org.elasticsearch.cluster.routing.ShardRoutingState;
+import org.elasticsearch.cluster.routing.UnassignedInfo;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.test.ElasticsearchTestCase;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public class PriorityComparatorTests extends ElasticsearchTestCase {
+
+ public void testPriorityComparatorSort() {
+ RoutingNodes.UnassignedShards shards = new RoutingNodes.UnassignedShards();
+ int numIndices = randomIntBetween(3, 99);
+ IndexMeta[] indices = new IndexMeta[numIndices];
+ final Map map = new HashMap<>();
+
+ for (int i = 0; i < indices.length; i++) {
+ if (frequently()) {
+ indices[i] = new IndexMeta("idx_2015_04_" + String.format(Locale.ROOT, "%02d", i), randomIntBetween(1, 1000), randomIntBetween(1, 10000));
+ } else { // sometimes just use defaults
+ indices[i] = new IndexMeta("idx_2015_04_" + String.format(Locale.ROOT, "%02d", i));
+ }
+ map.put(indices[i].name, indices[i]);
+ }
+ int numShards = randomIntBetween(10, 100);
+ for (int i = 0; i < numShards; i++) {
+ IndexMeta indexMeta = randomFrom(indices);
+ shards.add(new ShardRouting(indexMeta.name, randomIntBetween(1, 5), null, null, null,
+ randomBoolean(), ShardRoutingState.UNASSIGNED, randomIntBetween(0, 100), new UnassignedInfo(randomFrom(UnassignedInfo.Reason.values()), "foobar")));
+ }
+ shards.sort(new PriorityComparator() {
+ @Override
+ protected Settings getIndexSettings(String index) {
+ IndexMeta indexMeta = map.get(index);
+ return indexMeta.settings;
+ }
+ });
+ ShardRouting previous = null;
+ for (ShardRouting routing : shards) {
+ if (previous != null) {
+ IndexMeta prevMeta = map.get(previous.getIndex());
+ IndexMeta currentMeta = map.get(routing.getIndex());
+ if (prevMeta.priority == currentMeta.priority) {
+ if (prevMeta.creationDate == currentMeta.creationDate) {
+ if (prevMeta.name.equals(currentMeta.name) == false) {
+ assertTrue("indexName mismatch, expected:" + currentMeta.name + " after " + prevMeta.name + " " + prevMeta.name.compareTo(currentMeta.name), prevMeta.name.compareTo(currentMeta.name) > 0);
+ }
+ } else {
+ assertTrue("creationDate mismatch, expected:" + currentMeta.creationDate + " after " + prevMeta.creationDate, prevMeta.creationDate > currentMeta.creationDate);
+ }
+ } else {
+ assertTrue("priority mismatch, expected:" + currentMeta.priority + " after " + prevMeta.priority, prevMeta.priority > currentMeta.priority);
+ }
+ }
+ previous = routing;
+ }
+ }
+
+ private static class IndexMeta {
+ final String name;
+ final int priority;
+ final long creationDate;
+ final Settings settings;
+
+ private IndexMeta(String name) { // default
+ this.name = name;
+ this.priority = 1;
+ this.creationDate = -1;
+ this.settings = Settings.EMPTY;
+ }
+
+ private IndexMeta(String name, int priority, long creationDate) {
+ this.name = name;
+ this.priority = priority;
+ this.creationDate = creationDate;
+ this.settings = Settings.builder().put(IndexMetaData.SETTING_CREATION_DATE, creationDate)
+ .put(IndexMetaData.SETTING_PRIORITY, priority).build();
+ }
+ }
+}
diff --git a/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasTests.java b/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasTests.java
index 810118b5be377..73ea27ae84abf 100644
--- a/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasTests.java
+++ b/core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasTests.java
@@ -647,7 +647,6 @@ public void run() {
}
@Test
- @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/11788")
public void testIndexOnSharedFSRecoversToAnyNode() throws Exception {
Settings nodeSettings = nodeSettings();
Settings fooSettings = Settings.builder().put(nodeSettings).put("node.affinity", "foo").build();
diff --git a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java
index bfd13a27c981e..70a801abc7049 100644
--- a/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java
+++ b/core/src/test/java/org/elasticsearch/index/engine/InternalEngineTests.java
@@ -991,6 +991,7 @@ public void run() {
}
indexed.await();
IOUtils.close(engine);
+ thread.join();
}
}
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java
index dd02b208a14fa..a3b3ea12af295 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/FieldTypeLookupTests.java
@@ -24,8 +24,6 @@
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.index.fielddata.FieldDataType;
-import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
import org.elasticsearch.test.ElasticsearchTestCase;
import java.io.IOException;
@@ -176,10 +174,10 @@ static List newList(FieldMapper... mapper) {
}
// this sucks how much must be overridden just do get a dummy field mapper...
- static class FakeFieldMapper extends AbstractFieldMapper {
+ static class FakeFieldMapper extends FieldMapper {
static Settings dummySettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id).build();
public FakeFieldMapper(String fullName, String indexName) {
- super(fullName, makeFieldType(fullName, indexName), null, null, dummySettings, null, null);
+ super(fullName, makeFieldType(fullName, indexName), makeFieldType(fullName, indexName), dummySettings, null, null);
}
static MappedFieldType makeFieldType(String fullName, String indexName) {
FakeFieldType fieldType = new FakeFieldType();
@@ -201,10 +199,6 @@ public String typeName() {
}
}
@Override
- public MappedFieldType defaultFieldType() { return null; }
- @Override
- public FieldDataType defaultFieldDataType() { return null; }
- @Override
protected String contentType() { return null; }
@Override
protected void parseCreateField(ParseContext context, List list) throws IOException {}
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java b/core/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java
index b46c4e349d714..dabac4e204066 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/all/SimpleAllMapperTests.java
@@ -226,7 +226,6 @@ public void testRandom() throws Exception {
boolean tv_offsets = false;
boolean tv_positions = false;
String similarity = null;
- boolean fieldData = false;
XContentBuilder mappingBuilder = jsonBuilder();
mappingBuilder.startObject().startObject("test");
List> booleanOptionList = new ArrayList<>();
@@ -263,12 +262,6 @@ public void testRandom() throws Exception {
if (randomBoolean()) {
mappingBuilder.field("similarity", similarity = randomBoolean() ? "BM25" : "TF/IDF");
}
- if (randomBoolean()) {
- fieldData = true;
- mappingBuilder.startObject("fielddata");
- mappingBuilder.field("foo", "bar");
- mappingBuilder.endObject();
- }
mappingBuilder.endObject();
}
@@ -310,7 +303,6 @@ public void testRandom() throws Exception {
} else {
assertThat(similarity, equalTo(builtDocMapper.allFieldMapper().fieldType().similarity().name()));
}
- assertThat(builtMapping.contains("fielddata"), is(fieldData));
if (allDefault) {
BytesStreamOutput bytesStreamOutput = new BytesStreamOutput(0);
XContentBuilder b = new XContentBuilder(XContentType.JSON.xContent(), bytesStreamOutput);
diff --git a/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java b/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java
index 829d3458f2954..3d9398e426a3b 100644
--- a/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java
+++ b/core/src/test/java/org/elasticsearch/index/mapper/date/SimpleDateMappingTests.java
@@ -26,6 +26,8 @@
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.util.Constants;
import org.elasticsearch.Version;
+import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsResponse;
+import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.Settings;
@@ -45,6 +47,7 @@
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
import org.elasticsearch.test.TestSearchContext;
+import org.elasticsearch.test.VersionUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Before;
@@ -55,7 +58,6 @@
import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAsBoolean;
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.index.mapper.string.SimpleStringMappingTests.docValuesType;
-import static org.elasticsearch.test.VersionUtils.randomVersionBetween;
import static org.hamcrest.Matchers.*;
public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
@@ -482,4 +484,94 @@ public void testThatEpochCanBeIgnoredWithCustomFormat() throws Exception {
indexResponse = client().prepareIndex("test", "test").setSource(document).get();
assertThat(indexResponse.isCreated(), is(true));
}
+
+ public void testThatOlderIndicesAllowNonStrictDates() throws Exception {
+ String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
+ .startObject("properties").startObject("date_field").field("type", "date").endObject().endObject()
+ .endObject().endObject().string();
+
+ Version randomVersion = VersionUtils.randomVersionBetween(getRandom(), Version.V_0_90_0, Version.V_1_6_1);
+ IndexService index = createIndex("test", settingsBuilder().put(IndexMetaData.SETTING_VERSION_CREATED, randomVersion).build());
+ client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping).get();
+ assertDateFormat("epoch_millis||dateOptionalTime");
+ DocumentMapper defaultMapper = index.mapperService().documentMapper("type");
+
+ defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .field("date_field", "1-1-1T00:00:44.000Z")
+ .endObject()
+ .bytes());
+
+ // also test normal date
+ defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .field("date_field", "2015-06-06T00:00:44.000Z")
+ .endObject()
+ .bytes());
+ }
+
+ public void testThatNewIndicesOnlyAllowStrictDates() throws Exception {
+ String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
+ .startObject("properties").startObject("date_field").field("type", "date").endObject().endObject()
+ .endObject().endObject().string();
+
+ IndexService index = createIndex("test");
+ client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping).get();
+ assertDateFormat(DateFieldMapper.Defaults.DATE_TIME_FORMATTER.format());
+ DocumentMapper defaultMapper = index.mapperService().documentMapper("type");
+
+ // also test normal date
+ defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .field("date_field", "2015-06-06T00:00:44.000Z")
+ .endObject()
+ .bytes());
+
+ try {
+ defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
+ .startObject()
+ .field("date_field", "1-1-1T00:00:44.000Z")
+ .endObject()
+ .bytes());
+ fail("non strict date indexing should have been failed");
+ } catch (MapperParsingException e) {
+ assertThat(e.getCause(), instanceOf(IllegalArgumentException.class));
+ }
+ }
+
+ public void testThatUpgradingAnOlderIndexToStrictDateWorks() throws Exception {
+ String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
+ .startObject("properties").startObject("date_field").field("type", "date").field("format", "dateOptionalTime").endObject().endObject()
+ .endObject().endObject().string();
+
+ Version randomVersion = VersionUtils.randomVersionBetween(getRandom(), Version.V_0_90_0, Version.V_1_6_1);
+ createIndex("test", settingsBuilder().put(IndexMetaData.SETTING_VERSION_CREATED, randomVersion).build());
+ client().admin().indices().preparePutMapping("test").setType("type").setSource(mapping).get();
+ assertDateFormat("epoch_millis||dateOptionalTime");
+
+ // index doc
+ client().prepareIndex("test", "type", "1").setSource(XContentFactory.jsonBuilder()
+ .startObject()
+ .field("date_field", "2015-06-06T00:00:44.000Z")
+ .endObject()).get();
+
+ // update mapping
+ String newMapping = XContentFactory.jsonBuilder().startObject().startObject("type")
+ .startObject("properties").startObject("date_field")
+ .field("type", "date")
+ .field("format", "strictDateOptionalTime||epoch_millis")
+ .endObject().endObject().endObject().endObject().string();
+ PutMappingResponse putMappingResponse = client().admin().indices().preparePutMapping("test").setType("type").setSource(newMapping).get();
+ assertThat(putMappingResponse.isAcknowledged(), is(true));
+
+ assertDateFormat("strictDateOptionalTime||epoch_millis");
+ }
+
+ private void assertDateFormat(String expectedFormat) throws IOException {
+ GetMappingsResponse response = client().admin().indices().prepareGetMappings("test").setTypes("type").get();
+ Map mappingMap = response.getMappings().get("test").get("type").getSourceAsMap();
+ Map properties = (Map) mappingMap.get("properties");
+ Map