/*
* 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.deps.joda;
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.mapper.RootObjectMapper;
import org.elasticsearch.test.ESTestCase;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.joda.time.MutableDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;
import org.joda.time.format.DateTimeParser;
import org.joda.time.format.ISODateTimeFormat;
import java.util.Date;
import java.util.Locale;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
public class SimpleJodaTests extends ESTestCase {
public void testMultiParsers() {
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeParser[] parsers = new DateTimeParser[3];
parsers[0] = DateTimeFormat.forPattern("MM/dd/yyyy").withZone(DateTimeZone.UTC).getParser();
parsers[1] = DateTimeFormat.forPattern("MM-dd-yyyy").withZone(DateTimeZone.UTC).getParser();
parsers[2] = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZone(DateTimeZone.UTC).getParser();
builder.append(DateTimeFormat.forPattern("MM/dd/yyyy").withZone(DateTimeZone.UTC).getPrinter(), parsers);
DateTimeFormatter formatter = builder.toFormatter();
formatter.parseMillis("2009-11-15 14:12:12");
}
public void testIsoDateFormatDateTimeNoMillisUTC() {
DateTimeFormatter formatter = ISODateTimeFormat.dateTimeNoMillis().withZone(DateTimeZone.UTC);
long millis = formatter.parseMillis("1970-01-01T00:00:00Z");
assertThat(millis, equalTo(0L));
}
public void testUpperBound() {
MutableDateTime dateTime = new MutableDateTime(3000, 12, 31, 23, 59, 59, 999, DateTimeZone.UTC);
DateTimeFormatter formatter = ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC);
String value = "2000-01-01";
int i = formatter.parseInto(dateTime, value, 0);
assertThat(i, equalTo(value.length()));
assertThat(dateTime.toString(), equalTo("2000-01-01T23:59:59.999Z"));
}
public void testIsoDateFormatDateOptionalTimeUTC() {
DateTimeFormatter formatter = ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC);
long millis = formatter.parseMillis("1970-01-01T00:00:00Z");
assertThat(millis, equalTo(0L));
millis = formatter.parseMillis("1970-01-01T00:00:00.001Z");
assertThat(millis, equalTo(1L));
millis = formatter.parseMillis("1970-01-01T00:00:00.1Z");
assertThat(millis, equalTo(100L));
millis = formatter.parseMillis("1970-01-01T00:00:00.1");
assertThat(millis, equalTo(100L));
millis = formatter.parseMillis("1970-01-01T00:00:00");
assertThat(millis, equalTo(0L));
millis = formatter.parseMillis("1970-01-01");
assertThat(millis, equalTo(0L));
millis = formatter.parseMillis("1970");
assertThat(millis, equalTo(0L));
try {
formatter.parseMillis("1970 kuku");
fail("formatting should fail");
} catch (IllegalArgumentException e) {
// all is well
}
// test offset in format
millis = formatter.parseMillis("1970-01-01T00:00:00-02:00");
assertThat(millis, equalTo(TimeValue.timeValueHours(2).millis()));
}
public void testIsoVsCustom() {
DateTimeFormatter formatter = ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC);
long millis = formatter.parseMillis("1970-01-01T00:00:00");
assertThat(millis, equalTo(0L));
formatter = DateTimeFormat.forPattern("yyyy/MM/dd HH:mm:ss").withZone(DateTimeZone.UTC);
millis = formatter.parseMillis("1970/01/01 00:00:00");
assertThat(millis, equalTo(0L));
FormatDateTimeFormatter formatter2 = Joda.forPattern("yyyy/MM/dd HH:mm:ss");
millis = formatter2.parser().parseMillis("1970/01/01 00:00:00");
assertThat(millis, equalTo(0L));
}
public void testWriteAndParse() {
DateTimeFormatter dateTimeWriter = ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);
DateTimeFormatter formatter = ISODateTimeFormat.dateOptionalTimeParser().withZone(DateTimeZone.UTC);
Date date = new Date();
assertThat(formatter.parseMillis(dateTimeWriter.print(date.getTime())), equalTo(date.getTime()));
}
public void testSlashInFormat() {
FormatDateTimeFormatter formatter = Joda.forPattern("MM/yyyy");
formatter.parser().parseMillis("01/2001");
formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss");
long millis = formatter.parser().parseMillis("1970/01/01 00:00:00");
formatter.printer().print(millis);
try {
millis = formatter.parser().parseMillis("1970/01/01");
fail();
} catch (IllegalArgumentException e) {
// it really can't parse this one
}
}
public void testMultipleFormats() {
FormatDateTimeFormatter formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd");
long millis = formatter.parser().parseMillis("1970/01/01 00:00:00");
assertThat("1970/01/01 00:00:00", is(formatter.printer().print(millis)));
}
public void testMultipleDifferentFormats() {
FormatDateTimeFormatter formatter = Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd");
String input = "1970/01/01 00:00:00";
long millis = formatter.parser().parseMillis(input);
assertThat(input, is(formatter.printer().print(millis)));
Joda.forPattern("yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||dateOptionalTime");
Joda.forPattern("dateOptionalTime||yyyy/MM/dd HH:mm:ss||yyyy/MM/dd");
Joda.forPattern("yyyy/MM/dd HH:mm:ss||dateOptionalTime||yyyy/MM/dd");
Joda.forPattern("date_time||date_time_no_millis");
Joda.forPattern(" date_time || date_time_no_millis");
}
public void testInvalidPatterns() {
expectInvalidPattern("does_not_exist_pattern", "Invalid format: [does_not_exist_pattern]: Illegal pattern component: o");
expectInvalidPattern("OOOOO", "Invalid format: [OOOOO]: Illegal pattern component: OOOOO");
expectInvalidPattern(null, "No date pattern provided");
expectInvalidPattern("", "No date pattern provided");
expectInvalidPattern(" ", "No date pattern provided");
expectInvalidPattern("||date_time_no_millis", "No date pattern provided");
expectInvalidPattern("date_time_no_millis||", "No date pattern provided");
}
private void expectInvalidPattern(String pattern, String errorMessage) {
try {
Joda.forPattern(pattern);
fail("Pattern " + pattern + " should have thrown an exception but did not");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString(errorMessage));
}
}
public void testRounding() {
long TIME = utcTimeInMillis("2009-02-03T01:01:01");
MutableDateTime time = new MutableDateTime(DateTimeZone.UTC);
time.setMillis(TIME);
assertThat(time.monthOfYear().roundFloor().toString(), equalTo("2009-02-01T00:00:00.000Z"));
time.setMillis(TIME);
assertThat(time.hourOfDay().roundFloor().toString(), equalTo("2009-02-03T01:00:00.000Z"));
time.setMillis(TIME);
assertThat(time.dayOfMonth().roundFloor().toString(), equalTo("2009-02-03T00:00:00.000Z"));
}
public void testRoundingSetOnTime() {
MutableDateTime time = new MutableDateTime(DateTimeZone.UTC);
time.setRounding(time.getChronology().monthOfYear(), MutableDateTime.ROUND_FLOOR);
time.setMillis(utcTimeInMillis("2009-02-03T01:01:01"));
assertThat(time.toString(), equalTo("2009-02-01T00:00:00.000Z"));
assertThat(time.getMillis(), equalTo(utcTimeInMillis("2009-02-01T00:00:00.000Z")));
time.setMillis(utcTimeInMillis("2009-05-03T01:01:01"));
assertThat(time.toString(), equalTo("2009-05-01T00:00:00.000Z"));
assertThat(time.getMillis(), equalTo(utcTimeInMillis("2009-05-01T00:00:00.000Z")));
time = new MutableDateTime(DateTimeZone.UTC);
time.setRounding(time.getChronology().dayOfMonth(), MutableDateTime.ROUND_FLOOR);
time.setMillis(utcTimeInMillis("2009-02-03T01:01:01"));
assertThat(time.toString(), equalTo("2009-02-03T00:00:00.000Z"));
assertThat(time.getMillis(), equalTo(utcTimeInMillis("2009-02-03T00:00:00.000Z")));
time.setMillis(utcTimeInMillis("2009-02-02T23:01:01"));
assertThat(time.toString(), equalTo("2009-02-02T00:00:00.000Z"));
assertThat(time.getMillis(), equalTo(utcTimeInMillis("2009-02-02T00:00:00.000Z")));
time = new MutableDateTime(DateTimeZone.UTC);
time.setRounding(time.getChronology().weekOfWeekyear(), MutableDateTime.ROUND_FLOOR);
time.setMillis(utcTimeInMillis("2011-05-05T01:01:01"));
assertThat(time.toString(), equalTo("2011-05-02T00:00:00.000Z"));
assertThat(time.getMillis(), equalTo(utcTimeInMillis("2011-05-02T00:00:00.000Z")));
}
public void testRoundingWithTimeZone() {
MutableDateTime time = new MutableDateTime(DateTimeZone.UTC);
time.setZone(DateTimeZone.forOffsetHours(-2));
time.setRounding(time.getChronology().dayOfMonth(), MutableDateTime.ROUND_FLOOR);
MutableDateTime utcTime = new MutableDateTime(DateTimeZone.UTC);
utcTime.setRounding(utcTime.getChronology().dayOfMonth(), MutableDateTime.ROUND_FLOOR);
time.setMillis(utcTimeInMillis("2009-02-03T01:01:01"));
utcTime.setMillis(utcTimeInMillis("2009-02-03T01:01:01"));
assertThat(time.toString(), equalTo("2009-02-02T00:00:00.000-02:00"));
assertThat(utcTime.toString(), equalTo("2009-02-03T00:00:00.000Z"));
// the time is on the 2nd, and utcTime is on the 3rd, but, because time already encapsulates
// time zone, the millis diff is not 24, but 22 hours
assertThat(time.getMillis(), equalTo(utcTime.getMillis() - TimeValue.timeValueHours(22).millis()));
time.setMillis(utcTimeInMillis("2009-02-04T01:01:01"));
utcTime.setMillis(utcTimeInMillis("2009-02-04T01:01:01"));
assertThat(time.toString(), equalTo("2009-02-03T00:00:00.000-02:00"));
assertThat(utcTime.toString(), equalTo("2009-02-04T00:00:00.000Z"));
assertThat(time.getMillis(), equalTo(utcTime.getMillis() - TimeValue.timeValueHours(22).millis()));
}
public void testThatEpochsCanBeParsed() {
boolean parseMilliSeconds = randomBoolean();
// epoch: 1433144433655 => date: Mon Jun 1 09:40:33.655 CEST 2015
FormatDateTimeFormatter formatter = Joda.forPattern(parseMilliSeconds ? "epoch_millis" : "epoch_second");
DateTime dateTime = formatter.parser().parseDateTime(parseMilliSeconds ? "1433144433655" : "1433144433");
assertThat(dateTime.getYear(), is(2015));
assertThat(dateTime.getDayOfMonth(), is(1));
assertThat(dateTime.getMonthOfYear(), is(6));
assertThat(dateTime.getHourOfDay(), is(7)); // utc timezone, +2 offset due to CEST
assertThat(dateTime.getMinuteOfHour(), is(40));
assertThat(dateTime.getSecondOfMinute(), is(33));
if (parseMilliSeconds) {
assertThat(dateTime.getMillisOfSecond(), is(655));
} else {
assertThat(dateTime.getMillisOfSecond(), is(0));
}
}
public void testThatNegativeEpochsCanBeParsed() {
// problem: negative epochs can be arbitrary in size...
boolean parseMilliSeconds = randomBoolean();
FormatDateTimeFormatter formatter = Joda.forPattern(parseMilliSeconds ? "epoch_millis" : "epoch_second");
DateTime dateTime = formatter.parser().parseDateTime("-10000");
assertThat(dateTime.getYear(), is(1969));
assertThat(dateTime.getMonthOfYear(), is(12));
assertThat(dateTime.getDayOfMonth(), is(31));
if (parseMilliSeconds) {
assertThat(dateTime.getHourOfDay(), is(23)); // utc timezone, +2 offset due to CEST
assertThat(dateTime.getMinuteOfHour(), is(59));
assertThat(dateTime.getSecondOfMinute(), is(50));
} else {
assertThat(dateTime.getHourOfDay(), is(21)); // utc timezone, +2 offset due to CEST
assertThat(dateTime.getMinuteOfHour(), is(13));
assertThat(dateTime.getSecondOfMinute(), is(20));
}
// every negative epoch must be parsed, no matter if exact the size or bigger
if (parseMilliSeconds) {
formatter.parser().parseDateTime("-100000000");
formatter.parser().parseDateTime("-999999999999");
formatter.parser().parseDateTime("-1234567890123");
formatter.parser().parseDateTime("-1234567890123456789");
} else {
formatter.parser().parseDateTime("-100000000");
formatter.parser().parseDateTime("-1234567890");
formatter.parser().parseDateTime("-1234567890123456");
}
}
public void testForInvalidDatesInEpochSecond() {
FormatDateTimeFormatter formatter = Joda.forPattern("epoch_second");
try {
formatter.parser().parseDateTime(randomFrom("invalid date", "12345678901234567", "12345678901234567890"));
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("Invalid format"));
}
}
public void testForInvalidDatesInEpochMillis() {
FormatDateTimeFormatter formatter = Joda.forPattern("epoch_millis");
try {
formatter.parser().parseDateTime(randomFrom("invalid date", "12345678901234567890"));
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("Invalid format"));
}
}
public void testForInvalidTimeZoneWithEpochSeconds() {
DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
.append(new Joda.EpochTimeParser(false))
.toFormatter()
.withZone(DateTimeZone.forOffsetHours(1));
FormatDateTimeFormatter formatter =
new FormatDateTimeFormatter("epoch_seconds", dateTimeFormatter, Locale.ROOT);
try {
formatter.parser().parseDateTime("1433144433655");
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("time_zone must be UTC"));
}
}
public void testForInvalidTimeZoneWithEpochMillis() {
DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder()
.append(new Joda.EpochTimeParser(true))
.toFormatter()
.withZone(DateTimeZone.forOffsetHours(1));
FormatDateTimeFormatter formatter =
new FormatDateTimeFormatter("epoch_millis", dateTimeFormatter, Locale.ROOT);
try {
formatter.parser().parseDateTime("1433144433");
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("time_zone must be UTC"));
}
}
public void testThatEpochParserIsPrinter() {
FormatDateTimeFormatter formatter = Joda.forPattern("epoch_millis");
assertThat(formatter.parser().isPrinter(), is(true));
assertThat(formatter.printer().isPrinter(), is(true));
FormatDateTimeFormatter epochSecondFormatter = Joda.forPattern("epoch_second");
assertThat(epochSecondFormatter.parser().isPrinter(), is(true));
assertThat(epochSecondFormatter.printer().isPrinter(), is(true));
}
public void testThatEpochTimePrinterWorks() {
StringBuffer buffer = new StringBuffer();
LocalDateTime now = LocalDateTime.now();
Joda.EpochTimePrinter epochTimePrinter = new Joda.EpochTimePrinter(false);
epochTimePrinter.printTo(buffer, now, Locale.ROOT);
assertThat(buffer.length(), is(10));
// only check the last digit, as seconds go from 0-99 in the unix timestamp and don't stop at 60
assertThat(buffer.toString(), endsWith(String.valueOf(now.getSecondOfMinute() % 10)));
buffer = new StringBuffer();
Joda.EpochTimePrinter epochMilliSecondTimePrinter = new Joda.EpochTimePrinter(true);
epochMilliSecondTimePrinter.printTo(buffer, now, Locale.ROOT);
assertThat(buffer.length(), is(13));
assertThat(buffer.toString(), endsWith(String.valueOf(now.getMillisOfSecond())));
}
public void testThatEpochParserIsIdempotent() {
FormatDateTimeFormatter formatter = Joda.forPattern("epoch_millis");
DateTime dateTime = formatter.parser().parseDateTime("1234567890123");
assertThat(dateTime.getMillis(), is(1234567890123L));
dateTime = formatter.printer().parseDateTime("1234567890456");
assertThat(dateTime.getMillis(), is(1234567890456L));
dateTime = formatter.parser().parseDateTime("1234567890789");
assertThat(dateTime.getMillis(), is(1234567890789L));
dateTime = formatter.parser().parseDateTime("1234567890123456789");
assertThat(dateTime.getMillis(), is(1234567890123456789L));
FormatDateTimeFormatter secondsFormatter = Joda.forPattern("epoch_second");
DateTime secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890");
assertThat(secondsDateTime.getMillis(), is(1234567890000L));
secondsDateTime = secondsFormatter.printer().parseDateTime("1234567890");
assertThat(secondsDateTime.getMillis(), is(1234567890000L));
secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890");
assertThat(secondsDateTime.getMillis(), is(1234567890000L));
secondsDateTime = secondsFormatter.parser().parseDateTime("1234567890123456");
assertThat(secondsDateTime.getMillis(), is(1234567890123456000L));
}
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");
}
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);
}
}