簡體   English   中英

SimpleDateFormat 返回錯誤的天數

[英]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

在 IdeOne.com 中查看實時代碼

在 Java 9 及更高版本中,您可以通過調用to…Part方法(例如toDaysParttoHoursPart等)來訪問該值的每個組件。


關於 java.time

java.time框架內置於 Java 8 及更高版本中。 這些類取代麻煩的老傳統日期時間類,如java.util.DateCalendar ,和SimpleDateFormat

現在處於維護模式Joda-Time項目建議遷移到java.time類。

要了解更多信息,請參閱Oracle 教程 並在 Stack Overflow 上搜索許多示例和解釋。 規范是JSR 310

從哪里獲得 java.time 類?

ThreeTen-Extra項目用額外的類擴展了 java.time。 該項目是未來可能添加到 java.time 的試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

改變你的時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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM