Java 字符串转日期格式
Java String to Date format
我尝试解析并格式化为 Sept 21 2021
的日期低于 String
,但有 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)
我想我解析的日期格式不正确,但找不到正确的格式。
我是新来的,如果我做错了什么请见谅。
“星期二”包含三个字符,格式应为
"EEE MMM dd HH:mm:ss z yyyy"
我认为你的问题是 SimpleDateFormat
中缺少 Locale
。如果您没有明确设置一个,代码可能会使用您的默认 Locale
,这可能不是 ENGLISH
,而是其他东西,这可能位于菲律宾的计算机上。例如,它会尝试解析 Tue 的菲律宾语缩写,这会导致无法解析 String
.
在获得与您相同的 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());
这给出了以下输出:
Tue Sep 21 06:11:37 CEST 2021
这也适用于只有一个 E
的模式。
Java 8 - 10 解 java.time
:
这在 Java 8 和 10 上成功运行,但根据 ,这在 Java 11 和可能以上版本中不起作用String expiryDate
.
中的时区缩写
您可以在 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);
它会输出
Something will expire at 2021-09-21T12:11:37+08:00[Asia/Manila]
可以通过另一个 DateTimeFormatter
更改输出格式,使用 built-in 作为 DateTimeFormatter.ISO_ZONED_DATE_TIME
或通过 .ofPattern(pattern, Locale.ENGLISH)
创建自定义格式或使用 DateTimeFormatterBuilder
.
考虑到您只需要格式化和输出日期部分,您可以选择简单地提取日期部分(即 LocalDate
)并将其格式化为 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)));
会输出
Something will expire at Sep 21 2021
在 Trails 中阅读有关 java.time
的更多信息。
is brilliant but that fails with Java-11. A safe option will be to replace PHT with the corresponding Zone-Offset value.
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);
}
}
输出:
2021-09-21T12:11:37+08:00
Tuesday September 21 2021 at 12:11:37 PM
注意: java.util
date-time 类 已过时,error-prone 格式也已过时 API , SimpleDateFormat
。我建议你应该完全停止使用它们并切换到 modern date-time API.
如果您正在为您的 Android 项目执行此操作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring and .
了解有关现代 date-time 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);
}
}
解释
菲律宾标准时间的缩写似乎是 PHT 到 Java 10,而 PST 从 Java 11 开始。一种查看方式是 运行 以下片段代码:
DateTimeFormatter zf = DateTimeFormatter.ofPattern("z", Locale.ROOT);
ZoneId zid = ZoneId.of("Asia/Manila");
System.out.println(zf.format(ZonedDateTime.now(zid)));
Java9 上的输出:
PHT
Java11 上的输出:
PST
起初我以为是 CLDR(Unicode Common Locale Data Repository)版本不同的原因。但是当我使用 Java 的原始语言环境数据代替时 (运行 -Djava.locale.providers=COMPAT
),我在行为上得到了相同的差异,所以我不太确定。
在任何情况下,如果有任何方法可以避免,您首先不应依赖三个字母的时区缩写。它们往往是模棱两可的,而且没有标准化。所以你真的不能确定你得到了什么。
除此之外,告诉您为格式化程序指定语言环境的评论和答案也是正确的。
我尝试解析并格式化为 Sept 21 2021
的日期低于 String
,但有 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)
我想我解析的日期格式不正确,但找不到正确的格式。
我是新来的,如果我做错了什么请见谅。
“星期二”包含三个字符,格式应为
"EEE MMM dd HH:mm:ss z yyyy"
我认为你的问题是 SimpleDateFormat
中缺少 Locale
。如果您没有明确设置一个,代码可能会使用您的默认 Locale
,这可能不是 ENGLISH
,而是其他东西,这可能位于菲律宾的计算机上。例如,它会尝试解析 Tue 的菲律宾语缩写,这会导致无法解析 String
.
在获得与您相同的 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());
这给出了以下输出:
Tue Sep 21 06:11:37 CEST 2021
这也适用于只有一个 E
的模式。
Java 8 - 10 解 java.time
:
这在 Java 8 和 10 上成功运行,但根据 String expiryDate
.
您可以在 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);
它会输出
Something will expire at 2021-09-21T12:11:37+08:00[Asia/Manila]
可以通过另一个 DateTimeFormatter
更改输出格式,使用 built-in 作为 DateTimeFormatter.ISO_ZONED_DATE_TIME
或通过 .ofPattern(pattern, Locale.ENGLISH)
创建自定义格式或使用 DateTimeFormatterBuilder
.
考虑到您只需要格式化和输出日期部分,您可以选择简单地提取日期部分(即 LocalDate
)并将其格式化为 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)));
会输出
Something will expire at Sep 21 2021
在 Trails 中阅读有关 java.time
的更多信息。
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);
}
}
输出:
2021-09-21T12:11:37+08:00
Tuesday September 21 2021 at 12:11:37 PM
注意: java.util
date-time 类 已过时,error-prone 格式也已过时 API , SimpleDateFormat
。我建议你应该完全停止使用它们并切换到 modern date-time API.
如果您正在为您的 Android 项目执行此操作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring and
旧版 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);
}
}
解释
菲律宾标准时间的缩写似乎是 PHT 到 Java 10,而 PST 从 Java 11 开始。一种查看方式是 运行 以下片段代码:
DateTimeFormatter zf = DateTimeFormatter.ofPattern("z", Locale.ROOT);
ZoneId zid = ZoneId.of("Asia/Manila");
System.out.println(zf.format(ZonedDateTime.now(zid)));
Java9 上的输出:
PHT
Java11 上的输出:
PST
起初我以为是 CLDR(Unicode Common Locale Data Repository)版本不同的原因。但是当我使用 Java 的原始语言环境数据代替时 (运行 -Djava.locale.providers=COMPAT
),我在行为上得到了相同的差异,所以我不太确定。
在任何情况下,如果有任何方法可以避免,您首先不应依赖三个字母的时区缩写。它们往往是模棱两可的,而且没有标准化。所以你真的不能确定你得到了什么。
除此之外,告诉您为格式化程序指定语言环境的评论和答案也是正确的。