2017-07-24 17 views
1

我正在使用Android,JUnit和SimpleDateFormatAndroid - junit - 单元测试 - 带时区的SimpleDateFormat

我喜欢在StringDate之间进行rfc3339格式与时区的转换。

例如: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 

回答

2

老班(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.Dateorg.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()的结果(这是由0称为含蓄),默认情况下它与您想要的格式相匹配。但你也可以强制执行特定的格式,通过使用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)); 

另请注意t我使用了ZoneOffset.ofHours(2),这相当于ZoneOffset.of("+02:00")

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


ThreeTen反向移植为新的Java 8的日期/时间类一个反向移植,并且其具有许多不同的日期和时间类型(如上面所述OffsetDateTime)在不同的情况下使用。 Check this tutorial有关哪种类型最适合您的情况的更多信息 - 本教程涵盖了Java 8,但ThreeTen Backport具有相同的类和方法名称,只是包装不同:org.threeten.bp而不是java.time

+0

在Joda时间,我们有AbstractDateTime类,它提供了datetime类的常见行为,我没有在threeten中找到通讯器(提供LocalDateTime,ZonedDateTime和OffsetDateTime,但没有抽象类)? –

+0

@ Anh-TuanMai你需要什么常见的行为?根据你的需要,你可以使用'Temporal'或'TemporalAccessor'接口 – 2017-07-25 09:56:52

+0

我喜欢在Joda时间有一些像BaseDateTime.getMillis()和一个毫秒的构造函数:) –