簡體   English   中英

java時間差輸出負值和錯誤值

[英]java Time difference outputs negative value and wrong values

我試過下面的代碼。 java 時間差在開始時間和結束時間之間存在小時/日期差異時輸出負值和錯誤值

    Date d3 = null;
    Date d4 = null;
    List<String> activeTimeList = new ArrayList();
    int c = Integer.parseInt(cycle.get("Cycle No:").toString());
    try {
        for(int i = 0; i<c;i++) {
            SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy HH:mm", Locale.US); //("MM/dd/yyyy HH:mm:ss");
            format.setTimeZone(TimeZone.getTimeZone("GMT"));
            String cycleEndTm = cycle.get("End Time"+i+"").toString().trim();
            String cycleStartTm = cycle.get("Start Time"+i+"").toString().trim();

            d3 = format.parse(cycleEndTm);
            d4 = format.parse(cycleStartTm);
            long diff =  d3.getTime() - d4.getTime();
            long diffSeconds = diff / 1000 % 60;
            long diffMinutes = diff / (60 * 1000) % 60;
            long diffHours = diff / (60 * 60 * 1000) % 24;
            long diffDays = diff / (24 * 60 * 60 * 1000);
            String time1 = diffDays+"."+diffHours+"."+diffMinutes+"."+diffSeconds;

Log :
0.-10.-7.0

d4 =02-11-2017 16:47
d3 =02-11-2017 17:27 Diff = 0.-10.-7.0 無法獲得正確的時差? 我在這里缺少什么? 注意**:cycleEndTm -cycleStarttime 應該給出積極的結果。 我正在從地圖讀取 cycleEndTime 和開始時間。 這就是要求。

tl;博士

使用現代java.time類,不要使用Date 將任何Date轉換為java.time.Instant

Duration                              // Represent a span-of-time as 24-hour days, hours, minutes, seconds, and nanoseconds.
.between(                             // Calculate elapsed time.
    javaUtilDateStart.toInstant() ,   // Convert any `java.util.Date` to `java.time.Instant`. Never use `Date`; it is a terrible class, ditto for `Calendar`. 
    javaUtilDateStop.toInstant()
)                                      // Returns a `Duration` object.
.toString()                            // Generate text in standard ISO 8601 format.

或者調用to…Part方法來提取天數、小時數等。

時間

您正在使用多年前被java.time類取代的糟糕的舊日期時間類( DateCalendarSimpleDateFormat )。

Instant

顯然你得到了一個java.util.Date對象。 如果可能,請重寫該代碼以使用其替代對象java.time.Instant對象。 兩者都代表 UTC 中的一個時刻,但Instant具有更精細的納秒分辨率而不是毫秒。 如果不可能,請立即將Date轉換為Instant 調用添加到舊類的新轉換方法。

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy class to modern class. Same moment in UTC, same point on the timeline.

以標准ISO 8601格式生成表示該時刻的文本。

以 UTC 格式捕獲當前時刻。

Instant now = Instant.now() ;  // Capture the current moment in UTC.

Duration

將經過時間計算為Duration對象。 同樣,這具有納秒的分辨率。

Duration d = Duration.between( instant , now ) ;

以標准ISO 8601格式生成表示經過時間的文本。

String output = d.toString() ; 

或者創建您的字符串,將“天”定義為 24 小時的時間塊,而不考慮日歷。

long days = d.toDaysPart() ;
int hours = d.toHoursPart() ;
int minutes = d.toMinutesPart() ;
int seconds = d.toSecondsPart() ;

String output = days + "." + hours + "." + minutes + "." + seconds ;

解析字符串

您的問題不清楚您的輸入。 如果以字符串開頭,則解析。 首先,如果可能,更改這些字符串的來源以使用明智定義的ISO 8601標准格式。 如果不可能,請定義格式模式以匹配輸入。

String inputStart = "02-10-2018 10.30";

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu HH.mm" );

將您的輸入解析為LocalDateTime因為它缺少時區或UTC 偏移量的任何指示符。

LocalDateTime ldtStart = LocalDateTime.parse( inputStart , f ) ;

一個LocalDateTime不是一時,並不代表時間軸上的一個點。 這個類代表了大約 26-27 小時范圍內的潛在時刻,這是全球時區的范圍。

分配該字符串源預期的區域或偏移量,以提供確定時刻所需的上下文。

continent/region的格式指定正確的時區名稱,例如America/MontrealAfrica/CasablancaPacific/Auckland 永遠不要使用ESTIST等 2-4 個字母的縮寫,因為它們不是真正的時區,不是標准化的,甚至不是唯一的(!)。

// Transform the indefinite `LocalDateTime` to a definite moment by assigning the time zone intended by that input string.
ZoneId z = ZoneId.of( "Africa/Tunis" );
ZonedDateTime zdtStart = ldtStart.atZone( z );

計算您過去的時間跨度。

Duration d = Duration.between( zdtStart , zdtStop ) ;

關於java.time

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

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

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

您可以直接與您的數據庫交換java.time對象。 使用符合JDBC 4.2或更高版本的JDBC 驅動程序 不需要字符串,不需要java.sql.*類。

從哪里獲得 java.time 類?

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

時間

這個答案並沒有解決你問的問題。 無論如何,我建議使用 java.time,現代 Java 日期和時間 API。 這里的第一個版本至少需要Java 9 Java 6、7 和 8 緊隨其后。

    Map<String, Object> cycle = Map.of("Cycle No:", 1, 
            "Start Time0", "02-11-2017 16:47",
            "End Time0", "02-11-2017 17:27");

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm", Locale.US);
    List<String> activeTimeList = new ArrayList<>();
    int c = Integer.parseInt(cycle.get("Cycle No:").toString());
    try {
        for(int i = 0; i < c; i++) {
            String cycleEndTm = cycle.get("End Time" + i).toString().trim();
            String cycleStartTm = cycle.get("Start Time" + i).toString().trim();

            LocalDateTime d4 = LocalDateTime.parse(cycleStartTm, formatter);
            LocalDateTime d3 = LocalDateTime.parse(cycleEndTm, formatter);

            Duration diff = Duration.between(d4, d3);
            String time1 = String.format(Locale.US, "%d.%d.%d.%d", 
                    diff.toDays(), diff.toHoursPart(), 
                    diff.toMinutesPart(), diff.toSecondsPart());

            activeTimeList.add(time1);
        }
        System.out.println(activeTimeList);
    } catch (DateTimeParseException dtpe) {
        System.err.println(dtpe);
    }

這打印:

[0.0.40.0]

我用於格式化的Duration類的toXxxPart方法不在Java 8 中 因此,如果您使用的是 Java 8,則可以通過以下方式進行格式化:

            long days = diff.toDays();
            diff = diff.minusDays(days);
            long hours = diff.toHours();
            diff = diff.minusHours(hours);
            long minutes = diff.toMinutes();
            diff = diff.minusMinutes(minutes);
            long seconds = diff.getSeconds();
            String time1 = String.format(Locale.US, "%d.%d.%d.%d", 
                    days, hours, minutes, seconds);

輸出與之前相同。

如果有人在使用Java 6 或 7 ,請獲取ThreeTen Backport 庫,Java 8 代碼也應該在那里工作。

你的代碼出了什么問題?

您發布的代碼中的唯一問題是您使用的是過時且設計不佳的日期和時間類DateSimpleDateFormatTimeZone 您的代碼中沒有任何內容解釋您是如何出錯的,負值,所以我懷疑您沒有解析您認為正在解析的字符串。

您可以使用java.time.Duration ,它以ISO-8601 標准為模型,並作為JSR-310 實現的一部分與Java-8一起引入。 Java-9引入了一些更方便的方法。

演示:

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String d4 = "02-11-2017 16:47";
        String d3 = "02-11-2017 17:27";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm", Locale.ENGLISH);

        // The given date-times in UTC
        OffsetDateTime odtD4 = LocalDateTime.parse(d4, dtf).atOffset(ZoneOffset.UTC);
        OffsetDateTime odtD3 = LocalDateTime.parse(d3, dtf).atOffset(ZoneOffset.UTC);

        // Duration between the date-times in UTC
        Duration duration = Duration.between(odtD4, odtD3);
        System.out.println(duration);    
        
        // Custom format
        // ####################################Java-8####################################
        String formattedDuration = String.format("%02d.%02d.%02d.%02d", duration.toDays(), duration.toHours() % 24,
                duration.toMinutes() % 60, duration.toSeconds() % 60);
        System.out.println(formattedDuration);
        // ##############################################################################

        // ####################################Java-9####################################
        formattedDuration = String.format("%02d.%02d.%02d.%02d", duration.toDaysPart(), duration.toHoursPart(),
                duration.toMinutesPart(), duration.toSecondsPart());
        System.out.println(formattedDuration);
        // ##############################################################################
    }
}

輸出:

PT40M
00.00.40.00
00.00.40.00

Trail: Date Time了解現代日期時間 API。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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