SimpleDateFormat 使用 "S" 格式显示不正确的毫秒数,但不使用 "SSS"
SimpleDateFormat showing incorrect milliseconds with "S" format, but not with "SSS"
我遇到了显示日期的毫秒分量乘以 10 的问题。
具体来说,时间 52.050
在使用 .S
格式时显示为 52.50
,但在使用 .SSS
格式时显示为 52.050
.
以下面的代码为例:
// 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
和 java.time
来说明意外行为,我知道 java.time
更好,但我仍然想了解SimpleDateFormat
行为。
我是 运行 Java 14.0.2.12,但可以在 11.0.10.9 中重现。
遗留日期时间 API(java.util
日期时间类型及其格式类型,SimpleDateFormat
)已过时且容易出错。建议完全停止使用,改用java.time
,modern date-time API*.
让我们了解一下 SimpleDateFormat
产生的结果是如何令人困惑(因此容易出错)。
1620946852050 毫秒 = 1620946852000 毫秒 + 50 毫秒
对于 1620946852000,System.out.println(localDateTime)
将产生结果,2021-05-14T00:00:52
。
50 毫秒 = (50 / 1000) 秒 = 0.05 秒。 DateTimeFormatter
也是这样介绍的。 documentation 将 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
不会将其显示为秒数;相反,它将 .
之后的数字显示为毫秒数。 documentation将S
描述为:毫秒。因此,它将它表示为 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."
}
}
输出:
sdf: 50, dtf: 0.0
sdf: 50, dtf: 0.05
sdf: 050, dtf: 0.050
sdf: 0050, dtf: 0.0500
* 无论出于何种原因,如果您必须坚持Java 6 或Java 7,您可以使用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 . Learn more about the modern date-time API from Trail: Date Time。
我遇到了显示日期的毫秒分量乘以 10 的问题。
具体来说,时间 52.050
在使用 .S
格式时显示为 52.50
,但在使用 .SSS
格式时显示为 52.050
.
以下面的代码为例:
// 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
和 java.time
来说明意外行为,我知道 java.time
更好,但我仍然想了解SimpleDateFormat
行为。
我是 运行 Java 14.0.2.12,但可以在 11.0.10.9 中重现。
遗留日期时间 API(java.util
日期时间类型及其格式类型,SimpleDateFormat
)已过时且容易出错。建议完全停止使用,改用java.time
,modern date-time API*.
让我们了解一下 SimpleDateFormat
产生的结果是如何令人困惑(因此容易出错)。
1620946852050 毫秒 = 1620946852000 毫秒 + 50 毫秒
对于 1620946852000,System.out.println(localDateTime)
将产生结果,2021-05-14T00:00:52
。
50 毫秒 = (50 / 1000) 秒 = 0.05 秒。 DateTimeFormatter
也是这样介绍的。 documentation 将 S
清楚地描述为:秒的分数。换句话说,它将它呈现为 0.05 到小数点后 9 位(纳秒)的数学浮点数。
可以这样理解:在String.valueOf(0.05)
右边补零,将精度提高到小数点后9位。因此,它变成了"0.050000000"
。现在,根据S
的个数,得到"0.050000000"
的子串。请注意,您最多只能在 9 个位置执行此操作,即 SSSSSSSSSS
将引发异常。
S
: .0SS
: .05SSS
: .050SSSS
: .0500 等等直到SSSSSSSSS
:.050000000
这是我们小时候学数学分数时学的表示法
另一方面,SimpleDateFormat
不会将其显示为秒数;相反,它将 .
之后的数字显示为毫秒数。 documentation将S
描述为:毫秒。因此,它将它表示为 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."
}
}
输出:
sdf: 50, dtf: 0.0
sdf: 50, dtf: 0.05
sdf: 050, dtf: 0.050
sdf: 0050, dtf: 0.0500
* 无论出于何种原因,如果您必须坚持Java 6 或Java 7,您可以使用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