3

我的目标是创建一个可以处理以下两个要求的 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 位数字,它将重新计算以秒为单位的值,并且 dateformat 将被更新,新的 dateformat 将具有 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中是否有任何强大的解决方案,即使预期格式发生变化,它也可以自给自足。

4

3 回答 3

0

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

于 2014-03-13T17:42:24.583 回答
0

Ajava.sql.Timestamp不会帮助你,因为那一个java.util.Date.

代码相当简单,如果您使用正确的格式 String with 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()andDate.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
于 2013-09-16T13:45:32.363 回答
0

Java 8 中的 java.time

JSR 310Java 8中定义了一个新的java.time 包。它的日期时间类解析为纳秒。这会给你小数点后的 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库也是如此,毫秒精度。

所以小数秒内没有足够的数字来满足您的需求。

于 2014-03-13T19:22:54.117 回答