简体   繁体   English

如何解决scala中的无效日期格式错误?

[英]How to solve Invalid Date format error in scala?

I m getting follwing error: 我收到以下错误:

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"

how to resolve following error?? 如何解决以下错误?

I think you have the wrong format here - using SimpleDateFormat and a bit of googling this works: 我认为您这里的格式有误-使用SimpleDateFormat并进行了一些谷歌搜索工作:

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

edit: errr don't forget the timezone and year like I originally did ;-) 编辑:errr不要像我最初那样忘记时区和年份;-)

First thing to note: 首先要注意的是:

Your input is not in ISO-Format and contains the name of a timezone (here: IST). 您输入的不是ISO格式,而是包含时区的名称(此处为IST)。 You tried Joda-Time, but used an ISO-Format. 您尝试了Joda-Time,但是使用了ISO格式。 This cannot work because the ISO-format pattern does not match the non-ISO-input . 这不能工作,因为ISO格式模式与non-ISO-input不匹配 Second reason against Joda-Time is the fact that Joda-Time cannot parse timezone names . 反对Joda-Time的第二个原因是Joda-Time无法解析时区名称 So following approach using a theoretically correct pattern will fail: 因此,以下使用理论上正确的模式的方法将失败:

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"

So you can only change the library. 因此,您只能更改库。 An obvious candidate using the (horrible) class SimpleDateFormat is: 使用(可怕的)类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)

Okay no exception. 好的,也不例外。 But this does not mean that the result is automatically correct. 但这并不意味着结果自动正确。 The result can only be explained by having an offset of (+02:00 for IST). 只能通过偏移量(IST为+02:00)来解释结果。 But is this true??? 但这是真的吗? So let's have a closer look at the timezone involved: 因此,让我们仔细看看所涉及的时区:

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

This should trigger an alarm. 这将触发警报。 Timezone names (especially abbreviations, here: IST) are often ambivalent and denote different timezones with different offsets. 时区名称(尤其是缩写,在这里是IST)通常是矛盾的,它们表示具有不同偏移量的不同时区。

So if you have got the input from Israel then you can be happy, but if from India then the result is wrong by 3:30 hours. 因此,如果您从以色列那里得到了意见,那么您会很高兴,但是如果从印度那里得到的结果到3:30小时是错误的。 Maybe your result will be such that it will match the India case instead of Israel. 也许您的结果将与印度而不是以色列相符。 This will depend on your local timezone configuration. 这将取决于您当地的时区配置。 What so ever, don't blindly trust the parsed offsets. 因此,请不要盲目地相信解析后的偏移量。

The alternative Java-8: 替代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]

It will work if you specify your preferred timezone but you really need to think twice before you parse timezone names. 如果您指定了首选的时区,它将起作用,但是在解析时区名称之前,您确实需要三思。 The builder approach might appear a little bit awkward but cannot be avoided due to the difficulty of the problem. 生成器方法可能看起来有些笨拙,但由于问题的难度而无法避免。 So Java-8 is very fine to give you a solution here. 因此,Java-8非常适合在此处为您提供解决方案。

By the way, if you use a strict style ( DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH).withResolverStyle(ResolverStyle.STRICT) ) then the parser will throw an exception with the message: 顺便说一句,如果您使用严格的样式( DateTimeFormatter.ofPattern(pattern, Locale.ENGLISH).withResolverStyle(ResolverStyle.STRICT) ),则解析器将引发异常消息:

java.time.format.DateTimeParseException: Text 'Tue Dec 29 11:11:30 IST 2015' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {YearOfEra=2015, DayOfMonth=29, DayOfWeek=2, MonthOfYear=12},ISO,Asia/Jerusalem resolved to 11:11:30 of type java.time.format.Parsed java.time.format.DateTimeParseException:无法解析文本'Tue Dec 29 29:11:30 IST 2015':无法从TemporalAccessor获取ZonedDateTime:{YearOfEra = 2015,DayOfMonth = 29,DayOfWeek = 2,MonthOfYear = 12} ,ISO,Asia / Jerusalem解析为java.time.format.Parsed类型的11:11:30

The message is somehow mysterious but I assume it is because of the ambivalent name IST. 该消息某种程度上是神秘的,但我认为这是由于名称IST含混。

If you are working on a platform with older JDK (Java 6 or 7) then you might consider ThreetenBP . 如果您正在使用较旧的JDK(Java 6或7)的平台,则可以考虑ThreetenBP ThreetenBP has the advantage to make a future migration easy (just changing the import statements) but my own experiments with the builder approach failed, unfortunately (even failed with the newest version v1.3.1 - maybe this depends on the underlying JDK???): 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???

Else you can try my library Time4J which works on Java-6 or 7 (or later). 另外,您可以尝试我的 Time4J ,该可在Java-6或7(或更高版本)上运行。 It works similar to Java-8: 它的工作方式类似于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]

The error message in strict or smart parser style using 使用以下严格或智能解析器样式的错误消息

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);

will be: 将会:

Time zone name "IST" not found among preferred timezones in locale en, candidates=[Asia/Colombo, Asia/Jerusalem, Asia/Kolkata, Europe/Dublin] 在语言环境en的首选时区中找不到时区名称“ IST”,候选值= [亚洲/科伦坡,亚洲/耶路撒冷,亚洲/加尔各答,欧洲/都柏林]

Then you will immediately see that "IST" can be associated with different timezones. 然后,您将立即看到“ IST”可以与不同的时区相关联。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM