在我的代码中,我需要找到今天发生的所有事情。因此,我需要将今天凌晨00:00(今天凌晨午夜)到中午12:00(今晚午夜)的日期进行比较。

我知道……

Date today = new Date(); 

... 我现在很生气。和…

Date beginning = new Date(0);

…1970年1月1日是零。但是有什么简单的方法可以让你今天和明天的时间都为零呢?


更新

我做到了,但肯定有更简单的方法吧?

Calendar calStart = new GregorianCalendar();
calStart.setTime(new Date());
calStart.set(Calendar.HOUR_OF_DAY, 0);
calStart.set(Calendar.MINUTE, 0);
calStart.set(Calendar.SECOND, 0);
calStart.set(Calendar.MILLISECOND, 0);
Date midnightYesterday = calStart.getTime();
            
Calendar calEnd = new GregorianCalendar();
calEnd.setTime(new Date());
calEnd.set(Calendar.DAY_OF_YEAR, calEnd.get(Calendar.DAY_OF_YEAR)+1);
calEnd.set(Calendar.HOUR_OF_DAY, 0);
calEnd.set(Calendar.MINUTE, 0);
calEnd.set(Calendar.SECOND, 0);
calEnd.set(Calendar.MILLISECOND, 0);
Date midnightTonight = calEnd.getTime();

当前回答

这似乎是一个选项:

DateFormat justDay = new SimpleDateFormat("yyyyMMdd");
Date thisMorningMidnight = justDay.parse(justDay.format(new Date()));

也可以再加一天

Date tomorrow = new Date(thisMorningMidnight.getTime() + 24 * 60 * 60 * 1000);

or

Calendar c = Calendar.getInstance();
c.setTime(thisMorningMidnight);
c.add(Calendar.DATE, 1);
Date tomorrowFromCalendar = c.getTime();

我有一种预感,后者是首选,以防一些奇怪的事情,如夏令时,导致增加24小时不够(见https://stackoverflow.com/a/4336131/32453及其其他答案)。

其他回答

这些方法将帮助你

public static Date getStartOfDay(Date date) {
     Calendar calendar = Calendar.getInstance();
     calendar.setTime(date);
     calendar.set(Calendar.HOUR_OF_DAY, 0);
     calendar.set(Calendar.MINUTE, 0);
     calendar.set(Calendar.SECOND, 0);
     calendar.set(Calendar.MILLISECOND, 0);
     return calendar.getTime();
 }

and

public static Date getEndOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    calendar.set(Calendar.MILLISECOND, 999);
    return calendar.getTime();
}

我的做法和这里的其他人都不一样。我刚接触Java,所以我的解决方案可能很差。

Date now = new Date();
Date midnightToday = new Date(now.getYear(), now.getMonth(), now.getDate());

我不确定这是否有效,但无论如何,我很感激任何关于这个解决方案的反馈。

我对上面的陈述感到困惑,你可以通过调用:

c.add(Calendar.DAY_OF_MONTH, 1);

如果你在这个月的第几天加上1是31天,你不是得到了这个月的第32天吗?

为什么Java中的时间/日期不是全部基于UTC ?我认为时区应该只在与I /o一起使用时才需要,但在内部应该总是在UTC中使用。然而,这些类似乎包含了Timezone信息,这不仅浪费时间,而且容易产生编码错误。

其他答案都是正确的,尤其是java。时间回答由干政。正如一些人提到的,应该避免使用旧的java.util.Date/。日历类,因为它们设计得很差,令人困惑,而且很麻烦。他们已经被爪哇取代了。时间类。

让我补充一些关于处理午夜和时间跨度的策略。

半开的

在日期-时间工作中,时间跨度通常使用“半开放”方法来定义。在这种方法中,开始是包容的,而结束是排外的。这可以解决问题,如果始终使用,可以更容易地推理日期时间处理。

One problem solved is defining the end of the day. Is the last moment of the day 23:59:59.999 (milliseconds)? Perhaps, in the java.util.Date class (from earliest Java; troublesome – avoid this class!) and in the highly successful Joda-Time library. But in other software, such as database like Postgres, the last moment will be 23:59:59.999999 (microseconds). But in other software such as the java.time framework (built into Java 8 and later, successor to Joda-Time) and in some database such the H2 Database, the last moment might be 23:59.59.999999999 (nanoseconds). Rather than splitting hairs, think in terms of first moment only, not last moment.

在半开放中,一天从一天的第一个时刻算起,但不包括第二天的第一个时刻。所以与其这样想:

从今天凌晨0点(今天凌晨12点)到下午12点(今晚12点)。

这样想…

从今天的第一个时刻到但不包括明天的第一个时刻:(>=今天的00:00:00.0 AND <明天的00:00:00.0)

在数据库工作中,这种方法意味着不在SQL中使用BETWEEN操作符。

一天的开始

此外,一天的第一个时刻并不总是一天中的00:00:00.0。某些时区的日光节约时间(DST),以及可能存在的其他异常情况,可能意味着一天开始的时间不同。

所以让java。time类通过调用LocalDate::atStartOfDay(ZoneId)来确定一天的开始。因此,我们必须绕过LocalDate,返回到本例代码中所示的zoneeddatetime。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime todayStart = now.toLocalDate().atStartOfDay( zoneId );
ZonedDateTime tomorrowStart = todayStart.plusDays( 1 );

注意可选的ZoneId的传递。如果省略,则隐式应用JVM的当前默认时区。最好是明确一点。

时区对约会时间工作至关重要。这个问题和其他一些答案有潜在的缺陷,因为它们没有有意识地处理时区。

转换

如果必须使用java.util.Date或. calendar,请寻找添加到这些旧类中的新转换方法。

java.util.Date utilDate = java.util.Date.from( todayStart.toInstant() );
java.util.GregorianCalendar gregCal = java.util.GregorianCalendar.from( todayStart );

时间跨度

顺便说一下,如果你在一段时间内做了很多工作,可以看看:

持续时间 期 Interval类可以在ThreeTen-Extra项目中找到,它是java的扩展。时间框架。这个项目是未来可能添加到java.time.Interval todayMontreal = Interval的试验场。of(todayStart.toInstant(), tomorrowStart.toInstant());


关于java.time

java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。

Joda-Time项目现在处于维护模式,建议迁移到java。时间类。

要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。

你可以交换java。Time对象直接使用数据库。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java。sql。*类。

从哪里获取java。时间类?

Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本——带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和Java SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 后续版本的Android捆绑实现的java。时间类。 对于早期的Android (<26), ThreeTenABP项目适应ThreeTen-Backport(如上所述)。参见如何使用ThreeTenABP....

ThreeTen-Extra项目扩展了java。额外的课程时间。这个项目是未来可能添加到java.time的一个试验场。你可以在这里找到一些有用的类,比如Interval、YearWeek、YearQuarter等等。

记住,Date不是用来表示日期的(!)。为了表示日期,你需要一个日历。这样的:

Calendar c = new GregorianCalendar();

将创建一个日历实例,表示当前时区的当前日期。现在需要做的是截断日以下的每个字段(小时、分钟、秒和毫秒),将其设置为0。今天是午夜。

现在要得到第二天的午夜,你需要添加一天:

c.add(Calendar.DAY_OF_MONTH, 1);

请注意,加上86400秒或24小时是不正确的,因为在此期间可能会发生夏季时间。

更新:然而,我最喜欢的处理这个问题的方法是使用来自Commons Lang的DateUtils类:

Date start = DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH))
Date end = DateUtils.addDays(start, 1);

它在幕后使用Calendar…

老式的方式…

private static Date getDateWithMidnight(){
    long dateInMillis = new Date().getTime();
    return new Date(dateInMillis - dateInMillis%(1000*60*60*24) - TimeZone.getDefault().getOffset(dateInMillis));
}