当我在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
java.time.Instant.ofEpochMilli( 1_554_091_200_000L )
您已经了解到,如果您未指定JVM的日期时间类,则会隐式应用JVM的当前默认时区。这意味着您的结果可能会在运行时变化。更糟糕的是,您的结果可能会在运行时发生变化,因为JVM中任何应用程序的任何线程中的任何代码都可以change that default!
最好始终指定所需/预期的时区。如果对您的应用至关重要,请与用户确认该区域。
更好的是:专注于UTC工作。仅在业务逻辑需要的时间区域使用时区或向用户显示时区。
ZoneId
以proper time zone name的格式指定Continent/Region
,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用2-4字母缩写,如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
如果要使用JVM的当前默认时区,请求它并作为参数传递。如果省略,代码变得模糊不清,因为我们不确定您是否打算使用默认值,或者如果您像许多程序员一样,不知道这个问题。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
您应该知道优秀的Joda-Time项目现在处于维护模式。它的创建者Stephen Colebourne利用那里学到的经验继续创建JSR 310及其实现java.time类。
查看旧版Android和Java下面的项目符号。
java.time.Instant
类代表UTC的一个时刻。在内部,它是自UTC 1970年第一个时刻以来的纳秒数。
Instant instant = Instant.ofEpochMilli( 1_554_091_200_000L ) ;
ZoneId z = ZoneId.of( "America/Puerto_Rico" ) ;
ZonedDateTime zdt = instant.atZone( z )
Instant
和ZonedDateTime
都代表同一时刻,时间轴上的同一点。通过特定区域(时区)的人们使用的挂钟时间可以看出,同一时刻的显示方式不同。
看到这个code run live at IdeOne.com。
instant.toString():2019-04-01T04:00:00Z
zdt.toString():2019-04-01T00:00-04:00 [America / Puerto_Rico]
Clock
为了更好地进行测试,将备用Clock
对象作为各种方法的可选参数传递。请参阅Clock
类以获得stuck on a certain moment或lag behind the true time或use a different cadence的时钟,例如以whole second或whole minute的速率递增。
搜索堆栈溢出。所有这些主题已经多次得到解决。
提示:使用像DuckDuckGo这样的互联网搜索引擎,标准为site:stackoverflow.com
。 Stack Overflow中的搜索工具是贫血的,有缺陷的,并且偏向于查看问题而不是答案。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规格是JSR 310。
现在在Joda-Time的maintenance mode项目建议迁移到java.time班。
您可以直接与数据库交换java.time对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
基本上发生了什么是joda时间使用不同的时区然后我的测试期待。
我通过将其添加到我的测试中来解决它。
@Before
fun setUp() {
DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getTimeZone("CET")))
}
所以现在我在运行测试的每个地方使用相同的TimeZone