本文介紹了SimpleDateFormat使用&Quot;S";格式顯示不正確的毫秒,但使用&Quot;SSS&Quot;格式不顯示錯誤的毫秒的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我遇到顯示日期的毫秒分量乘以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中重現。
推薦答案
舊的日期-時間接口(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
描述為:。換句話說,它將其表示為小數點后9位(納秒)的0.05的數學浮點數。
您可以這樣理解:在String.valueOf(0.05)
的右側填零,以將精度調到小數點后9位。因此,它變成"0.050000000"
。現在,根據S
的編號,得到"0.050000000"
的子字符串。請注意,您最多只能在9個位置執行此操作,即SSSSSSSSSS
將引發異常。
S
:.0
SS
:0.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,它將大部分java.time功能移植到Java 6&;7。如果您正在為Android項目工作,而您的Android API級別仍然不符合Java-8,請勾選Java 8+ APIs available through desugaring和How to use ThreeTenABP in Android Project。從Trail: Date Time了解有關現代日期-時間API的更多信息。
這篇關于SimpleDateFormat使用&Quot;S";格式顯示不正確的毫秒,但使用&Quot;SSS&Quot;格式不顯示錯誤的毫秒的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,