Joda-Time 库指定 mili 秒精度

Posted

技术标签:

【中文标题】Joda-Time 库指定 mili 秒精度【英文标题】:Joda-Time Library Specifying mili second precision 【发布时间】:2021-11-11 10:56:36 【问题描述】:

我正在使用这段代码片段将日期和时间字符串转换为 Joda DateTime 对象 -

String time = "124204";
String date = "05/09/25";
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/mm/yyhhmmss").withZone(DateTimeZone.UTC);
String dateInString = date.concat(time);
DateTime dateTime = DateTime.parse(dateInString, formatter);
System.out.println(dateTime);

我得到的输出是 - 2025-01-05T00:42:04.000Z

但我希望它为 - 2025-01-05T00:42:04.000000Z

我希望 mili 秒精度为 6 位。

我该怎么做?感谢您的帮助。

【问题讨论】:

您使用 Joda Time 有什么原因吗?尽管它比使用 DateCalendarSimpleDateFormat 更好,但您确实应该使用 java.time 中提供的更新的 Java 日期和时间 API。 毫秒精度不能是六位数,毫秒按定义是三位数。您似乎想要的是微秒精度。但是,您似乎将toString() 的输出与某些所需的渲染混淆了。如果您想要 dateTime 的不同呈现方式,则需要使用适当的格式化程序。 请注意,格式模式字母区分大小写。请再次检查您是否需要mmMMhhHH 【参考方案1】:

你很困惑。

你似乎认为你有一个字符串。你没有;你有一个DateTime 类型的对象。您所看到的是在其中一个对象上调用 toString() 的结果,并且与 all toString() 方法一样,这只是一个调试辅助工具。它是为了你的开发者的眼球,绝对没有其他用途(如果你将它用于其他用途,请停止这样做)。

如果您希望以某种特定格式输出,则创建第二个 DateTimeFormat 对象并使用它。您正在使用第一个将字符串转换为日期时间对象(parse 方法)。这些格式化程序对象是双向的;他们还可以使用format 方法将日期时间对象转换回字符串。去做。制作你想要的图案,在上面调用.format 并将你拥有的dateTime 对象交给它。

注意:您为什么使用 jodatime?它已被 java.time 包淘汰,该包由与 jodatime 相同的作者编写。

【讨论】:

【参考方案2】:

只要您至少使用 Java 8,请使用 java.time:

    String time = "124204";
    String date = "05/09/25";
    DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd/MM/yyHHmmss").withZone(ZoneId.of("UTC"));
    String dateInString = date.concat(time);
    ZonedDateTime dateTime = ZonedDateTime.parse(dateInString, parser);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSX");
    System.out.println(dateTime.format(formatter));

这将打印 2025-09-05T12:42:04.000000Z。不确定您是否真的打算在输入中使用 12 小时格式,而且我没有这方面的经验,所以我忽略了这一点。

【讨论】:

【参考方案3】:

Joda-Time 解决方案(过时)

您的结果中的秒数可能不需要这 6 位小数。你可能想再次考虑这个问题。您要求的格式是 ISO 8601。ISO 8601 格式不规定小数位数,而是让交换数据的各方商定。大多数实现都接受不同数量的小数(有一定的限制,但在我遇到的情况下提供少于限制的小数是没有问题的)。

其他是正确的,您可以考虑升级到 java.time,它是 Joda-Time 的继任者。如果你现在不能这样做,这里有一种使用 Joda-Time 获取你想要的字符串的方法。

    String time = "124204";
    String date = "05/09/25";

    DateTimeFormatter timeFormatter = DateTimeFormat.forPattern("HHmmss");
    DateTimeFormatter dateFormatter = DateTimeFormat.forPattern("dd/MM/yy");

    LocalTime lt = LocalTime.parse(time, timeFormatter);
    LocalDate ld = LocalDate.parse(date, dateFormatter);
    
    DateTime dateTime = ld.toLocalDateTime(lt).toDateTime(DateTimeZone.UTC);
    
    DateTimeFormatter resultFormatter
            = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZ");
    
    String dateTimeString = dateTime.toString(resultFormatter);
    
    System.out.println(dateTimeString); 

输出:

2025-09-05T12:42:04.000000+00:00

我注意到您要求2025-01-05T00:42:04.000000Z。也许您没有注意到时间字符串中的小时是12(不是00),而日期字符串中的月份是09(不是01)。在您自己的代码中,您的小时和月份不正确,因为您在格式模式中始终使用小写模式字母。我们需要大写 HH 代表一天中的小时和大写 MM 代表月份。

编辑:您还希望 Z 而不是 +00:00 来表示 UTC(与 UTC 的偏移量为零),就像您从无参数 DateTime.toString() 得到的一样。 ISO 8601 再次允许两者,所以这可能无关紧要。不过,我很惊讶,没有找到简单的方法来获取Z。以下格式化程序给出了它,但我可能会遗漏一些更简单的东西。

    DateTimeFormatter resultFormatter = new DateTimeFormatterBuilder()
            .append(ISODateTimeFormat.dateHourMinuteSecond())
            .appendPattern(".SSSSSS")
            .appendTimeZoneOffset("Z", true, 2, 2)
            .toFormatter();

2025-09-05T12:42:04.000000Z

我还使用了不同的解析方法。虽然连接两个字符串并解析结果有效,但我发现单独解析每个字符串更清晰。

正如其他人所说,当您要求特定格式时,例如秒的特定小数位数,您只能在字符串中使用该格式。因此,解决方案是将您的DateTime 格式化为字符串。

用法:一毫秒是千分之一秒。所以要求 6 位毫秒是没有意义的,也不会给你更高的精度。我把你的问题理解为秒的小数点后 6 位——也称为微秒(百万分之一秒)。

链接

Wikipedia article: ISO 8601 可能类似的问题:Scala / Joda - Joda DateTimeFormat not applying

【讨论】:

以上是关于Joda-Time 库指定 mili 秒精度的主要内容,如果未能解决你的问题,请参考以下文章

MySQL DATETIME 精度(joda-time、Hibernate、org.jadira.usertype、hbm2ddl)

使用joda-time工具类 计算时间相差多少 天,小时,分钟,秒

使用joda-time工具类 计算时间相差多少 天,小时,分钟,秒

sleep() 超过 1000 milis 永远阻塞线程 - android

Joda-Time开源库

Joda-Time 中两个日期之间的天数