【问题标题】:Is there a way to compare timestamps with different formats?有没有办法比较不同格式的时间戳?
【发布时间】:2020-01-07 21:00:01
【问题描述】:

我正在尝试比较来自数据库和 Web 服务的响应。

response from web services is : 2020-01-07T17:15:00-08:00
response from database is :     2020-01-08 01:15:00.0

如何将它们都转换为通用格式?

或者有没有办法使用子字符串来匹配比较?

【问题讨论】:

  • 请添加您尝试过的内容。
  • 我尝试使用 joda-date 时间格式化程序。但这没有用。

标签: java testing automation rest-assured timestamp-with-timezone


【解决方案1】:

这些字符串代表某些格式。比较它们相当于询问“这些格式是否相同”——它们不是,这不是你想要测试的(你想要测试:这些不同格式的字符串是否代表相同的时间? )。

那么,那就这样做吧。首先,将这些字符串(人类的东西)转换为实际的适当时间对象,然后比较 THOSE

您可以将这些字符串转换为 Instant,它代表时间点,大概是您在此处寻找的内容,然后将两者转换为瞬间后,您可以比较这两个瞬间。

p>

要将字符串转换为Instant,请使用DateTimeFormatter。更多信息:java time API

【讨论】:

    【解决方案2】:

    我们不知道。字符串不提供相同的信息,因此来自它们的信息不易比较。如果您知道第二个字符串中假定的时区,我们将每个时区转换为一个时间点并进行比较。

    前一个字符串更容易,因为除了日期和时间之外,它还通知我们与 UTC 的偏移量(时区偏移量)。所以有了这个字符串,我们可以识别一个时间点。此外,该字符串采用 ISO 8601 格式。 java.time 类,现代 Java 日期和时间 API,将 ISO 8601 格式(或其最常见的变体)解析为默认格式,即没有任何显式格式化程序。

        String responseFromWs = "2020-01-07T17:15:00-08:00";
        OffsetDateTime odtFromWs = OffsetDateTime.parse(responseFromWs);
        System.out.println(odtFromWs);
    

    到目前为止的输出是:

    2020-01-07T17:15-08:00
    

    它看起来很像输入(仅省略了00 秒)。这是因为OffsetDateTime 还打印回 ISO 8601 格式(根据该格式,秒数是可选的)。重要的是我们有一个日期时间对象,可以用于进一步处理,例如与其他日期时间对象进行比较。

    第二个字符串(来自数据库的字符串)的问题是我们不知道隐含的偏移量。常见的建议包括将日期和时间以 UTC 格式存储在数据库中,并且不要将其作为字符串从数据库中获取,而是作为适当的日期时间对象,例如我们之前使用的 OFfsetDateTime

    如果您知道字符串是 UTC 格式并且我们现在依赖该字符串:

        DateTimeFormatter dbFormatter = new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral(' ')
                .append(DateTimeFormatter.ISO_LOCAL_TIME)
                .toFormatter();
    
        String responseFromDatabase = "2020-01-08 01:15:00.0";
    
        OffsetDateTime odtFromDb = LocalDateTime
                .parse(responseFromDatabase, dbFormatter)
                .atOffset(ZoneOffset.UTC);
        System.out.println(odtFromDb);
    
    2020-01-08T01:15Z
    

    现在我们有两个OffsetDateTime 对象。他们有比较方法:

        System.out.println("Before: " + odtFromWs.isBefore(odtFromDb));
        System.out.println("After: " + odtFromWs.isAfter(odtFromDb));
        System.out.println("Same time: " + odtFromWs.isEqual(odtFromDb));
        System.out.println("Equal: " + odtFromWs.equals(odtFromDb));
    
    Before: false
    After: false
    Same time: true
    Equal: false
    

    isEqual() 返回 true 和 equals() false,您可能会感到惊讶。这是因为isEqual() 测试这两个对象是否表示相同的时间点,它们会这样做,而equals() 需要相同的时间点和相同的偏移量,才能产生真值。由于两个对象有不同的偏移量,在这种情况下它返回 false。

    您的 JDBC 驱动程序或 JPA 实现可能会很乐意从数据库中获取日期时间对象,而不是字符串,正如我所说的,建议这样做。详细信息取决于数据库中使用的数据类型,但您可以在我对不同问题的回答中阅读更多信息,请参阅底部的链接。

    链接

    【讨论】:

      【解决方案3】:

      您可以将时间戳转换为等效的日期格式。 Web 服务似乎是 ISO,因此您可以将数据库时间戳转换为 ISO,然后最终解析文本以生成日期,您可以使用该日期进行比较。

      例如:

      import java.time.LocalDateTime;
      import java.time.format.DateTimeFormatter;
      
      public class CompareTimeStamp {
      
          private String webServiceTS = ": 2020-01-07T17:15:00-08:00".replace(": ", "");
          private String dataBaseTS = ": 2020-01-08 01:15:00.0".replace(": ", "");
          private DateTimeFormatter isoFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
          private DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
      
          public static void main(String[] args) {
              CompareTimeStamp cts = new CompareTimeStamp();
              LocalDateTime webServiceTime = LocalDateTime.parse(cts.webServiceTS, cts.isoFormat);
              LocalDateTime dataBaseTime = LocalDateTime.parse(cts.dataBaseTS, cts.format);
              /** OPTION 1 -Remove below code if not choosing this option*/
              System.out.println("webServiceTime: " + webServiceTime);
              System.out.println("dataBaseTime: " + dataBaseTime);
              System.out.println(cts.compareTimeStamps(webServiceTime, dataBaseTime) + "\n");
              /*********************************************************************/
      
              /** OPTION 2 -Remove below code if not choosing this option*/
              String webServiceTS = cts.formatTimeStamp(webServiceTime);
              String dataBaseTS = cts.formatTimeStamp(dataBaseTime);
              System.out.println("webServiceTS: " + webServiceTS);
              System.out.println("dataBaseTS: " + dataBaseTS);
              System.out.println(cts.compareTimeStamps(webServiceTS, dataBaseTS));
              /*********************************************************************/
          }
      
          // OPTION 1 - Compares this LocalDateTime with another ensuring that the date-time is the same.
          private String compareTimeStamps(LocalDateTime webServiceTime, LocalDateTime dataBaseTime) {
              if (webServiceTime.equals(dataBaseTime)) {
                  return "Time stamp matches";
              } else {
                  return "Time stamp does not match";
              }
          }
      
          // OPTION 2 - Compares this string to the specified object.
          private String compareTimeStamps(String webServiceTS2, String dataBaseTS2) {
              if (webServiceTS2.equals(dataBaseTS2)) {
                  return "Time stamp matches";
              } else {
                  return "Time stamp does not match";
              }
          }
      
          private String formatTimeStamp(LocalDateTime timeStamp) {
              DateTimeFormatter formating = DateTimeFormatter.ofPattern("EEEE, MMM d, yyyy HH:mm:ss a");
              String localTimeStamp = formating.format(timeStamp);
              return localTimeStamp;
          }
      }
      

      输出:

      webServiceTime: 2020-01-07T17:15
      dataBaseTime: 2020-01-08T01:15
      Time stamp does not match
      
      webServiceTS: Tuesday, Jan 7, 2020 17:15:00 PM
      dataBaseTS: Wednesday, Jan 8, 2020 01:15:00 AM
      Time stamp does not match
      

      修改时间戳:

      ": 2020-01-07T17:15:00-08:00"
      ": 2020-01-07 17:15:00.0"
      

      输出:

      webServiceTime: 2020-01-07T17:15
      dataBaseTime: 2020-01-07T17:15
      Time stamp matches
      
      webServiceTS: Tuesday, Jan 7, 2020 17:15:00 PM
      dataBaseTS: Tuesday, Jan 7, 2020 17:15:00 PM
      Time stamp matches
      

      【讨论】:

      • 我得到了第一个输出。以后怎么修改?我猜使用.replace 函数不起作用。
      • @YadullahHaider 我已经更新了示例以提供两个可供选择的选项,请注意上面添加的 cmets。我同意 Ole V.V 并将 SimpleDateFormat 转换为较新的 DateTimeFormatter。您的评论“以后如何修改它?我猜使用.replace 函数不起作用。”您能否提供您所指的代码中的行?
      • 您的编辑是一个很好的改进,谢谢。我仍然显然更喜欢比较 LocalDateTime 或其他日期时间对象,而不是比较字符串。后者有点像String.valueOf(42).equals(String.valueOf(42)),也就是做额外的工作没有收获。此外,我会完全避免使用Timestamp 课程。它的设计很糟糕(一个真正的 hack。真的)并且已经过时了,再一次,转换为 Timestamp 并返回是在做额外的工作而没有任何收获。
      • @OleV.V.谢谢。我不知道时间戳。在重构我的代码时,我接受了您的建议将其删除。我仍然喜欢向 O.P 提供这两个选项并让他们决定。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      相关资源
      最近更新 更多