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”时则不显示 的相关文章

  • 如何使用 Java 和 Selenium WebDriver 在 C 目录中创建文件夹并需要将屏幕截图保存在该目录中?

    目前正在与硒网络驱动程序和代码Java 我有一种情况 我需要在 C 目录中创建一个文件夹 并在该文件夹中创建我通过 selenium Web 驱动程序代码拍摄的屏幕截图 它需要存储在带有时间戳的文件夹中 如果我每天按计划运行脚本 所有屏幕截
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • Spring @RequestMapping 带有可选参数

    我的控制器在请求映射中存在可选参数的问题 请查看下面的控制器 GetMapping produces MediaType APPLICATION JSON VALUE public ResponseEntity
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 如何从日期中查找该月的最后一天?

    如何在 PHP 中获取该月的最后一天 Given a date 2009 11 23 我要2009 11 30 并给出 a date 2009 12 23 我要2009年12月31日 t返回给定日期所在月份的天数 请参阅的文档date ht

随机推荐

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

    如何在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