SimpleDateFormat 使用“S”格式显示不正确的毫秒,但使用“SSS”时则不显示

2023-12-03

我遇到一个问题,显示的日期的毫秒部分乘以 10。

具体来说,时间52.050显示为52.50 when a .S使用格式,但是52.050 when a .SSS使用格式。

采取以下代码示例:

// Some arbitrary point with 50 milliseconds
final Date date = new Date(1620946852050 l);
final LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

final String format = "%-40s%-20s%-20s%n";
System.out.format(format, "Date Formatter", "Date Format", "Formatted Output");

Stream.of("HH:mm:ss", "HH:mm:ss.S", "HH:mm:ss.SS", "HH:mm:ss.SSS").forEach(dateFormat - > {
    System.out.println();
    System.out.format(format, SimpleDateFormat.class.getName(), dateFormat,
        new SimpleDateFormat(dateFormat).format(date));
    System.out.format(format, DateTimeFormatter.class.getName(), dateFormat,
        DateTimeFormatter.ofPattern(dateFormat).format(localDateTime));
});

这会产生以下输出:

Date Formatter                          Date Format         Formatted Output    

java.text.SimpleDateFormat              HH:mm:ss            00:00:52            
java.time.format.DateTimeFormatter      HH:mm:ss            00:00:52            

java.text.SimpleDateFormat              HH:mm:ss.S          00:00:52.50         
java.time.format.DateTimeFormatter      HH:mm:ss.S          00:00:52.0          

java.text.SimpleDateFormat              HH:mm:ss.SS         00:00:52.50         
java.time.format.DateTimeFormatter      HH:mm:ss.SS         00:00:52.05         

java.text.SimpleDateFormat              HH:mm:ss.SSS        00:00:52.050        
java.time.format.DateTimeFormatter      HH:mm:ss.SSS        00:00:52.050        

我都用过java.util.Date and java.time来说明意外的行为,我知道java.time更好,但我仍然想了解SimpleDateFormat行为。

我正在运行 Java 14.0.2.12,但可以在 11.0.10.9 中重现。


The legacy date-time API (java.util date-time types and their formatting type, SimpleDateFormat) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time, the modern date-time API*.

让我们了解一下结果是如何产生的SimpleDateFormat令人困惑(因此容易出错)。

1620946852050 毫秒 = 1620946852000 毫秒 + 50 毫秒

1620946852000,System.out.println(localDateTime)将产生结果,2021-05-14T00:00:52.

50 毫秒 = (50 / 1000) 秒 = 0.05 秒。就是这样DateTimeFormatter也呈现它。这文档描述S明确为:几分之一秒。换句话说,它将其表示为 0.05 到小数点后 9 位(纳秒)的数学浮点数。

你可以这样理解:在右边补零String.valueOf(0.05)将精度提高到小数点后 9 位。这样,就变成了"0.050000000"。现在,根据数量S, 获取子串"0.050000000"。请注意,您最多只能在 9 个位置执行此操作,即SSSSSSSSSS会抛出异常。

  • S: .0
  • SS: .05
  • SSS: .050
  • SSSS: .0500 等最多
  • SSSSSSSSS: .050000000

这是我们小时候学习数学分数时学到的表示法。

另一方面,SimpleDateFormat不将其呈现为几分之一秒;相反,它呈现的是后面的数字.作为毫秒数。这文档描述S as: 毫秒。因此,它将它表示为一个数学十进制整数 50。这使得它令人困惑,因为一旦我们看到.,我们考虑分数,而SimpleDateFormat认为它只是秒和毫秒的分隔符。

以下示例说明了这些不同的表示方式:

public class Main {
    public static void main(String[] args) {
        int sdf = 50;
        String dtf = String.format("%.9f", 0.05);

        System.out.format("sdf: %01d, dtf: %s%n", sdf, dtf.substring(0, 3));// Including two places for "0."
        System.out.format("sdf: %02d, dtf: %s%n", sdf, dtf.substring(0, 4));// Including two places for "0."
        System.out.format("sdf: %03d, dtf: %s%n", sdf, dtf.substring(0, 5));// Including two places for "0."
        System.out.format("sdf: %04d, dtf: %s%n", sdf, dtf.substring(0, 6));// Including two places for "0."
    }
}

Output:

sdf: 50, dtf: 0.0
sdf: 50, dtf: 0.05
sdf: 050, dtf: 0.050
sdf: 0050, dtf: 0.0500

* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project. Learn more about the modern date-time API from Trail: Date Time.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SimpleDateFormat 使用“S”格式显示不正确的毫秒,但使用“SSS”时则不显示 的相关文章

随机推荐

  • 如何在乌龟中创建按钮?

    如何在turtle python中创建一个简单的按钮 如果单击它 您可以定义它来打印消息 或者做其他更复杂的事情 You can embed正如 JoshuaNixon 在他的评论中建议的那样 tkinter 中的海龟使用 tkinter
  • 微风过滤。在服务器端扩展

    我正在尝试BreezeJS 有一个要求我可以使用 expand在客户端代码中 但基于role对于该用户 服务器端不会返回该用户的所有记录 expand请求的类型 我尝试创建一个自定义BreezeQueryable属性并重写一个方法来完全过滤
  • PHP:如何发送HTTP响应代码?

    我有一个 PHP 脚本 需要使用 HTTP 响应代码 状态代码 进行响应 例如 HTTP 200 OK 或某些 4XX 或 5XX 代码 我怎样才能在 PHP 中做到这一点 我刚刚发现这个问题并认为它需要更全面的答案 As of PHP 5
  • 自动解决主键合并冲突

    你能建议我自动解决的方法吗 发布者和订阅者之间合并期间的主键冲突 看来 Sql Server 并没有开箱即用 冲突查看器向我显示下一条消息 在 publisher server 处插入的行无法传播到 subscriber server 此失
  • 使用 Hibernate 通过 SSH 隧道获取数据

    最近开始学习Hibernate技术 要使用Hibernate从数据库中获取数据 问题是我只能通过 SSH 隧道连接到数据库 有没有我可以使用的属性hibernate cfg xml文件来解决这个问题 或者您可以提出另一种新手可以理解的方法
  • 如何在Python中迭代列表时从列表中删除元素? [复制]

    这个问题在这里已经有答案了 给定一个数字列表 L 1 2 3 4 5 当我迭代它时 如何从列表中删除一个元素 假设是 3 我尝试了以下代码 但没有成功 for el in L if el 3 del el 最好的做法通常是建设性地进行 建立
  • 处理超过 200 个复选框,将它们存储在状态中

    我有一个表 父元素 它获取用户并将每一行呈现为它自己的组件 表中的行包含复选框 目标是能够使用复选框并检索选中的复选框 问题是 当我将函数传递给每一行 子组件 时 触发将选中的复选框值添加到数组 由选定用户的 id 组成 中 整个组件会重新
  • 在共享库的类中调用 GSL 函数

    我正在尝试用 C 创建一个共享库来实现费米气体的工具 我正在使用 GSL 库以数值方式求解函数 并且我的代码在作为脚本运行时运行没有问题 但在尝试将其转换为共享库和类时遇到问题 我见过类似的问题 Q1 Q2 Q3 我对 C 编程相当陌生 似
  • 为什么要在CMake中的add_library/add_executable命令中添加头文件?

    我有一个项目 它使用 CMake 作为构建工具 并制作了一个简单的模板供我和我的同事使用 当我在线搜索最佳且易于使用的实践时 我遇到了创建库的不同方法 在此模板中 我在两个单独的变量中列出了头文件和源文件 并且我没有将标头传递给add li
  • R 中的限制命令?

    R 中的限制命令或函数是什么 我无法通过使用 和 函数搜索或在介绍性手册中找到它 lim 和 limit 不存在 这是在 F X 的极限 X gt Y 的意义上 我不是指任何人编写代码 我指的是任何人 我的意思是 作为安装标准包含在 R 中
  • android 标签图标不显示

    现在我正在尝试让选项卡布局正常工作 我已经完成了所有操作 就像 Android TabView 教程中一样 应用程序运行正常 但问题是我没有看到我在 ic tab artists xml 中定义的任何图标 只有文字 我想这与默认主题或样式或
  • 将 JDBC 与 SQL Server 连接

    我正在尝试将我的 JAVA 代码连接到我本地的 SQL Server 这就是我想要的 public static void main String args throws ClassNotFoundException SQLExceptio
  • 类名中的正则表达式用于识别控件

    某个程序的控件ClassnameNN被识别为AutoIt 窗口信息工具 as WindowsForms10 BUTTON app 0 24f4a7c r27 ad19在以前的版本中 在当前版本中它更改为 WindowsForms10 BUT
  • 安排每周将 Excel 文件下载到唯一的名称

    我们有一个数据库 每周一都会从客户端上传一个 Excel 文件 该文件始终具有相同的名称 因此如果我们忘记了它 就会丢失它 有没有办法制作一个脚本来重命名脚本并为其提供日期或数字 我们现在使用 FileZilla 来获取文件 文件齐拉不允许
  • 设置 pandas 数据框中时间戳数据的时区

    我有一个经常更改的 pandas 数据框 如下所示 date name time timezone 0 2016 08 01 aaa 0900 Asia Tokyo 1 2016 08 04 bbb 1200 Europe Berlin 2
  • Android 应用内结算:“RESULT_DEVELOPER_ERROR”

    我无法理解为什么我在 应用内计费 的实现中收到 RESULT DEVELOPER ERROR 我做了什么 将代码从示例应用程序复制到我的应用程序 android 清单包含 在 Android 4 0 4 和 Google Play 应用程序
  • 确定当前本地时间是否在两个时间之间(忽略日期部分)

    考虑到 Cocoa Touch 中没有 NSTime iPhone 上的 Objective C 并且以 NSString 形式给出两个时间 以 NSString 形式给出一个时区 如何计算当前 LOCAL 时间是否在这两个时间之间 请记住
  • 备份和恢复eMMC

    从 Google Coral 开发板的 SD 卡映像备份板载 eMMC 的过程是什么 同样 我们应该按照什么步骤将镜像恢复到板载的emmc驱动器上呢 从SD卡镜像备份板载eMMC Mendel OS 映像未安装在 SD 卡上 所以您的意思是
  • XAML:访问用户控件内的控件

    我有这样的用户控件
  • SimpleDateFormat 使用“S”格式显示不正确的毫秒,但使用“SSS”时则不显示

    我遇到一个问题 显示的日期的毫秒部分乘以 10 具体来说 时间52 050显示为52 50 when a S使用格式 但是52 050 when a SSS使用格式 采取以下代码示例 Some arbitrary point with 50