java时差输出负值和错误值

java Time difference outputs negative value and wrong values

我尝试了下面的代码。 java 开始时间和结束时间

相差hours/date 时,时间差输出负值和错误值
    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 差异 = 0.-10.-7.0 无法获得正确的时差?我在这里缺少什么? 注意 ** :cycleEndTm -cycleStarttime 应该给出肯定的结果。我正在从地图上读取 cycleEndTime 和开始时间。就是这个要求。

tl;博士

使用现代 java.time classes,从不使用 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

您正在使用可怕的旧日期时间 classes(DateCalendarSimpleDateFormat),这些日期时间在多年前被 取代java.timeclasses.

Instant

显然你被递给了一个 java.util.Date 对象。如果可能,重写该代码以使用它的替代品 java.time.Instant 对象。两者都代表 UTC 中的一个时刻,但 Instant 具有纳秒而不是毫秒的更精细分辨率。如果不可能,请立即将 Date 转换为 Instant。调用添加到旧 classes 的新转换方法。

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 ) ;

一个LocalDateTimenot一个时刻,not是否代表时间轴上的一个点。此 class 代表 潜在 时刻,时间跨度约为 26-27 小时,即全球时区范围。

分配该字符串的来源预期的区域或偏移量,以提供确定时刻所需的上下文。

指定 proper time zone name in the format of continent/region, such as America/Montreal, Africa/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 framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

java.time

该回答没有解决您所问的问题。无论如何,我建议使用 java.time,现代 Java 日期和时间 API。这里第一个版本需要至少Java9。 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]

我用来格式化的Durationclass的toXxxPart方法在Java8中没有。因此,如果您使用 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,请获取 the ThreeTen Backport library,并且 Java 8 代码也应该在那里工作.

你的代码出了什么问题?

您发布的代码中的唯一问题是您使用的日期和时间早已过时且设计不当 classes、DateSimpleDateFormatTimeZone。您的代码中没有任何内容可以解释您是如何出错的,负值,所以我怀疑您没有解析您认为正在解析的字符串。

您可以使用 java.time.Duration which is modelled on ISO-8601 standards and was introduced with Java-8 as part of JSR-310 implementationJava-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
  • 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它向后移植了大部分 java.time Java 6 和 7 的功能。
  • 如果您正在为 Android 项目工作,并且您的 Android API 水平仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring and