LANG-1116: DateUtilsTest.testLang530 fails for some timezones
This commit is contained in:
parent
cb83f7cb31
commit
bea1ae92aa
|
@ -22,6 +22,7 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<release version="3.5" date="tba" description="tba">
|
<release version="3.5" date="tba" description="tba">
|
||||||
|
<action issue="LANG-1116" type="fix" dev="chas" due-to="Aaron Sheldon">DateUtilsTest.testLang530 fails for some timezones</action>
|
||||||
<action issue="LANG-1114" type="fix" dev="britter" due-to="Andy Coates">TypeUtils.ParameterizedType#equals doesn't work with wildcard types</action>
|
<action issue="LANG-1114" type="fix" dev="britter" due-to="Andy Coates">TypeUtils.ParameterizedType#equals doesn't work with wildcard types</action>
|
||||||
<action issue="LANG-1119" type="add" dev="britter" due-to="Loic Guibert">Add rotate(string, int) method to StringUtils</action>
|
<action issue="LANG-1119" type="add" dev="britter" due-to="Loic Guibert">Add rotate(string, int) method to StringUtils</action>
|
||||||
<action issue="LANG-1118" type="fix" dev="britter" due-to="Loic Guibert">StringUtils.repeat('z', -1) throws NegativeArraySizeException</action>
|
<action issue="LANG-1118" type="fix" dev="britter" due-to="Loic Guibert">StringUtils.repeat('z', -1) throws NegativeArraySizeException</action>
|
||||||
|
|
|
@ -18,12 +18,12 @@ package org.apache.commons.lang3.time;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.ParsePosition;
|
import java.text.ParsePosition;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -366,37 +366,21 @@ public class DateUtils {
|
||||||
throw new IllegalArgumentException("Date and Patterns must not be null");
|
throw new IllegalArgumentException("Date and Patterns must not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleDateFormat parser;
|
final TimeZone tz = TimeZone.getDefault();
|
||||||
if (locale == null) {
|
final Locale lcl = locale==null ?Locale.getDefault() : locale;
|
||||||
parser = new SimpleDateFormat();
|
|
||||||
} else {
|
|
||||||
parser = new SimpleDateFormat("", locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.setLenient(lenient);
|
|
||||||
final ParsePosition pos = new ParsePosition(0);
|
final ParsePosition pos = new ParsePosition(0);
|
||||||
|
|
||||||
for (final String parsePattern : parsePatterns) {
|
for (final String parsePattern : parsePatterns) {
|
||||||
|
FastDateParser fdp = new FastDateParser(parsePattern, tz, lcl, null, lenient);
|
||||||
String pattern = parsePattern;
|
try {
|
||||||
|
Date date = fdp.parse(str, pos);
|
||||||
// LANG-530 - need to make sure 'ZZ' output doesn't get passed to SimpleDateFormat
|
if (pos.getIndex() == str.length()) {
|
||||||
if (parsePattern.endsWith("ZZ")) {
|
|
||||||
pattern = pattern.substring(0, pattern.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.applyPattern(pattern);
|
|
||||||
pos.setIndex(0);
|
|
||||||
|
|
||||||
String str2 = str;
|
|
||||||
// LANG-530 - need to make sure 'ZZ' output doesn't hit SimpleDateFormat as it will ParseException
|
|
||||||
if (parsePattern.endsWith("ZZ")) {
|
|
||||||
str2 = str.replaceAll("([-+][0-9][0-9]):([0-9][0-9])$", "$1$2");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Date date = parser.parse(str2, pos);
|
|
||||||
if (date != null && pos.getIndex() == str2.length()) {
|
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
pos.setIndex(0);
|
||||||
|
}
|
||||||
|
catch(IllegalArgumentException iae) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw new ParseException("Unable to parse the date: " + str, -1);
|
throw new ParseException("Unable to parse the date: " + str, -1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class FastDateParser implements DateParser, Serializable {
|
||||||
*
|
*
|
||||||
* @see java.io.Serializable
|
* @see java.io.Serializable
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 2L;
|
private static final long serialVersionUID = 3L;
|
||||||
|
|
||||||
static final Locale JAPANESE_IMPERIAL = new Locale("ja","JP","JP");
|
static final Locale JAPANESE_IMPERIAL = new Locale("ja","JP","JP");
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ public class FastDateParser implements DateParser, Serializable {
|
||||||
private final Locale locale;
|
private final Locale locale;
|
||||||
private final int century;
|
private final int century;
|
||||||
private final int startYear;
|
private final int startYear;
|
||||||
|
private final boolean lenient;
|
||||||
|
|
||||||
// derived fields
|
// derived fields
|
||||||
private transient Pattern parsePattern;
|
private transient Pattern parsePattern;
|
||||||
|
@ -106,7 +107,7 @@ public class FastDateParser implements DateParser, Serializable {
|
||||||
* @param locale non-null locale
|
* @param locale non-null locale
|
||||||
*/
|
*/
|
||||||
protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale) {
|
protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale) {
|
||||||
this(pattern, timeZone, locale, null);
|
this(pattern, timeZone, locale, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,11 +122,31 @@ public class FastDateParser implements DateParser, Serializable {
|
||||||
* @since 3.3
|
* @since 3.3
|
||||||
*/
|
*/
|
||||||
protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) {
|
protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) {
|
||||||
|
this(pattern, timeZone, locale, centuryStart, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Constructs a new FastDateParser.</p>
|
||||||
|
*
|
||||||
|
* @param pattern non-null {@link java.text.SimpleDateFormat} compatible
|
||||||
|
* pattern
|
||||||
|
* @param timeZone non-null time zone to use
|
||||||
|
* @param locale non-null locale
|
||||||
|
* @param centuryStart The start of the century for 2 digit year parsing
|
||||||
|
* @param lenient if true, non-standard values for Calendar fields should be accepted;
|
||||||
|
* if false, non-standard values will cause a ParseException to be thrown {@link CalendaretLenient(boolean)}
|
||||||
|
*
|
||||||
|
* @since 3.5
|
||||||
|
*/
|
||||||
|
protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale,
|
||||||
|
final Date centuryStart, final boolean lenient) {
|
||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
this.timeZone = timeZone;
|
this.timeZone = timeZone;
|
||||||
this.locale = locale;
|
this.locale = locale;
|
||||||
|
this.lenient = lenient;
|
||||||
|
|
||||||
final Calendar definingCalendar = Calendar.getInstance(timeZone, locale);
|
final Calendar definingCalendar = Calendar.getInstance(timeZone, locale);
|
||||||
|
|
||||||
int centuryStartYear;
|
int centuryStartYear;
|
||||||
if(centuryStart!=null) {
|
if(centuryStart!=null) {
|
||||||
definingCalendar.setTime(centuryStart);
|
definingCalendar.setTime(centuryStart);
|
||||||
|
@ -336,6 +357,7 @@ public class FastDateParser implements DateParser, Serializable {
|
||||||
// timing tests indicate getting new instance is 19% faster than cloning
|
// timing tests indicate getting new instance is 19% faster than cloning
|
||||||
final Calendar cal= Calendar.getInstance(timeZone, locale);
|
final Calendar cal= Calendar.getInstance(timeZone, locale);
|
||||||
cal.clear();
|
cal.clear();
|
||||||
|
cal.setLenient(lenient);
|
||||||
|
|
||||||
for(int i=0; i<strategies.length;) {
|
for(int i=0; i<strategies.length;) {
|
||||||
final Strategy strategy= strategies[i++];
|
final Strategy strategy= strategies[i++];
|
||||||
|
|
|
@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.text.ParseException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -268,4 +269,20 @@ public class DateFormatUtilsTest {
|
||||||
String date = "2013-11-18T12:48:05Z";
|
String date = "2013-11-18T12:48:05Z";
|
||||||
DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.parse(date);
|
DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.parse(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLang530() throws ParseException {
|
||||||
|
TimeZone save = TimeZone.getDefault();
|
||||||
|
try {
|
||||||
|
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||||
|
final Date d = new Date();
|
||||||
|
final String isoDateStr = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(d);
|
||||||
|
final Date d2 = DateUtils.parseDate(isoDateStr, new String[] { DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.getPattern() });
|
||||||
|
// the format loses milliseconds so have to reintroduce them
|
||||||
|
assertEquals("Date not equal to itself ISO formatted and parsed", d.getTime(), d2.getTime() + d.getTime() % 1000);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
TimeZone.setDefault(save);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue