【问题标题】:Assertion failure for calculating hour difference计算时差的断言失败
【发布时间】:2015-07-07 01:49:54
【问题描述】:

我正在从日历日期中减去500 hours,我的方法是以小时为单位。

为什么下面的断言失败了?

测试方法:

 public long dataFetchTotalTime(long time) {
        long hours = 0;
        Calendar ackCal = Calendar.getInstance();
        long diff = ackCal.getTime().getTime() - time;
        hours = TimeUnit.HOURS.convert(diff, TimeUnit.MILLISECONDS);
        return hours;
    }

测试用例:

@Test
public void checkFetchTimeDiff()
{
    long expected = 500;
    Client client = new Client();
    Calendar ackCal = Calendar.getInstance();
    ackCal.set(Calendar.HOUR_OF_DAY, -500);
    long actual = client.dataFetchTotalTime(ackCal.getTime().getTime());
    Assert.assertEquals(expected, actual);
}

错误追踪:

java.lang.AssertionError: expected:<500> but was:<514>
    at org.junit.Assert.fail(Assert.java:88)
    at org.junit.Assert.failNotEquals(Assert.java:834)
    at org.junit.Assert.assertEquals(Assert.java:645)
    at org.junit.Assert.assertEquals(Assert.java:631)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

【问题讨论】:

    标签: java date calendar assertion


    【解决方案1】:

    这是一个错误:

    ackCal.set(Calendar.HOUR_OF_DAY, -500);
    

    测试方法:

     public long dataFetchTotalTime(long time) {
            long hours = 0;
            Calendar ackCal = Calendar.getInstance();
            long diff = ackCal.getTime().getTime() - time;
            hours = TimeUnit.HOURS.convert(diff, TimeUnit.MILLISECONDS);
            return hours;
        }
    

    测试用例:

    @Test
    public void checkFetchTimeDiff()
    {
        long expected = 500;
        Client client = new Client();
        Calendar ackCal = Calendar.getInstance();
        ackCal.add(Calendar.HOUR_OF_DAY, -500);
        long actual = client.dataFetchTotalTime(ackCal.getTime().getTime());
        Assert.assertEquals(expected, actual);
    }
    

    【讨论】:

      【解决方案2】:

      tl;博士

      ZonedDateTime now = ZonedDateTime.now( ZoneId.systemDefault() ) ;
      System.out.println(
          Duration
          .between(
              now , 
              now.plusHours( 500L ) 
          )
          .toHours()
      ) ;
      

      看到这个code run live at IdeOne.com

      500

      java.time

      您正在使用糟糕的日期时间类,这些类在几年前被 JSR 310 中定义的现代 java.time 类所取代。

      ZonedDateTime

      Calendar 类,实际上是它常用的子类GregorianCalendar,被ZonedDateTime 取代。 ZonedDateTime 类代表特定地区人们使用的挂钟时间所看到的时刻。换句话说,一个日期,一个时间,在一个时区的上下文中。

      您可以根据需要进行转换,但最好完全避免使用旧的日期时间类。要进行转换,请调用添加到旧类的新方法。

      GregorianCalendar gc = ( GregorianCalendar ) myJavaUtilCalendar  ;  // Cast from the more general to the concrete.
      ZonedDateTime zdt = gc.toZonedDateTime() ;  // Convert from legacy class to modern class.
      

      要捕捉当前时刻,请指定您想要的时区。对于任何给定的时刻,日期在全球各地都因地区而异。

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

      Duration

      算一算吧。将未附加到时间线的时间跨度表示为以小时-分钟-秒为单位的 Duration,或以年-月-日为单位的 Period

      Duration d = Duration.ofHours( 500 ) ;
      ZonedDateTime zdtLater = zdt.plus( d ) ; 
      

      要确定经过的时间,请使用Duration.between

      Duration elapsed = Duration.between( zdt , zdtLater ) ;
      

      要以标准 ISO 8601 格式查看文本,请致电 toString

      String output = elapsed.toString() ;
      

      要查看总小时数的经过时间,请致电Duration::toHours

      long hours = elapsed.toHours() ;
      


      关于java.time

      java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

      要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

      Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

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

      从哪里获得 java.time 类?

      ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

      【讨论】:

        猜你喜欢
        • 2012-12-25
        • 2011-05-27
        • 1970-01-01
        • 2017-09-10
        • 2019-02-02
        • 1970-01-01
        • 1970-01-01
        • 2021-03-16
        相关资源
        最近更新 更多