问题描述
我以 2021-06-20T09:56:05.697Z
格式从服务器获取 UTC 时间。我想将其格式化为用户时区,并尝试了以下代码。但它返回
java.text.ParseException:无法解析的日期:“2021-06-20T09:56:05.697Z”
使用的代码:(来自服务器的 dateInString 为“2021-06-20T09:56:05.697Z”)
String dateStr = dateInString;
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z",Locale.ENGLISH);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date dateex = df.parse(dateStr);
df.setTimeZone(TimeZone.getDefault());
String formattedDate = df.format(dateex);
解决方法
java.time 通过脱糖
考虑使用 java.time,现代 Java 日期和时间 API,用于您的日期和时间工作。让我们首先为我们想要的格式声明一个格式化程序:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z",Locale.ENGLISH);
现在转换是这样的:
String dateStr = "2021-06-20T09:56:05.697Z";
Instant dateex = Instant.parse(dateStr);
ZonedDateTime dateTime = dateex.atZone(ZoneId.systemDefault());
String formattedDate = dateTime.format(FORMATTER);
System.out.println("Formatted date and time: " + formattedDate);
示例输出:
格式化日期和时间:2021-06-20 05:56:05 AST
这是在美国/托尔托拉时区的计算机上运行的,我们看到日期和时间已按要求转换为大西洋标准时间。
我正在利用来自服务器的字符串采用 ISO 8601 格式这一事实,java.time 的类通常在没有任何显式格式化程序的情况下本地解析这种格式。
您的代码出了什么问题?
解析来自服务器的字符串时,如果对其使用格式化程序,则该格式化程序需要知道要解析的格式。它知道以后要格式化的格式也无济于事。
问题:java.time 不需要 Android API 级别 26 吗?
java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少 Java 6。
- 在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 开始)中,内置了现代 API。
- 在非 Android Java 6 和 7 中获得 ThreeTen Backport,现代类的向后移植(ThreeTen for JSR 310;请参阅底部的链接)。
- 在较旧的 Android 上,使用脱糖或 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。在后一种情况下,请确保使用子包从
org.threeten.bp
导入日期和时间类。
链接
- Oracle tutorial: Date Time 解释如何使用 java.time。
-
Java Specification Request (JSR) 310,其中首次描述了
java.time
。 -
ThreeTen Backport project,将
java.time
向后移植到 Java 6 和 7(JSR-310 的 ThreeTen)。 - Java 8+ APIs available through desugaring
- ThreeTenABP,ThreeTen Backport 的 Android 版
- Question: How to use ThreeTenABP in Android Project,非常详尽的解释。
- Wikipedia article: ISO 8601