[英]SimpleDateFormat returns wrong number of days
我需要從 long 值中獲取天數、小時數、分鍾數、秒數。 但是我從以下代碼中得到錯誤的天數。
public static String formatTimeUTC(long value, String pattern) {
final SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date(value);
String formatString = format.format(date);
return formatString;
}
當我將106988550
和"dd:HH:mm:ss"
傳遞給這個方法時,我得到了"02:05:43:08"
預期的實際答案是: "01:05:43:08" 。
我不知道哪里錯了,也不知道我如何才能得到實際的答案。
表達式System.out.println(formatTimeUTC(106988550L, "dd:HH:mm:ss"));
確實預計會多打印一天 (02:05:43:08)。 為什么?
抽象的:
SimpleDateFormat
類不是用來打印持續時間而是用來打印時間點的。 對於舊類型java.util.Date
也可以這樣說,它不是持續時間而是瞬間。
具體的:
模式部分“dd”指示格式化程序打印名義日期,而不是自 UNIX 紀元以來的天數。 在這種情況下,它是日歷日期的一部分1970-01- 02 T05:43:08.550。 因此,您需要從 UNIX 時代的原始日期 1 中減去一天。
如您所見,以這種方式打印持續時間非常尷尬(誤用了不是為此目的而設計的類SimpleDateFormat
)。 我建議使用更好的 API。 例如Joda-Time或我的圖書館Time4J :
Joda-Time(基於builder-approach ):
PeriodFormatter pf =
new PeriodFormatterBuilder().minimumPrintedDigits(2).appendDays().appendLiteral(":")
.appendHours().appendLiteral(":").appendMinutes().appendLiteral(":").appendSeconds()
.toFormatter();
long v = 106988550L;
System.out.println(
pf.print(new Period(v, PeriodType.dayTime()).normalizedStandard())); // 01:05:43:08
對於 Android:使用適配Joda-Time-Android 。
Time4J(基於模式方法):
long v = 106988550L;
Duration<IsoUnit> duration = Duration.of(v, ClockUnit.MILLIS);
System.out.println(
Duration.formatter("DD:hh:mm:ss").format(duration.with(Duration.STD_PERIOD))
); // 01:05:43:08
對於 Android:使用姊妹項目 Time4A。
您還可以調查Android 平台中內置的DateUtils類,盡管我不確定它是否適合您的目的,因為它的 API 很笨拙(無論如何您都需要設置位標志的組合)。
Hochschild的答案是正確的。 您將一段時間作為日期時間處理,喜歡將蘋果與橙子混合。
java.time 類取代了麻煩的舊日期時間類。 使這個工作變得容易。
你實際上沒有解釋,但我猜你的數字是經過的毫秒數。
long input = 106_988_550L ;
我們將其表示為Duration
。
Duration d = Duration.ofMillis( input );
我們可以將該值表示為使用標准ISO 8601格式的子集格式化的字符串,用於持續時間PTnHnMnS
。
String output = d.toString();
PT29H43M8.55S
在 Java 9 及更高版本中,您可以通過調用to…Part
方法(例如toDaysPart
、 toHoursPart
等)來訪問該值的每個組件。
java.time框架內置於 Java 8 及更高版本中。 這些類取代麻煩的老傳統日期時間類,如java.util.Date
, Calendar
,和SimpleDateFormat
。
現在處於維護模式的Joda-Time項目建議遷移到java.time類。
要了解更多信息,請參閱Oracle 教程。 並在 Stack Overflow 上搜索許多示例和解釋。 規范是JSR 310 。
從哪里獲得 java.time 類?
ThreeTen-Extra項目用額外的類擴展了 java.time。 該項目是未來可能添加到 java.time 的試驗場。 您可以在這里找到一些有用的類,比如Interval
, YearWeek
, YearQuarter
,和更多。
改變你的時TimeZone
這個
format.setTimeZone(TimeZone.getTimeZone("UTC"));
對此
format.setTimeZone(TimeZone.getTimeZone("GMT+0:00"));
並檢查輸出。
您可以使用java.time.Duration
,它以ISO-8601 標准為模型,作為JSR-310 實現的一部分隨Java-8一起引入。 Java-9引入了一些更方便的方法。
演示:
import java.time.Duration;
public class Main {
public static void main(String[] args) {
long value = 106988550;
Duration duration = Duration.ofMillis(value);
// Default format
System.out.println(duration);
// Custom format
// ####################################Java-8####################################
String formattedElapsedTime = String.format("%02d:%02d:%02d:%02d", duration.toDays(), duration.toHours() % 24,
duration.toMinutes() % 60, duration.toSeconds() % 60);
System.out.println(formattedElapsedTime);
// ##############################################################################
// ####################################Java-9####################################
formattedElapsedTime = String.format("%02d:%02d:%02d:%02d", duration.toDaysPart(), duration.toHoursPart(),
duration.toMinutesPart(), duration.toSecondsPart());
System.out.println(formattedElapsedTime);
// ##############################################################################
}
}
輸出:
PT29H43M8.55S
01:05:43:08
01:05:43:08
從Trail: Date Time了解現代日期時間 API。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.