本文介紹了SimpleDateFormat使用&Quot;S";格式顯示不正確的毫秒,但使用&Quot;SSS&Quot;格式不顯示錯(cuò)誤的毫秒的處理方法,對(duì)大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!
問題描述
我遇到顯示日期的毫秒分量乘以10的問題。
具體而言,52.050
在使用.S
格式時(shí)顯示為52.50
,但在使用.SSS
格式時(shí)顯示為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));
});
這將產(chǎn)生以下輸出:
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
我已經(jīng)使用java.util.Date
和java.time
來說明意外行為,我知道java.time
更好,但我仍然希望了解SimpleDateFormat
行為。
我運(yùn)行的是Java 14.0.2.12,但可以在11.0.10.9中重現(xiàn)。
推薦答案
舊的日期-時(shí)間接口(java.util
日期-時(shí)間類型及其格式類型,SimpleDateFormat
)過時(shí)且容易出錯(cuò)。建議完全停止使用,切換到java.time
、modern date-time API*。
讓我們了解SimpleDateFormat
產(chǎn)生的結(jié)果是如何令人困惑的(因此容易出錯(cuò))。
1620946852050毫秒=1620946852000毫秒+50毫秒
對(duì)于1620946852000,System.out.println(localDateTime)
將生成結(jié)果2021-05-14T00:00:52
。
50毫秒=(50/1000)秒=0.05秒。DateTimeFormatter
也是這樣呈現(xiàn)的。documentation清楚地將S
描述為:。換句話說,它將其表示為小數(shù)點(diǎn)后9位(納秒)的0.05的數(shù)學(xué)浮點(diǎn)數(shù)。
您可以這樣理解:在String.valueOf(0.05)
的右側(cè)填零,以將精度調(diào)到小數(shù)點(diǎn)后9位。因此,它變成"0.050000000"
。現(xiàn)在,根據(jù)S
的編號(hào),得到"0.050000000"
的子字符串。請(qǐng)注意,您最多只能在9個(gè)位置執(zhí)行此操作,即SSSSSSSSSS
將引發(fā)異常。
S
:.0
SS
:0.05
SSS
:.050
SSSS
:.0500以此類推
SSSSSSSSS
:.050000000
這是我們小時(shí)候?qū)W數(shù)學(xué)分?jǐn)?shù)時(shí)學(xué)到的表示法。
另一方面,SimpleDateFormat
沒有將其表示為秒的分?jǐn)?shù);相反,它將.
之后的數(shù)字表示為毫秒數(shù)。documentation將S
描述為:毫秒。因此,它將其表示為一個(gè)數(shù)學(xué)十進(jìn)制整數(shù)50。這讓人感到困惑,因?yàn)槲覀円豢吹?code>.,我們就會(huì)想到分?jǐn)?shù),而SimpleDateFormat
則認(rèn)為它只是幾秒和幾毫秒的分隔符。
以下示例說明了這些不同的表示方式:
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
*出于任何原因,如果您必須堅(jiān)持使用Java 6或Java 7,您可以使用ThreeTen-Backport,它將大部分java.time功能移植到Java 6&;7。如果您正在為Android項(xiàng)目工作,而您的Android API級(jí)別仍然不符合Java-8,請(qǐng)勾選Java 8+ APIs available through desugaring和How to use ThreeTenABP in Android Project。從Trail: Date Time了解有關(guān)現(xiàn)代日期-時(shí)間API的更多信息。
這篇關(guān)于SimpleDateFormat使用&Quot;S";格式顯示不正確的毫秒,但使用&Quot;SSS&Quot;格式不顯示錯(cuò)誤的毫秒的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,