【问题标题】:Java : Custom Timestamp Format : verify format to microsec precisionJava:自定义时间戳格式:验证格式到微秒精度
【发布时间】:2013-09-20 03:19:48
【问题描述】:

我的目标是 创建一个可以处理以下两个要求的java类

(A) 1. 验证时间戳的格式是否与预期格式匹配。
CCYY-MM-DD'T'hh:mm:ss'.0000000000+'uh:um"
例如:预期的格式不是静态的。

可能是其中任何一个 “2013-09-10T18:30:20.123456+10:00”或 “2013-09-10T18:30:20.123+10:00”。
我不介意 精度和价值。只有格式很重要。

(B) 2.验证时间戳是否在一定范围内。
例如:验证时间戳是否在 在“2013-09-10 18:27”和“2013-09-10 18:33”之间。 (验证仅达到分钟级精度)(可能是 + 或 - 2 分钟的增量)


根据其中一位成员的建议,我已编辑帖子以定位于 一个具体问题。

问题:

如何使用 JAVA 类验证自定义时间戳达到微秒精度?

这个类的两个参数是

1) 预期格式为字符串

2) 字符串形式的时间戳值

根据各种搜索结果的分析,以下是我的理解:

  1. Java(默认)不解析/格式化微秒级别的时间戳(我使用 SimpleDateFormat)
  2. 如果以毫秒为单位给出 6 位数字,它将重新计算以秒为单位的值,并且日期格式将被更新,新的日期格式将具有 3 位毫秒精度。
  3. 我还看到了一个建议使用 java.sql.Timestamp 的线程。

尝试了这种方法,但没有奏效。 我无法将我的 strTimestamp 2013-09-10T18:30:20.123456+10:00 转换为 Timestamp 对象。

Timestamp ts = Timestamp.valueOf(strTimestamp); 
java.lang.IllegalArgumentException: 
 Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]

我无法将输入格式转换为 Timestamp 对象。


我有一个使用正则表达式验证的解决方法:

2013-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9]).[0-9][0-9][0-9][0-9][0-9][0-9]\+10:00

这个 reg ex 的问题在于,我预期的时间戳格式不是静态的。所以我必须为每个模式使用一个正则表达式。

所以我想弄清楚 java 中是否有任何强大的解决方案,即使预期格式发生变化,它也可以自给自足。

【问题讨论】:

  • 将问题中的问题数量限制为一个。如有必要,请提出单独的问题。
  • 我编辑了帖子以针对一个特定问题...

标签: java timestamp


【解决方案1】:

Java 8 中的 java.time

JSR 310Java 8 中定义了一个新的java.time package。它的日期时间类解析为纳秒。这会给你小数点后 9 位数字。

java.time 包的灵感来自Joda-Time,但完全重新架构。概念类似。

与 Joda-Time 一样,java.time 包使用 ISO 8601 格式作为其解析和格式化的默认值。所以可以输入或输出2013-09-10T18:30:20.123456789+10:00等字符串。

Java 8 的早期版本现已推出。本月正式发布。

将这个包反向移植到 Java 早期版本的项目正在进行中。我不知道它的当前状态或成功。 backport 项目独立于 Oracle 和 OpenJDK 项目。

毫秒

旧的捆绑类 java.util.Date 和 .Calendar 使用毫秒精度。

优秀的Joda-Time 库也是如此,毫秒精度。

因此,小数秒中的数字不足以满足您的需求。

【讨论】:

    【解决方案2】:

    真的,我也在努力寻找这个问题的答案。因为我无法对波西米亚的答案添加评论。我想提一下,SimpleDateFormat 中的“S”模式不是用于微秒,而是用于毫秒。这意味着对于模式“yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ”,字符串中提供的微秒数字将被解析为毫秒。 因此,前三位数字将作为 XXX 秒传递,并且它们的值将被添加到日期。所以我们可以在 16 分钟左右收到错误。

    【讨论】:

      【解决方案3】:

      java.sql.Timestamp 不会帮你,因为 java.util.Date

      代码相当简单,如果您使用带有SimpleDateFormat 的正确格式字符串,那么您就可以让它完成繁重的工作。这是一个完整的工作解决方案:

      public static boolean isNear(String timestamp, int microPlaces, Date near, int minutes) {
          if (!timestamp.matches(".*\\.\\d{" + microPlaces + "}\\D.*") {
              return false;
          }
          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ");
          try {
              Date date = sdf.parse(timestamp.replaceAll(":(?=\\d\\d$)", ""));
              return Math.abs(date.getTime() - near.getTime()) <= minutes * 60000;
          } catch (ParseException ignore) {
              return false; // string was not of correct format
          }
      }
      

      这可能与您的想法不完全相同 - 如果不是,您应该能够将其用作您想要的基础。重点是:

      • S 格式字符串表示“微秒”,它不需要所有位数字 - 所以您的时间戳可以是任意数字
      • Java 6 需要从时区中删除冒号。 Java 7 不需要这个 - 使用 X 格式字符串而不是 Z
      • 无法从输入中解析日期会引发ParseException - 使用此事件做你想做的事
      • 我选择让 API 提供范围的中心日期和 +/- 分钟值。您可能需要传递两个日期 - 由您决定。如果您这样做,请使用Date.before()Date.after() 进行比较。

      这里有一些测试代码测试您的示例和几个边缘案例:

      public static void main(String[] args) throws Exception {
          Date near = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm").parse("2013-09-10T18:32");
          System.out.println(isNear("2013-09-10T18:30:20.123456+10:00", near, 2));
          System.out.println(isNear("2013-09-10T18:30:20.123+10:00", near, 2));
          System.out.println(isNear("2013-09-10T18:10:20.123+10:00", near, 1));
          System.out.println(isNear("XXXX-09-10T18:10:20.123+10:00", near, 1));
      }
      

      输出:

      true
      true
      false
      false
      

      【讨论】:

      • 要求验证实际时间戳格式是否与预期的时间戳格式匹配到微秒精度。正如您所提到的,上面的代码不需要以微秒为单位的所有数字,并且时间戳可以有任何数字。因此,此代码不处理要求。当预期时间戳有 6 位数字时,该类应强制要求所有 6 位数字。如果不返回错误/异常。当预期的时间戳有 3 位数字时,该类应该只要求 3 位数字。如果不返回错误/异常。
      • 如前所述,我已经有了解决方法。使用 SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ"); 解析以检查有效日期由于这实际上并没有在微秒内验证所有数字,因此我可以对字符串进行长度检查以确认没有数字。但我觉得这一切都是一种古怪的做事方式。我正在寻找让 Java 做到这一点的简单直接的解决方案。我正在使用 Java 6。
      • 所以你想检查是否只有 3 位或 6 位微秒?即如果不是 3 或 6 则返回 false?
      • Expected format are either of these :2013-09-17T10:31:30.123+10:00 or2013-09-17T10:31:30.123456+10:00 or2013-09-17T10:31:30.123456789+10:00the expected format will be passed as argument to class. It should match the exact format.
      • 上面有三个(3/6/9)。并且只有这三种格式是预期的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-14
      相关资源
      最近更新 更多