ThreeTenABP:DateTimeParseException

ThreeTenABP: DateTimeParseException

提问人:moyo 提问时间:12/19/2018 更新时间:12/19/2018 访问量:1264

问:

尝试更改 String 的日期格式,但收到 DateTimeException:

String oldDate = "2018-12-18T17:04:56+00:00";
String outputFormat = "DD-MM";
try {
    Instant instant = Instant.parse(oldDate);
    LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
    return localDateTime.format(DateTimeFormatter.ofPattern(outputFormat);
} catch (DateTimeException | IllegalArgumentException e) {
    Log.e("Error", e.getLocalizedMessage());
    return "";
}

我收到的错误是:无法在索引 2018 处解析文本“12-18T17:04:56+00:00”

我正在使用 com.jakewharton.threetenabp:threetenabp:1.1.1,因为我无法使用 Java 8 类

Android 日期 时间 threetenbp

评论

0赞 Anonymous 12/19/2018
我想你打算用小写字母(大写字母代表一年中的某一天)。dddd-MMDD
0赞 Anonymous 12/19/2018
如果你想要一个,我认为这种方式有点优雅:。InstantInstant instant = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(oldDate, Instant::from);

答:

3赞 Basil Bourque 12/19/2018 #1

TL的;博士

OffsetDateTime.parse(                // Represent a moment, a date with time-of-day in the context of an offset-from-UTC (some number of hours-minutes-seconds).
    "2018-12-18T17:04:56+00:00"      // Input string in standard ISO 8601 format, with an indicator of an offset-from-UTC of zero hours and zero minutes, meaning UTC itself.
)                                    // Returns an `OffsetDateTime` object.
.atZoneSameInstant(                  // Adjust our moment from UTC to the wall-clock time used by the people of a particular region (a time zone).
    ZoneId.systemDefault()           // Using the JVM’s current default time zone. NOTE: this default can change at any moment during runtime. If important, confirm with the user.
)                                    // Returns a `ZonedDateTime` object.
.toString()                          // Generate text in standard ISO 8601 format wisely extended by appending the name of the zone in square brackets. Returns a `String` object.

2018-12-18T09:04:56-08:00[美国/Los_Angeles]

以下是使用 ThreeTen-Backport 项目的示例 Java 代码,该项目由 ThreeTenABP 扩展,适用于 26 之前的 Android。

import org.threeten.bp.*;

错误的格式化程序

Instant.parse 命令使用 DateTimeFormatter.ISO_INSTANT 格式化程序。该格式化程序期望末尾的 a 表示 UTC。Z

该类是 java.time 框架的基本构建块类。为了获得更大的灵活性,请使用 .其默认格式化程序 DateTimeFormatter.ISO_OFFSET_DATE_TIME 可以处理您的输入。InstantOffsetDateTime

String input = "2018-12-18T17:04:56+00:00";
OffsetDateTime odt = OffsetDateTime.parse( input );

odt.toString():2018-12-18T17:04:56Z

错误的班级

不要使用 LocalDateTime 跟踪某个时刻。该类故意缺少任何时区相对于 UTC 的偏移量的概念。它只是一个日期和一天中的时间。因此,它不能代表一个时刻,从来都不是时间轴上的一个点。相反,这个类代表了 26-27 小时范围内的潜在时刻,即全球时区的范围。

要跟踪某个时刻,请仅使用:

  • 即时
    UTC 中的某个时刻,始终是 UTC。
  • OffsetDateTime
    一个日期,一个时间,具有与 UTC 的偏移量。偏移量只是小时-分钟-秒的数量,仅此而已。
  • ZonedDateTime
    通过特定地区(时区)的人们使用的挂钟时间看到的时刻。区域是特定区域中使用的偏移量的过去、现在和未来变化的历史记录。

要将 UTC 调整到某个时区,请应用 a 以获得 .OffsetDateTimeZoneIdZonedDateTime

ZoneId z = ZoneId.systemDefault() ;  // If important, confirm the zone with user rather than depending on the JVM’s current default zone.
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

zdt.toString():2018-12-18T09:04:56-08:00[美国/Los_Angeles]

通过这些结果,我们看到在北美西海岸的大部分地区,UTC 的下午 5 点同时是上午 9 点。这一天的均值差异,西海岸比UTC晚了八个小时。-08:00


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 中搜索许多示例和解释。规范是 JSR 310

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

从哪里获取 java.time 类?

ThreeTen-Extra 项目使用其他类扩展了 java.time。这个项目是未来可能添加java.time的试验场。您可以在这里找到一些有用的类,例如 IntervalYearWeekYearQuarter

评论

0赞 moyo 12/19/2018
感谢您的解释,但是 DateTimeFormatter 的用法呢?我需要以与我收到的日期不同的格式显示收到的日期。
1赞 Basil Bourque 12/19/2018
@moyo Using 已经在 Stack Overflow 上介绍过很多次了。注意您的格式代码 - 它们区分大小写。您可能会发现 MonthDay 课程很有帮助。DateTimeFormatter