如何创建今天午夜和明天午夜的Java Date对象?

Rob*_*ume 170 java date

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

我知道 ...

Date today = new Date(); 
Run Code Online (Sandbox Code Playgroud)

......马上找我 而......

Date beginning = new Date(0);
Run Code Online (Sandbox Code Playgroud)

...让我在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();
Run Code Online (Sandbox Code Playgroud)

tim*_*hew 330

java.util.Calendar中

// today    
Calendar date = new GregorianCalendar();
// reset hour, minutes, seconds and millis
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);

// next day
date.add(Calendar.DAY_OF_MONTH, 1);
Run Code Online (Sandbox Code Playgroud)

JDK 8 - java.time.LocalTime和java.time.LocalDate

LocalTime midnight = LocalTime.MIDNIGHT;
LocalDate today = LocalDate.now(ZoneId.of("Europe/Berlin"));
LocalDateTime todayMidnight = LocalDateTime.of(today, midnight);
LocalDateTime tomorrowMidnight = todayMidnight.plusDays(1);
Run Code Online (Sandbox Code Playgroud)

乔达时间

如果你使用JDK <8,我推荐Joda Time,因为API非常好:

DateTime date = new DateTime().toDateMidnight().toDateTime();
DateTime tomorrow = date.plusDays(1);
Run Code Online (Sandbox Code Playgroud)

由于Joda Time版本2.3 DateMidnight弃用,因此请使用:

DateTime today = new DateTime().withTimeAtStartOfDay();
DateTime tomorrow = today.plusDays(1).withTimeAtStartOfDay();
Run Code Online (Sandbox Code Playgroud)

如果您不想要JVM的当前默认时区,请传递时区.

DateTimeZone timeZone = DateTimeZone.forID("America/Montreal");
DateTime today = new DateTime(timeZone).withTimeAtStartOfDay(); // Pass time zone to constructor.
Run Code Online (Sandbox Code Playgroud)

  • 从JodaTime 2.3开始,不推荐使用`toDateMidnight`.有关详细信息,请参阅此答案:http://stackoverflow.com/a/19048833/363573 (3认同)

ric*_*din 34

为了完整起见,如果您使用的是Java 8,您还可以使用该类的truncatedTo方法Instant来获取UTC的午夜时间.

Instant.now().truncatedTo(ChronoUnit.DAYS);
Run Code Online (Sandbox Code Playgroud)

正如Javadoc所写

例如,使用MINUTES单位截断将向下舍入到最接近的分钟,将秒和纳秒设置为零.

希望能帮助到你.

  • 注意[truncatedTo`和`atStartOfDay`之间的区别](/sf/ask/2040073731/). (3认同)

And*_*gin 33

找到午夜最简单的方法:

Long time = new Date().getTime();
Date date = new Date(time - time % (24 * 60 * 60 * 1000));
Run Code Online (Sandbox Code Playgroud)

明天:

Date date = new Date(date.getTime() + 24 * 60 * 60 * 1000);
Run Code Online (Sandbox Code Playgroud)

  • 如果您执行类似System.out.print(date)的操作,系统会将日期实例转换为系统时区(CDT).晚上7点在CDT是GMT的午夜.如果您需要在所选时区中使用午夜,则必须添加此时区的偏移量,并将DST考虑在内. (3认同)
  • @Andrei Volgin不知道有一个“ java午夜”。;)我想说的是该解决方案确实对imo并没有真正帮助主题创建者。日历解决方案避免了笨拙的第二次计算,并且在正确使用时会注意时区(尤其是夏时制等)。我看不到您的解决方案。 (2认同)

Tom*_*icz 28

请记住,Date不用于表示日期(!).要表示日期,您需要一个日历.这个:

Calendar c = new GregorianCalendar();
Run Code Online (Sandbox Code Playgroud)

将创建一个Calendar表示当前时区当前日期的实例.现在你需要的是通过将其设置为截断日下面的每个字段(小时,分钟,秒和毫秒)0.你现在今天午夜了.

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

c.add(Calendar.DAY_OF_MONTH, 1);
Run Code Online (Sandbox Code Playgroud)

请注意,86400由于夏令时可能会同时增加秒或24小时是不正确的.

更新:但是我最喜欢处理这个问题的方法是使用Commons Lang的DateUtils类:

Date start = DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH))
Date end = DateUtils.addDays(start, 1);
Run Code Online (Sandbox Code Playgroud)

Calendar在幕后使用......

  • 谢谢您的帮助."日期并不是用来代表日期" - 我们认为这非常棒,不是吗?;) (15认同)

Vis*_*oot 14

这些方法可以帮助你 -

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();
 }
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)


Chy*_*nov 10

JDK8 - Java时间模块方式:

LocalDateTime todayMidnight = LocalDate.now().atStartOfDay();

还工作:

LocalDateTime todayMidnight = LocalDateTime.now().with(LocalTime.MIDNIGHT);


Ste*_*han 9

从JodaTime 2.3开始,toDateMidnight()不推荐使用.

2.2升级到2.3

    Deprecations since 2.2
    ----------------------
    - DateMidnight [#41]
     This class is flawed in concept
     The time of midnight occasionally does not occur in some time-zones
     This is a result of a daylight savings time from 00:00 to 01:00
     DateMidnight is essentially a DateTime with a time locked to midnight
     Such a concept is more generally a poor one to use, given LocalDate
     Replace DateMidnight with LocalDate
     Or replace it with DateTime, perhaps using the withTimeAtStartOfDay() method

这是一个没有toDateMidnight()方法的示例代码.

DateTime todayAtMidnight = new DateTime().withTimeAtStartOfDay();
System.out.println(todayAtMidnight.toString("yyyy-MM-dd HH:mm:ss"));
Run Code Online (Sandbox Code Playgroud)

输出(可能因您当地的时区而异)

2013-09-28 00:00:00
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案.我想添加一个[`DateTimeZone`](http://www.joda.org/joda-time/apidocs/org/joda/time/DateTimeZone.html)实例到[`DateTime`](http ://www.joda.org/joda-time/apidocs/org/joda/time/DateTime.html)构造函数强调指定时区的重要性,而不是无意中取决于默认值:`DateTimeZone timeZone = DateTimeZone.forID ("欧洲/巴黎");` (2认同)

Bas*_*que 7

其他答案都是正确的,尤其是arganzheng的java.time回答.正如一些人提到的,你应该避免使用旧的java.util.Date/.Calendar类,因为它们的设计很糟糕,令人困惑,而且很麻烦.它们已被java.time类取代.

让我添加关于处理午夜时间跨度的策略的说明.

半开

在日期时间工作中,通常使用"半开"方法定义时间跨度.在这种方法中,开始是包容性的,而结尾是排他性的.这解决了问题,如果一直使用,可以更容易地推断您的日期时间处理.

解决的一个问题是定义当天的结束.是一天的最后一刻23:59:59.999(毫秒)?也许,在java.util.Date类中(来自最早的Java;麻烦 - 避免这个类!)和非常成功的Joda-Time库.但在其他软件中,如像Postgres这样的数据库,最后一刻将是23:59:59.999999(微秒).但是在其他软件中,例如java.time框架(内置于Java 8及更高版本,Joda-Time的后继版本)和某些数据库(如H2数据库)中,最后一刻可能是23:59.59.999999999(纳秒).而不是分裂头发,只考虑第一时刻,而不是最后时刻.

在半开放状态下,一天从一天的第一个时刻开始上升,但不包括第二天的第一个时刻.所以不要这样想:

......从今天上午00:00(今天凌晨的午夜)到中午12:00(今晚午夜).

......这样想......

从今天的第一个时刻开始,但不包括明天的第一个时刻:
(> = 00:00:00.0今天和< 00:00:00.0明天)

在数据库工作中,此方法意味着不在 SQL中使用BETWEEN运算符.

一天的开始

此外,一天的第一时刻并不总是一天中的时间00:00:00.0.某些时区的夏令时(DST)以及可能的其他异常可能意味着一天中的不同时间开始.

所以让java.time类通过调用来确定一天的开始LocalDate::atStartOfDay( ZoneId ).因此,我们必须绕过LocalDate并返回到ZonedDateTime您在此示例代码中看到的内容.

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

注意可选的传递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 );
Run Code Online (Sandbox Code Playgroud)

时间跨度

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

  • Duration
  • Period
  • Interval
    Interval班在发现ThreeTen-额外的项目,扩展到java.time框架.该项目是未来可能添加到java.time的试验场.
    Interval todayMontreal = Interval.of( todayStart.toInstant() , tomorrowStart.toInstant() );

关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,Calendar,和SimpleDateFormat.

现在处于维护模式Joda-Time项目建议迁移到java.time类.

要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.

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

从哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.


arg*_*eng 6

java.time

如果您使用的是Java 8及更高版本,则可以尝试java.time包(教程):

LocalDate tomorrow = LocalDate.now().plusDays(1);
Date endDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant());
Run Code Online (Sandbox Code Playgroud)

  • 好答案.我建议指定所需/预期的时区.JVM的当前默认时区可能因操作系统设置,更改计算机或JVM的任何线程中的任何应用程序而异,在运行时期间随时更改默认值. (2认同)

rog*_*ack 5

这似乎是一个选项:

DateFormat justDay = new SimpleDateFormat("yyyyMMdd");
Date thisMorningMidnight = justDay.parse(justDay.format(new Date()));
Run Code Online (Sandbox Code Playgroud)

添加一天,要么

Date tomorrow = new Date(thisMorningMidnight.getTime() + 24 * 60 * 60 * 1000);
Run Code Online (Sandbox Code Playgroud)

或者

Calendar c = Calendar.getInstance();
c.setTime(thisMorningMidnight);
c.add(Calendar.DATE, 1);
Date tomorrowFromCalendar = c.getTime();
Run Code Online (Sandbox Code Playgroud)

我有一种预感,如果出现夏令时等奇怪的事情导致增加 24 小时不够用,则首选后者(请参阅/sf/answers/303529201/及其其他答案)。