使用Joda Time时在ci上测试失败

时间:2019-04-06 18:31:32

标签: android jodatime

当我在CI服务器上运行测试时,它们的测试开始失败。我在这条线上收到断言错误

assertEquals(DateTime(1554091200000), generateNextTime())

我遇到错误

java.lang.AssertionError: 
Expected :2019-04-01T00:00:00.000-04:00
Actual   :2019-03-31T20:00:00.000-04:00

2 个答案:

答案 0 :(得分:1)

tl; dr

java.time.Instant.ofEpochMilli( 1_554_091_200_000L ) 

始终指定时区

您已经了解到,如果您未指定日期时间类,则日期时间类会回退到隐式应用JVM当前的默认时区。这意味着您的结果在运行时可能会有所不同。更糟糕的是,您的结果在 运行时可能会有所不同,因为JVM中任何应用程序的任何线程中的任何代码都可以change that default

最好始终指定您想要的/期望的时区。如果对您的应用程序至关重要,请与用户确认区域。

甚至更好:专注于UTC工作。仅在业务逻辑要求或向用户展示时使用时区。

ZoneId

Continent/Region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  

如果要使用JVM的当前默认时区,请提出要求并作为参数传递。如果省略,代码将变得难以理解,因为我们不确定您是否打算使用默认值,还是像许多程序员一样不知道该问题。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Joda-Time

您应该知道,出色的Joda-Time项目现在处于维护模式。它的创建者Stephen Colebourne利用那里获得的经验教训,继续创建了JSR 310及其实现 java.time 类。

有关旧版Android和Java,请参见下面的项目符号。

java.time.Instant类代表UTC的时刻。从内部看,这是自1970年UTC的第一刻以来的纳秒计数。

Instant instant = Instant.ofEpochMilli( 1_554_091_200_000L ) ;

ZoneId z = ZoneId.of( "America/Puerto_Rico" ) ;
ZonedDateTime zdt = instant.atZone( z ) 

InstantZonedDateTime代表同一时刻,时间轴上的同一点。从特定区域(时区)的人们使用的挂钟时间可以看出,同一时刻同时显示的方式有所不同。

请参阅此code run live at IdeOne.com

  

instant.toString():2019-04-01T04:00:00Z

     

zdt.toString():2019-04-01T00:00-04:00 [美国/波多黎各]

Clock

为进行更好的测试,请将备用Clock对象作为可选参数传递给各种方法。请参阅Clock类以获取stuck on a certain momentlag behind the true timeuse a different cadence的时钟,例如以whole second或{{3 }}。

搜索堆栈溢出

搜索堆栈溢出。所有这些主题已经被解决了很多次。

提示:使用标准为site:stackoverflow.com的Internet搜索引擎,例如DuckDuckGo。 Stack Overflow中的搜索功能过时,错误且偏向于查看问题而不是答案。


关于 java.time

whole minute框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacyjava.util.DateCalendar

要了解更多信息,请参见SimpleDateFormat。并在Stack Overflow中搜索许多示例和说明。规格为Oracle Tutorial

目前位于JSR 310Joda-Time项目建议迁移到maintenance mode类。

您可以直接与数据库交换 java.time 对象。使用符合java.time或更高版本的JDBC driver。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

答案 1 :(得分:0)

基本上发生了什么事,乔达时间使用的时区与我的测试期望的时区不同。

我通过将其添加到测试中解决了该问题。

@Before
fun setUp() {
    DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getTimeZone("CET")))
}

所以现在我在运行测试的所有地方都使用相同的TimeZone