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.