Java returns 比较两个时间时的错误时间对象

Java returns wrong Time object when comparing two Times

我今天在 java 创作了一个杰作,我需要计算两次之间的差异。

所以我用 Time.getTime() 得到时间的长值并减去它们得到我想要的...

这是我的测试代码:

public static void main(String[] args) {    
    Time time = new Time(00,00,00);
    Time time2 = new Time(02,00,00);
    long longTime = (time2.getTime() - time.getTime());
    Time finalTime = new Time(longTime);
    System.out.println(finalTime.toString());
}

现在显然打印出的字符串必须是02:00:00

但我总是得到 04:00:00

我试了很多时间,我总是把时间增加两个小时,我不知道为什么。

我什至尝试减去 00:00:00 和 00:00:00

而不是得到 00:00:00

我得到了02:00:00

那么,对我有什么帮助吗???

时间构造器 new Time(long) 使用您的时区。

所以你的 longTime 如你所料是 60*60*2*1000=7200000。

但是 new Time(7200000) 需要 1. January 1970 00:00:00 UTC/GMT + 7200000 因为它是新日期,所以它会按您所在的时区移动。 对我来说,您的代码打印:03:00:00。 new Time(int, int, int) 已弃用,不应使用。

因此,如果可能的话,我建议不要使用旧的日期和时间,而是使用 jodatime 或 java8:Do we have a TimeSpan sort of class in Java

这里有一种方法可以使用 GregorianCalendar 来完成您想要做的事情:

Calendar time = new GregorianCalendar();
Calendar time2 = new GregorianCalendar();
time2.add(GregorianCalendar.HOUR, 2);

System.out.println(time2.getTimeInMillis() - time.getTimeInMillis());

问题是在您打印时间时,它正在转换为您的时区。基本上时区仅用于展示,而不是日期的存储方式。你必须显示你的格林威治标准时间,然后它会给你你想要的。像这样:

Time time = new Time(00,00,00);
Time time2 = new Time(02,00,00);
long longTime = (time2.getTime() - time.getTime());
Time finalTime = new Time(longTime);
System.out.println(finalTime.toString());
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
//correct one
System.out.println(sdf.format(finalTime));

此外,我认为您正在使用 java.sql.Time class,除非您正在使用 sql,否则我认为 class 的使用是错误的。 Date class 拥有您需要的一切,Calendar class 也是如此。还有一些新的 java 时间 class 我没用过但看起来很有趣 https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

这是交易...

首先,如果可能的话,我建议不要使用 class 时间,因为它的方法大多已被弃用。

改为尝试使用日期 class 或持续时间和即时 https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

如果您现在必须坚持这个 class,这里是诀窍。

构造函数new Time(long)考虑了时区偏移...

因此,如果您处于 +02 时区...您的时间对象将在 120 分钟后增加。

要解决此问题,您可以使用 Time.getTimezoneOffset()

此方法将 return 一个整数,其中包含您所在时区的分钟数

我为此编辑了我的代码,现在它可以正常工作了:

public static void main(String[] args) {


    Time time = new Time(00,00,00);
    Time time2 = new Time(02,00,00);

    long longTime = (time2.getTime() - time.getTime());

    Time finalTime = new Time(longTime);

    int timeOffset = time.getTimezoneOffset();
    finalTime.setMinutes(finalTime.getMinutes()+timeOffset);

    System.out.println(finalTime.toString());   

    }

八进制数

您在 Java 中的文字数字上使用了前导零。这意味着 octal number(基数 8)而不是十进制数(基数 10)。

您应该使用 0 而不是 00,并且 2 而不是 02

不太可能是这个特定示例中的核心问题,因为八进制零和二具有相同的十进制值。

在我看来,这个问题没有实际意义。您的 objective 有更好的方法;继续阅读。

java.time

问题和其他答案使用旧的过时日期时间 classes 与 Java 的最早版本捆绑在一起。事实证明,那些旧的 classes 非常麻烦、有缺陷且设计不佳。它们已在 Java 8 及之后被 java.time framework. See Tutorial.

取代

新的 classes 包括 LocalTime 时间值,没有任何日期和任何时区。

使用 LocalTime class 优于 java.sql.Time。 java.sql.* classes 仅用于将数据传入和传出数据库,而不用于业务逻辑。特别是,java.sql.Time class 假装只有一天中的时间,但实际上是 java.util.Date 的子class(一个被黑的 class 设计),所以在内部它确实有一个日期和时区(UTC 另一个隐藏在源代码中但出于某些目的被忽略的时区)。使困惑?正如我所说,旧的日期时间 classes 是一团糟,应该避免;仅在绝对必要时使用,并尽可能简短。

传输后,立即将 java.sql 类型转换为 java.time 类型。 java.sql.Timeclass提供了toLocalTime的方法方便转换。

LocalTime localTime = myJavaSqlTime.toLocalTime();

已过去

您的问题似乎是关于确定一对时间之间经过的时间。

请记住在没有日期的情况下确定经过时间的问题。我们必须假定通用的 24 小时长的一天,同时忽略夏令时 (DST) 或现实世界中发生的其他异常情况。我们必须假设这些发生在同一天,或者滚动到下一个 24 小时时钟。所以一般来说,时间轴上的实际时刻表示为 InstantZonedDateTimeOffsetDateTime.

会更好

java.time 框架提供 Duration class to represent a span of time as a number of whole seconds plus a fraction of a second in nanoseconds.

假设您已经检索到 java.sql.Time 对象并将它们转换为 java.time.LocalTime 对象。

让我们模拟从数据库中获取一对值
LocalTime start = LocalTime.of ( 0 , 0 , 0 ); // First moment of the day.
LocalTime stop = LocalTime.of ( 2 , 0 , 0 ); // 2 AM.

将时间跨度计算为小时、分钟和秒数。

    Duration duration = Duration.between ( start , stop );

转储到控制台。

    System.out.println ( "start: " + start + " | stop: " + stop + " | duration: " + duration );

注意 PnYnMnDTnHnMnSLocalTime::toString uses the standard ISO 8601 格式的隐式调用的输出。在我们的例子中,PT2H 表示“两小时”。 java.time classes 可以解析和生成 ISO 8601 格式。这种标准格式比使用无法与时间区分的模棱两可的 02:00:00 更明智。

start: 00:00 | stop: 02:00 | duration: PT2H

如果你想要数字,你可能会得到持续时间的总秒数。请记住,持续时间也可能包含纳秒的小数秒,而获取整秒时会忽略它。

long seconds = duration.get ( ChronoUnit.SECONDS );  // 7,200 seconds in 2 hours.

或调用 to 方法,例如 toHourstoMinutes 以获取持续时间作为这些单位的总数。

如果您打算将这些通用时间值应用到特定日期以获得时间轴上的实际时刻,请搜索 Stack Overflow,因为它已被覆盖。