【问题标题】:How to get date part (dispose of time part) from java.util.Date?如何从 java.util.Date 获取日期部分(处理时间部分)?
【发布时间】:2011-09-30 11:18:15
【问题描述】:

我想比较两个java.util.Date 对象的日期部分。我怎样才能做到这一点?我不想分别比较日期、月份和年份。

提前致谢!

【问题讨论】:

标签: java date calendar date-comparison


【解决方案1】:

commons-lang DateUtils 为这个问题提供了一个很好的解决方案:

watch this

这样,您可以在一行中比较两个 Date 实例,而忽略您想要的 Date 的每个部分。

Date date1 = new Date(2011, 8, 30, 13, 42, 15);
    Date date2 = new Date(2011, 8, 30, 15, 23, 46);
    int compareTo = DateUtils.truncatedCompareTo(date1, date2,
            Calendar.DAY_OF_MONTH);

在本例中,compareTo 的值为 0。

【讨论】:

  • 我有点犹豫是否要为此使用 api 方法,因为它需要新的导入到我的类中。
【解决方案2】:

Date 只是一个瞬间。当您对其应用日历和时区时,它仅在日期方面真正“意味着”任何东西。因此,如果您想坚持使用标准 Java API,您应该真正关注 Calendar - 您可以创建一个具有正确 Date 和时区的 Calendar 对象,然后将时间组件设置为 0。

但是,最好使用Joda Time 开头,它的LocalDate 类型更准确地反映了您感兴趣的内容。

【讨论】:

  • 我将日历组件设置为 0 并且有效!实际上我只是在处理日历对象,但我使用setTime() 方法设置日期。这就是问题的不可避免的根源。此外,我使用的比较函数将日期作为其参数,而不是日历。所以,需要一些与日期有关的东西。总之,非常感谢!
  • 我不能使用 Joda Time,因为我正在开发一个产品并为如此琐碎的事情添加 API 将是一种浪费。
  • @Piyush:你现在这么说……但是在你维护了应用程序几年并且不断被内置 API 的缺陷咬伤之后,回来再说一遍…… . 说真的,如果有任何方法您可以在这里开始使用 Joda Time,您将在代码可读性和可维护性方面获得重大胜利。
  • @Jon 看我知道长期问题。但问题是我目前只面临一个问题,我可以使用 java API 来解决它。此外,IBM 为产品添加新 API 的过程非常困难,我不是这里的决策者。我只是写解码代码:P
  • @Piyush:好吧,别说我没有警告你... :)
【解决方案3】:

使用 Calendar.set() 与 Calendar.HOUR_OF_DAY、Calendar.MINUTE、Calendar.SECOND 和 Calendar.MILLISECOND 将所有这些字段设置为 0。

这个重复问题的答案会很有用:Resetting the time part of a timestamp in Java

【讨论】:

  • 是的,这就是我所做的:)。虽然,问题不同。他正在使用java.sql.* 包
【解决方案4】:

在下面找到使用 Joda Time 并支持时区的解决方案。 因此,您将在 JVM 中当前配置的时区中获取日期和时间(到 currentDate 和 currentTime)。

请注意,Joda Time 不支持闰秒。因此,您可能会偏离真实值大约 26 或 27 秒。这可能要在未来 50 年内才能解决,届时累积误差将接近 1 分钟,人们会开始关心它。

另请参阅:https://en.wikipedia.org/wiki/Leap_second

/**
 * This class splits the current date/time (now!) and an informed date/time into their components:
 * <lu>
 *     <li>schedulable: if the informed date/time is in the present (now!) or in future.</li>
 *     <li>informedDate: the date (only) part of the informed date/time</li>
 *     <li>informedTime: the time (only) part of the informed date/time</li>
 *     <li>currentDate: the date (only) part of the current date/time (now!)</li>
 *     <li>currentTime: the time (only) part of the current date/time (now!)</li>
 * </lu>
 */
public class ScheduleDateTime {
    public final boolean schedulable;
    public final long millis;
    public final java.util.Date informedDate;
    public final java.util.Date informedTime;
    public final java.util.Date currentDate;
    public final java.util.Date currentTime;

    public ScheduleDateTime(long millis) {
        final long now = System.currentTimeMillis();
        this.schedulable = (millis > -1L) && (millis >= now);

        final TimeZoneUtils tz = new TimeZoneUtils();

        final java.util.Date          dmillis   = new java.util.Date( (millis > -1L) ? millis : now );
        final java.time.ZonedDateTime zdtmillis = java.time.ZonedDateTime.ofInstant(dmillis.toInstant(), java.time.ZoneId.systemDefault());
        final java.util.Date          zdmillis  = java.util.Date.from(tz.tzdate(zdtmillis));
        final java.util.Date          ztmillis  = new java.util.Date(tz.tztime(zdtmillis));

        final java.util.Date          dnow   = new java.util.Date(now);
        final java.time.ZonedDateTime zdtnow = java.time.ZonedDateTime.ofInstant(dnow.toInstant(), java.time.ZoneId.systemDefault());
        final java.util.Date          zdnow  = java.util.Date.from(tz.tzdate(zdtnow));
        final java.util.Date          ztnow  = new java.util.Date(tz.tztime(zdtnow));

        this.millis       = millis;
        this.informedDate = zdmillis;
        this.informedTime = ztmillis;
        this.currentDate  = zdnow;
        this.currentTime  = ztnow;
    }
}



public class TimeZoneUtils {

    public java.time.Instant tzdate() {
        final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
        return tzdate(zdtime);
    }
    public java.time.Instant tzdate(java.time.ZonedDateTime zdtime) {
        final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
        final java.time.Instant instant = zddate.toInstant();
        return instant;
    }

    public long tztime() {
        final java.time.ZonedDateTime zdtime = java.time.ZonedDateTime.now();
        return tztime(zdtime);
     }
    public long tztime(java.time.ZonedDateTime zdtime) {
        final java.time.ZonedDateTime zddate = zdtime.truncatedTo(java.time.temporal.ChronoUnit.DAYS);
        final long millis = zddate.until(zdtime, java.time.temporal.ChronoUnit.MILLIS);
        return millis;
    }
}

【讨论】:

    【解决方案5】:

    tl;博士

    LocalDate ld = 
        myUtilDate.toInstant()
                  .atZone( ZoneId.of( "America/Montreal" ) )
                  .toLocalDate() ;
    

    避免使用旧的日期时间类

    您正在使用麻烦的旧旧日期时间类。避开他们。

    改为使用java.time 类。这些取代了旧的类以及 Joda-Time 库。

    转换

    将您的java.util.Date 转换为Instant。

    Instant 类代表UTC 中时间轴上的一个时刻,分辨率为nanoseconds。

    Instant instant = myUtilDate.toInstant();
    

    时区

    应用时区。时区至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,法国巴黎午夜过后几分钟是新的一天,而魁北克蒙特利尔则是“昨天”。

    应用ZoneId 以获取ZonedDateTime 对象。

    ZoneId z = ZoneId.of( "America/Montreal" );
    ZonedDateTime zdt = instant.atZone( z );
    

    Local… 类型

    LocalDate 类表示没有时间和时区的仅日期值。同样,LocalTime 表示没有日期和时区的时间。您可以将它们视为两个组件,它们与ZoneId 一起构成ZonedDateTime。您可以从ZonedDateTime 中提取这些内容。

    LocalDate ld = zdt.toLocalDate();
    LocalTime lt = zdt.toLocalTime();
    

    字符串

    如果您的目标只是生成字符串以呈现给用户,则不需要 Local… 类型。相反,使用DateTimeFormatter 生成仅表示日期部分或时间部分的字符串。该类足够聪明,可以在生成字符串时自动localize。

    指定Locale 以确定 (a) 用于翻译日期名称、月份名称等的人类语言,以及 (b) 用于决定诸如缩写、大写、标点符号等问题的文化规范.

    Locale l = Locale.CANADA_FRENCH ;  // Or Locale.US, Locale.ITALY, etc.
    
    DateTimeFormatter fDate = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale );
    String outputDate = zdt.format( fDate );
    
    DateTimeFormatter fTime = DateTimeFormatter.ofLocalizedTime( FormatStyle.MEDIUM ).withLocale( locale );
    String outputTime = zdt.format( fTime );
    

    关于java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,例如 java.util.Date、.Calendar 和 java.text.SimpleDateFormat。

    Joda-Time 项目现在位于 maintenance mode,建议迁移到 java.time。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。

    大部分 java.time 功能在ThreeTen-Backport 中向后移植到Java 6 和7,并进一步适应ThreeTenABP 中的Android(请参阅How to use…)。

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 2014-06-02
      • 2020-03-19
      • 1970-01-01
      • 2011-03-13
      相关资源
      最近更新 更多