我正在使用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()
)如果不为零,则将打印秒的分数;如果它们为零,则将忽略秒,而第二个版本(使用格式化程序)将始终在所需的格式(在这种情况下,显示秒,但不打印秒的分数),无论值是否为零。我认为,就您而言,您将需要一个格式化程序,因为您似乎总是需要一种具有秒且没有几分之一秒的格式。
要将
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
。