我正在使用Android,JUnit和SimpleDateFormat
。
我喜欢在String
和Date
之间以时区的 rfc3339 格式进行一些转换。
例如:2017-12-31T23:59:59+02:00
但不是2017-12-31T23:59:59+0200
。
AndroidSimpleDateFormat
使用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
(有很多问题和设计问题,它们正在被新的 API 所取代。如果我没记错的话,X
模式并非在所有版本中都有效(我知道在JDK 6中不支持它,它仅在JDK 7中引入;不确定这对不同的Android版本有何影响(。
作为替代方案,在Android中,您可以使用ThreeTen Backport。要使其工作,您还需要ThreeTenABP(在此处查看如何使用它(。
但是,如果您仍然需要使用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()
(将打印秒的小数部分(如果它们不为零(,如果秒为零,将省略秒,而第二个版本(使用格式化程序(将始终以所需的格式打印(在这种情况下,打印秒但不打印秒的小数部分(, 无论值是否为零。
我相信,在您的情况下,您将需要一个格式化程序,因为您似乎总是需要一种有秒和没有秒的格式。
要将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
(可用于不同情况。查看本教程以获取有关哪种类型最适合您的情况的更多信息 - 本教程涵盖了 Java 8,但 ThreeTen Backport 具有相同的类和方法名称,只是包不同:org.threeten.bp
而不是java.time
。