mirror of https://github.com/apache/jclouds.git
Java SimpleDateFormat cannot handle valid ISO8601 time zone strings, fixed
This commit is contained in:
parent
241a33b5c8
commit
3623918de5
|
@ -27,14 +27,15 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
public class DateUtils {
|
||||
|
||||
public static final Pattern MILLIS_PATTERN = Pattern.compile("(.*\\.[0-9][0-9][0-9])[0-9]*Z?");
|
||||
public static final Pattern MILLIS_PATTERN = Pattern.compile("(.*\\.[0-9][0-9][0-9])[0-9]*");
|
||||
|
||||
public static final Pattern TZ_PATTERN = Pattern.compile("(.*)[+-][0-9][0-9]:?[0-9][0-9]Z?");
|
||||
// This regexp will match all TZ forms that are valid is ISO 8601
|
||||
public static final Pattern TZ_PATTERN = Pattern.compile("(.*)([+-][0-9][0-9](:?[0-9][0-9])?|Z)");
|
||||
|
||||
public static String trimToMillis(String toParse) {
|
||||
Matcher matcher = MILLIS_PATTERN.matcher(toParse);
|
||||
if (matcher.find()) {
|
||||
toParse = matcher.group(1) + 'Z';
|
||||
toParse = matcher.group(1);
|
||||
}
|
||||
return toParse;
|
||||
}
|
||||
|
@ -44,11 +45,25 @@ public class DateUtils {
|
|||
public static String trimTZ(String toParse) {
|
||||
Matcher matcher = TZ_PATTERN.matcher(toParse);
|
||||
if (matcher.find()) {
|
||||
toParse = matcher.group(1) + 'Z';
|
||||
toParse = matcher.group(1);
|
||||
}
|
||||
// TODO explain why this check is here
|
||||
if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches())
|
||||
toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
|
||||
toParse = toParse.substring(0, toParse.length() - 6);
|
||||
return toParse;
|
||||
}
|
||||
|
||||
public static String findTZ(String toParse) {
|
||||
Matcher matcher = TZ_PATTERN.matcher(toParse);
|
||||
if (matcher.find()) {
|
||||
// Remove ':' from the TZ string, as SimpleDateFormat can't handle it
|
||||
String tz = matcher.group(2).replace(":", "");
|
||||
// Append '00; if we only have a two digit TZ, as SimpleDateFormat
|
||||
if (tz.length() == 2) tz += "00";
|
||||
return tz;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,8 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
package org.jclouds.date.internal;
|
||||
import static org.jclouds.date.internal.DateUtils.trimToMillis;
|
||||
import static org.jclouds.date.internal.DateUtils.trimTZ;
|
||||
import static org.jclouds.date.internal.DateUtils.*;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
@ -42,20 +41,16 @@ public class SimpleDateFormatDateService implements DateService {
|
|||
* guard against the lack of thread safety.
|
||||
*/
|
||||
// @GuardedBy("this")
|
||||
private static final SimpleDateFormat iso8601SecondsSimpleDateFormat = new SimpleDateFormat(
|
||||
"yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||
private static final SimpleDateFormat iso8601SecondsSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
|
||||
|
||||
// @GuardedBy("this")
|
||||
private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
|
||||
Locale.US);
|
||||
private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
|
||||
|
||||
// @GuardedBy("this")
|
||||
private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z",
|
||||
Locale.US);
|
||||
private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
|
||||
|
||||
// @GuardedBy("this")
|
||||
private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss '+0000' yyyy",
|
||||
Locale.US);
|
||||
private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss '+0000' yyyy", Locale.US);
|
||||
|
||||
static {
|
||||
iso8601SimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
|
||||
|
@ -64,83 +59,99 @@ public class SimpleDateFormatDateService implements DateService {
|
|||
cSimpleDateFormat.setTimeZone(new SimpleTimeZone(0, "GMT"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Date fromSeconds(long seconds) {
|
||||
return new Date(seconds * 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String cDateFormat(Date date) {
|
||||
synchronized (cSimpleDateFormat) {
|
||||
return cSimpleDateFormat.format(date);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String cDateFormat() {
|
||||
return cDateFormat(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Date cDateParse(String toParse) {
|
||||
synchronized (cSimpleDateFormat) {
|
||||
try {
|
||||
return cSimpleDateFormat.parse(toParse);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ParseException pe) {
|
||||
throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String rfc822DateFormat(Date date) {
|
||||
synchronized (rfc822SimpleDateFormat) {
|
||||
return rfc822SimpleDateFormat.format(date);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String rfc822DateFormat() {
|
||||
return rfc822DateFormat(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Date rfc822DateParse(String toParse) {
|
||||
synchronized (rfc822SimpleDateFormat) {
|
||||
try {
|
||||
return rfc822SimpleDateFormat.parse(toParse);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ParseException pe) {
|
||||
throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String iso8601SecondsDateFormat() {
|
||||
return iso8601SecondsDateFormat(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String iso8601DateFormat(Date date) {
|
||||
synchronized (iso8601SimpleDateFormat) {
|
||||
return iso8601SimpleDateFormat.format(date);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String iso8601DateFormat() {
|
||||
return iso8601DateFormat(new Date());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Date iso8601DateParse(String toParse) {
|
||||
String tz = findTZ(toParse);
|
||||
toParse = trimTZ(toParse);
|
||||
toParse = trimToMillis(toParse);
|
||||
toParse += tz; // Usable TZ added back
|
||||
synchronized (iso8601SimpleDateFormat) {
|
||||
try {
|
||||
return iso8601SimpleDateFormat.parse(toParse);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ParseException pe) {
|
||||
throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Date iso8601SecondsDateParse(String toParse) {
|
||||
String tz = findTZ(toParse);
|
||||
toParse = trimTZ(toParse);
|
||||
toParse += tz; // Usable TZ added back
|
||||
synchronized (iso8601SecondsSimpleDateFormat) {
|
||||
try {
|
||||
return iso8601SecondsSimpleDateFormat.parse(toParse);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ParseException pe) {
|
||||
throw new RuntimeException("Error parsing data at " + pe.getErrorOffset(), pe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue