我正在使用 Android、JUnit 和 SimpleDateFormat
。
我喜欢在带时区的 rfc3339 格式的 String
和 Date
之间做一些转换。
例如: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
最佳答案
旧类(Date
、Calendar
和SimpleDateFormat
)有lots of problems和 design 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/