[英]Java String to Date format
I have below String
of date that I'm trying to parse and format to Sept 21 2021
but having ParsingException
:我有以下日期
String
,我试图将其解析并格式化为Sept 21 2021
但有ParsingException
:
String expiryDate ="Tue Sep 21 12:11:37 PHT 2021";
System.out.println(expiryDate);
Date formatter = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy").parse(expiryDate);
Exception in thread "main" java.text.ParseException:
Unparseable date: "Tue Sep 21 12:11:37 PHT 2021"
at java.base/java.text.DateFormat.parse(DateFormat.java:395)
I guess I have incorrect parsing date format but can't figure out the correct one.我想我的解析日期格式不正确,但无法找出正确的格式。
I think your problem is the missing Locale
in your SimpleDateFormat
.我认为您的问题是
SimpleDateFormat
缺少Locale
。 If you don't explicitly set one, the code may use your default Locale
, which then might not be ENGLISH
but something else, which is likely to be on a computer located on the Philipines.如果您没有明确设置,代码可能会使用您的默认
Locale
,然后它可能不是ENGLISH
而是其他东西,它可能位于菲律宾的计算机上。 It would try to parse the Philipine abbreviation for Tue , for example, and that leads to an unparseable String
.例如,它会尝试解析Tue的菲律宾缩写,这会导致无法解析的
String
。
Here is what worked on my computer (also not ENGLISH
) after having got the same Exception
as you:在遇到与您相同的
Exception
后,这是在我的计算机上运行的(也不是ENGLISH
):
String expiryDate = "Tue Sep 21 12:11:37 PHT 2021";
Date date = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH)
.parse(expiryDate);
System.out.println(date.toString());
This gave the following output:这给出了以下输出:
Tue Sep 21 06:11:37 CEST 2021
This worked with a pattern having just one E
as well.这也适用于只有一个
E
的模式。
java.time
:java.time
Java 8 - 10 解决方案: This successfully runs on Java 8 and 10, but according to the answer by @ArvindKumarAvinash , this won't work in Java 11 and possibly the versions above due to the abbreviation of the time zone in the String expiryDate
.这在 Java 8 和 10 上成功运行,但根据@ArvindKumarAvinash 的回答,由于
String expiryDate
时区的缩写,这在 Java 11 和上述版本中可能String expiryDate
。
You could do it like this in java.time
:你可以在
java.time
这样做:
String expiryDate = "Tue Sep 21 12:11:37 PHT 2021";
DateTimeFormatter parserDtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu",
Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(expiryDate, parserDtf);
System.out.println("Something will expire at " + zdt);
and it would output它会输出
Something will expire at 2021-09-21T12:11:37+08:00[Asia/Manila]
Changing the output format can be done via another DateTimeFormatter
, either use a built-in one as DateTimeFormatter.ISO_ZONED_DATE_TIME
or create a custom one by .ofPattern(pattern, Locale.ENGLISH)
or using a DateTimeFormatterBuilder
.可以通过另一个
DateTimeFormatter
更改输出格式,或者使用内置的DateTimeFormatter.ISO_ZONED_DATE_TIME
或通过.ofPattern(pattern, Locale.ENGLISH)
或使用DateTimeFormatterBuilder
创建自定义.ofPattern(pattern, Locale.ENGLISH)
。
Considering your requirement to format and output the date part only, you have the option to simply extract the date part (that's a LocalDate
) and format that in java.time
:考虑到您只需要格式化和输出日期部分,您可以选择简单地提取日期部分(即
LocalDate
)并在java.time
中java.time
:
String expiryDate = "Tue Sep 21 12:11:37 PHT 2021";
DateTimeFormatter parserDtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu",
Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(expiryDate, parserDtf);
LocalDate expiryLocalDate = zdt.toLocalDate();
System.out.println("Something will expire at "
+ expiryLocalDate.format(DateTimeFormatter.ofPattern("MMM dd uuuu",
Locale.ENGLISH)));
will output会输出
Something will expire at Sep 21 2021
Read more about java.time
in the Trails .在Trails 中阅读有关
java.time
更多信息。
The answer by deHaar is brilliant but that fails with Java-11. deHaar的回答很精彩,但在 Java-11 中失败了。 A safe option will be to replace PHT with the corresponding Zone-Offset value .
一个安全的选择是将 PHT 替换为相应的 Zone-Offset 值。
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String expiryDate = "Tue Sep 21 12:11:37 PHT 2021".replace("PHT", "GMT+08:00");
OffsetDateTime odt = OffsetDateTime.parse(expiryDate,
DateTimeFormatter.ofPattern("EEE MMM d H:m:s ZZZZ u", Locale.ENGLISH));
System.out.println(odt);
// Custom format
String formatted = odt.format(DateTimeFormatter.ofPattern("EEEE MMMM dd uuuu 'at' hh:mm:ss a", Locale.ENGLISH));
System.out.println(formatted);
}
}
Output:输出:
2021-09-21T12:11:37+08:00
Tuesday September 21 2021 at 12:11:37 PM
Note: java.util
date-time classes are outdated and error-prone and so is their formatting API, SimpleDateFormat
.注意:
java.util
日期时间类已经过时且容易出错,它们的格式化 API SimpleDateFormat
也是如此。 I suggest you should stop using them completely and switch to the modern date-time API .我建议您应该完全停止使用它们并切换到现代日期时间 API 。
If you are doing it for your Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project .如果您正在为您的 Android 项目执行此操作,并且您的 Android API 级别仍然不符合 Java-8,请查看 通过脱糖可用的 Java 8+ API和如何在 Android 项目中使用 ThreeTenABP 。
Learn more about the modern date-time API at Trail: Date Time .在Trail: Date Time 中了解有关现代日期时间 API 的更多信息。
With legacy API:使用旧 API:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
String expiryDate = "Tue Sep 21 12:11:37 PHT 2021".replace("PHT", "GMT+08:00");
Date date = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZZ yyyy").parse(expiryDate);
System.out.println(date);
// Custom format
String formatted = new SimpleDateFormat("EEEE MMMM dd yyyy 'at' hh:mm:ss a", Locale.ENGLISH).format(date);
System.out.println(formatted);
}
}
I'm new here, sorry if I did anything wrong.我是新来的,如果我做错了什么,抱歉。
The "Tue" contains three character and the format should be “Tue”包含三个字符,格式应为
"EEE MMM dd HH:mm:ss z yyyy"
It seems that the abbrevatiosn for Philipines Standard Time was PHT up to Java 10 whereas it's PST from Java 11. One way to see this is running the following piece of code:似乎菲律宾标准时间的缩写是 PHT 到 Java 10 而它是 Java 11 的 PST。查看它的一种方法是运行以下代码:
DateTimeFormatter zf = DateTimeFormatter.ofPattern("z", Locale.ROOT);
ZoneId zid = ZoneId.of("Asia/Manila");
System.out.println(zf.format(ZonedDateTime.now(zid)));
Output on Java 9: Java 9 上的输出:
PHT
PHT
Output on Java 11: Java 11 上的输出:
PST
太平洋标准时间
I thought at first that different versions of CLDR, the Unicode Common Locale Data Repository, was the reason.起初我认为是 CLDR 的不同版本,即 Unicode 通用语言环境数据存储库,是原因。 But when I use Java's original locale data instead (running with
-Djava.locale.providers=COMPAT
), I get the same difference in behaviuour, so I am not so sure.但是当我使用 Java 的原始语言环境数据(使用
-Djava.locale.providers=COMPAT
运行)时,我在行为上得到了相同的差异,所以我不太确定。
In any case you should not rely in three letter time zone abbreviaitons in the first place if there is any way you can avoid it.在任何情况下,如果有任何方法可以避免它,您首先不应该依赖三个字母的时区缩写。 They tend to be ambiguous, and they are not standardized.
它们往往是模棱两可的,并且没有标准化。 So you really cannot be sure what you get.
所以你真的不能确定你得到了什么。
Apart from that the comments and answers telling you to specify a locale for your formatter are correct too.除此之外,告诉您为格式化程序指定语言环境的评论和答案也是正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.