【问题标题】:Java - issues comparing Calendar to LocalDateTime?Java - 比较日历和 LocalDateTime 的问题?
【发布时间】:2021-06-04 03:05:18
【问题描述】:

我的Java 代码中有以下比较:

if(appointment.getEndDate().after(LocalDateTime.now()){

//do something
}

注意endDate 字段是Calendar 类型。

以这种方式比较CalendarLocalDateTime 是否有任何问题,或者有更好的方法吗?

【问题讨论】:

  • 很多事情要考虑,但要点是比较两种不同的时间单位是不明智的。我更喜欢使用 LocalDateTime。如果您无法摆脱日历,这是一个转换链接。 javaprogramto.com/2020/08/…
  • 我建议您既不要使用Calendar 也不要使用LocalDateTime。对于可以与另一个时间点进行比较的时间点,请使用 Instant 或定义时间点的另一个类。 LocalDateTime 没有。而Calendar 类的设计很糟糕而且已经过时了。

标签: java java-8 calendar localdate localdatetime


【解决方案1】:

在日历和日历之间进行比较是否有任何问题? LocalDateTime 这种方式,还是有更好的方法?

是的,它会给你一个不正确的结果。此外,java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern date-time API*

您应该将Calendar 对象转换为Instant,然后您可以使用现代日期时间API 完成其余的事情。

演示:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        // A sample calendar object
        String strDateTime = "10/02/2021 22:25";
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm", Locale.ENGLISH);
        Date date = sdf.parse(strDateTime);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        Instant instant = calendar.getTime().toInstant();

        // Change the ZoneId as per your requirement e.g. ZoneId.of("Europe/London")
        ZoneId zoneId = ZoneId.systemDefault();

        ZonedDateTime zdt = instant.atZone(zoneId);

        ZonedDateTime now = ZonedDateTime.now(zoneId);

        System.out.println(zdt.isAfter(now));
    }
}

输出:

true

通过 Trail: Date Time 了解有关现代日期时间 API 的更多信息。


更新

谢谢,Ole V.V. for your valuable feedback:.

如果 OP 无法升级约会类以返回 结束日期时间的现代类型(如ZonedDateTime),就是这样 去。 Calendar 也有 toInstant method,所以你可以用 只需Instant instant = calendar.toInstant();。对于创建一个 示例老式 Calendar 我会使用 like GregorianCalendar.from(ZonedDateTime.of(2021, 10, 2, 22, 25, 0, 0, ZoneId.systemDefault()))


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个Android项目工作并且您的Android API级别仍然不符合Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

  • 如果 OP 无法升级约会类以返回现代类型(如 ZonedDateTime)结束日期时间,这就是要走的路。 Calendar 也有一个toInstant method,所以你可以简单地使用Instant instant = calendar.toInstant();。为了创建一个老式的示例Calendar,我会使用GregorianCalendar.from(ZonedDateTime.of(2021, 10, 2, 22, 25, 0, 0, ZoneId.systemDefault()))
【解决方案2】:

您不应将CalendarLocalDateTime 对象进行比较。根据文档,这将 always 返回 false

返回此日历是否表示时间之后的时间 由指定的 Object 表示。该方法等价于:

compareTo(when) > 0

当且仅当 when 是 Calendar 实例。否则,该方法返回 false。

您需要先将日历转换为LocalDateTime,然后再将其与另一个LocalDateTime 进行比较

您可以使用以下代码进行转换

LocalDateTime localDateTime = LocalDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId());

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2017-11-08
相关资源
最近更新 更多