java - Android - junit - 单元测试 - 带时区的 SimpleDateFormat

标签 java android simpledateformat timezone-offset

我正在使用 Android、JUnit 和 SimpleDateFormat

我喜欢在带时区的 rfc3339 格式的 StringDate 之间做一些转换。

例如:2017-12-31T23:59:59+02:00 但不是 2017-12-31T23:59:59+0200

Android SimpleDateFormat 使用 Z 模式而不是 X 模式(参见下面的 RFC3339_REGEX_1)。

但是在我的JUnit测试(jdk1.8)中,RFC3339_REGEX_1没有给我正确的格式(+02:00),但是+0200。 JUnit 测试在 RFC3339_REGEX_2 下运行良好。

那么我怎样才能做一些在 Android 设备和 JUnit 测试上都运行良好的干净的东西呢?

public static final String RFC3339_REGEX_1 = "yyyy-MM-dd'T'HH:mm:ssZ"; //android
public static final String RFC3339_REGEX_2 = "yyyy-MM-dd'T'HH:mm:ssXXX"; //java

最佳答案

旧类(DateCalendarSimpleDateFormat)有lots of problemsdesign issues ,并且它们正在被新的 API 取代。如果我没记错的话,X 模式 doesn't work in all versions (我知道在 JDK 6 it wasn't supported 中,它仅在 JDK 7 中引入;不确定这对不同的 Android 版本有何影响)。

作为替代方案,在 Android 中您可以使用 ThreeTen Backport .为了让它工作,你还需要 ThreeTenABP (查看如何使用它 here )。

不过,如果您仍然需要使用 java.util.Date,这个 API 可以让事情变得更容易。如果您想要像 2017-12-31T23:59:59+02:00 这样的格式,您可以将 java.util.Date 转换为 org.threeten .bp.OffsetDateTime(使用 org.threeten.bp.DateTimeUtils 类转换值,使用 org.threeten.bp.ZoneOffset 设置偏移到 +02:00):

// assuming that java.util.Date has value equivalent to 2017-12-31T23:59:59+02:00
Date date = ...
// convert to OffsetDateTime (use +02:00 offset)
OffsetDateTime odt = DateTimeUtils.toInstant(date).atOffset(ZoneOffset.of("+02:00"));
System.out.println(odt); // 2017-12-31T23:59:59+02:00

输出将是:

2017-12-31T23:59:59+02:00

请注意,这是 odt.toString() 的结果(被 System.out.println 称为隐式),默认情况下它与您的格式匹配想。但您也可以通过使用 org.threeten.bp.format.DateTimeFormatter 强制执行特定格式:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
System.out.println(fmt.format(odt));

输出是一样的。唯一的区别是第一个版本(使用 toString())将打印秒的小数部分(如果它们不为零),如果它们为零则将忽略秒,而第二个版本(使用formatter) 将始终以所需格式打印(在这种情况下,打印秒而不是秒的小数部分),无论值是否为零。

我相信,在您的情况下,您将需要一个格式化程序,因为您似乎总是需要一种带有秒和没有几分之一秒的格式。


要将 OffsetDateTime 转换回 Date,您也可以使用 DateTimeUtils:

// convert back to java.util.Date
date = DateTimeUtils.toDate(odt.toInstant());

如果你不需要使用java.util.Date,你可以直接使用OffsetDateTime:

// create OffsetDateTime with value = 2017-12-31T23:59:59+02:00
OffsetDateTime odt = OffsetDateTime.of(2017, 12, 31, 23, 59, 59, 0, ZoneOffset.ofHours(2));

另请注意,我使用了 ZoneOffset.ofHours(2),它等同于 ZoneOffset.of("+02:00")

您还可以使用 OffsetDateTime.now(ZoneOffset.ofHours(2)) 获取当前日期。


ThreeTen Backport 是新的 Java 8 日期/时间类的反向端口,它有许多不同的日期和时间类型(如上面的 OffsetDateTime)可用于不同的情况。 Check this tutorial有关哪种类型最适合您的情况的更多信息 - 本教程涵盖 Java 8,但 ThreeTen Backport 具有相同的类和方法名称,只是包不同:org.threeten.bp 而不是 java.time.

关于java - Android - junit - 单元测试 - 带时区的 SimpleDateFormat,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45283340/

相关文章:

java - 如何使用 Android 对 Firestore 进行分页?

java - Kubernetes java api 客户端更改 pod 标签

java - 如何找到两个日期之间的年数?

android - 谷歌云消息 'Not Registered'失败和退订最佳实践?

android - 我的(非 Android)库内部使用的库未包含在 classes.dex 中

android - 在Android中设置RatingBar星级选择颜色

java - SimpleDateFormat 未正确解析毫秒

java - 使用 SimpleDateFormat 获取月份名称错误

java - 为什么 SimpleDateFormat.format() 和 SimpleDateFormat.parse() 只设置一个时区却给出不同的时间?

java - Java SE 6 之前的脚本引擎?