我遇到了以下错误:
val formatter = ISODateTimeFormat.dateTimeParser()
scala> val date2 = "Tue Dec 29 11:11:30 IST 2015"
date2: String = Tue Dec 29 11:11:30 IST 2015
scala> formatter.parseDateTime(date2)
java.lang.IllegalArgumentException: Invalid format: "Tue Dec 29 11:11:30 IST 2015" is malformed at "ue Dec 29 11:11:30 IST 2015"
如何解决以下错误?
答案 0 :(得分:4)
我认为你的格式错误 - 使用SimpleDateFormat和a bit of googling这有效:
scala> val formatter = new java.text.SimpleDateFormat("EEE MMM d HH:mm:ss Z yyyy")
formatter: java.text.SimpleDateFormat = java.text.SimpleDateFormat@73342172
scala> formatter.parse("Tue Dec 29 11:11:30 IST 2015")
res1: java.util.Date = Tue Dec 29 09:11:30 GMT 2015
编辑:错误不要忘记我最初做的时区和年份; - )
答案 1 :(得分:3)
首先要注意的是:
您的输入不是ISO格式,并且包含时区名称(此处为:IST)。您尝试过Joda-Time,但使用的是ISO格式。这不起作用,因为 ISO格式模式与非ISO输入不匹配。反对Joda-Time的第二个原因是 Joda-Time无法解析时区名称。因此,使用理论上正确的模式的跟随方法将失败:
String input = "Tue Dec 29 11:11:30 IST 2015";
DateTimeFormatter dtf =
DateTimeFormat.forPattern("EEE MMM d HH:mm:ss z yyyy").withLocale(Locale.ENGLISH);
DateTime unparseable = dtf.parseDateTime(input);
// java.lang.IllegalArgumentException:
// Invalid format: "Tue Dec 29 11:11:30 IST 2015" is malformed at "IST 2015"
因此您只能更改库。使用(可怕的)课程SimpleDateFormat
的明显候选人是:
String input = "Tue Dec 29 11:11:30 IST 2015";
String pattern = "EEE MMM d HH:mm:ss z yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.ENGLISH);
java.util.Date jud = sdf.parse(input);
System.out.println(jud); // Tue Dec 29 10:11:30 CET 2015 (in my local tz CET=+01:00)
好吧也不例外。但这并不意味着结果会自动纠正。结果只能通过偏移量(IST为+02:00)来解释。但这是真的???那么让我们仔细看看所涉及的时区:
TimeZone india = TimeZone.getTimeZone("Asia/Kolkata");
TimeZone israel = TimeZone.getTimeZone("Asia/Jerusalem");
System.out.println(israel.getDisplayName(false, TimeZone.SHORT)); // IST
System.out.println(india.getDisplayName(false, TimeZone.SHORT)); // IST
System.out.println(israel.getOffset(jud.getTime()) / 1000); // 7200 = +02:00
System.out.println(india.getOffset(jud.getTime()) / 1000); // 19800 = +05:30
这应该触发警报。时区名称(尤其是缩写,这里:IST)通常是矛盾的,表示具有不同偏移的不同时区。
所以,如果你得到了以色列的意见,那么你会感到高兴,但是如果来自印度那么结果在3:30之后就会出错。也许你的结果会匹配印度的情况而不是以色列。这取决于您当地的时区配置。所以,不要盲目相信解析的偏移量。
替代Java-8:
String input = "Tue Dec 29 11:11:30 IST 2015";
ZoneId india = ZoneId.of("Asia/Kolkata");
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.appendPattern("EEE MMM d HH:mm:ss ");
builder.appendZoneText(TextStyle.SHORT, Collections.singleton(india)); // preferred zone
builder.appendPattern(" yyyy");
DateTimeFormatter dtf = builder.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(input, dtf);
System.out.println(zdt); // 2015-12-29T11:11:30+05:30[Asia/Kolkata]
// compare dangerous standard approach (not specifying your zone preference)
String pattern = "EEE MMM d HH:mm:ss z yyyy";
zdt = ZonedDateTime.parse(input, DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH));
System.out.println(zdt); // 2015-12-29T11:11:30+02:00[Asia/Jerusalem]
如果您指定首选时区,它会起作用,但在解析时区名称之前,您确实需要三思而后行。构建器方法可能看起来有点尴尬但由于问题的困难而无法避免。 因此,Java-8可以很好地为您提供解决方案。
顺便说一句,如果你使用严格的样式(DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH).withResolverStyle(ResolverStyle.STRICT)
),那么解析器将抛出一个带有消息的异常:
java.time.format.DateTimeParseException:Text'Tue Dec 29 11:11:30 IST 2015'无法解析:无法从中获取ZonedDateTime TemporalAccessor:{YearOfEra = 2015,DayOfMonth = 29,DayOfWeek = 2, MonthOfYear = 12},ISO,亚洲/耶路撒冷解决了类型的11:11:30 java.time.format.Parsed
这条消息有点神秘,但我认为这是因为IST的矛盾名称。
如果您正在使用旧版JDK(Java 6或7)的平台上工作,那么您可能会考虑ThreetenBP。 ThreetenBP 的优点是可以轻松实现未来的迁移(只需更改导入语句)但不幸的是,我自己的构建器方法实验失败了(即使最新版本v1.3.1失败了 - 可能这取决于基础JDK ???):
String input = "Tue Dec 29 11:11:30 IST 2015";
ZoneId india = ZoneId.of("Asia/Kolkata");
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.appendPattern("EEE MMM d HH:mm:ss ");
builder.appendZoneText(TextStyle.SHORT, Collections.singleton(india)); // preferred zone
builder.appendPattern(" yyyy");
DateTimeFormatter dtf = builder.toFormatter(Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(input, dtf);
System.out.println(zdt); // 2015-12-29T11:11:30+02:00[Israel] // why???
否则,您可以尝试使用适用于Java-6或7(或更高版本)的my library Time4J 。它的工作方式类似于Java-8:
String input = "Tue Dec 29 11:11:30 IST 2015";
TZID india = ASIA.KOLKATA;
ChronoFormatter<Moment> f = ChronoFormatter.setUp(Moment.axis(), Locale.ENGLISH)
.addPattern("EEE MMM d HH:mm:ss ", PatternType.CLDR)
.addShortTimezoneName(Collections.singleton(india)) // preferred zone
.addPattern(" yyyy", PatternType.CLDR)
.build();
System.out.println(f.parse(input)); // 2015-12-29T05:41:30Z
System.out.println(ZonalDateTime.parse(input, f)); // 2015-12-29T11:11:30UTC+05:30[Asia/Kolkata]
使用
的严格或智能解析器样式的错误消息String input = "Tue Dec 29 11:11:30 IST 2015";
String pattern = "EEE MMM d HH:mm:ss z yyyy";
ChronoFormatter<Moment> f = // here smart standard style!
ChronoFormatter.ofMomentPattern(
pattern, PatternType.CLDR, Locale.ENGLISH, ZonalOffset.UTC);
f.parse(input);
将是:
在locale en的首选时区中找不到时区名称“IST”, 候选人= [亚洲/科伦坡,亚洲/耶路撒冷,亚洲/加尔各答,欧洲/都柏林]
然后你会立即看到“IST”可以与不同的时区相关联。