user550738
user550738

Reputation:

How to create a Java Date object of midnight today and midnight tomorrow?

In my code I need to find all my things that happened today. So I need to compare against dates from today at 00:00 AM (midnight early this morning) to 12:00 PM (midnight tonight).

I know ...

Date today = new Date(); 

... gets me right now. And ...

Date beginning = new Date(0);

... gets me zero time on Jan 1, 1970. But what's an easy way to get zero time today and zero time tomorrow?


UPDATE

I did this, but surely there's an easier way?

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();

Upvotes: 229

Views: 316962

Answers (20)

riccardo.cardin
riccardo.cardin

Reputation: 8353

For the sake of completeness, if you are using Java 8 you can also use the truncatedTo method of the Instant class to get midnight in UTC.

Instant.now().truncatedTo(ChronoUnit.DAYS);

As written in the Javadoc

For example, truncating with the MINUTES unit will round down to the nearest minute, setting the seconds and nanoseconds to zero.

Hope it helps.

Upvotes: 85

Chyngyz Sagynov
Chyngyz Sagynov

Reputation: 161

JDK8 - Java Time Module way:

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

Also work:

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

Upvotes: 10

Basil Bourque
Basil Bourque

Reputation: 338211

Other answers are correct, especially the java.time answer by arganzheng. As some mentioned, you should avoid the old java.util.Date/.Calendar classes as they are poorly designed, confusing, and troublesome. They have been supplanted by the java.time classes.

Let me add notes about strategy around handling midnight and spans of time.

Half-Open

In date-time work, spans of time are often defined using the “Half-Open” approach. In this approach the beginning is inclusive while the ending is exclusive. This solves problems and if used consistently makes reasoning about your date-time handling much easier.

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.

In Half-Open, a day runs from the first moment of one day and goes up to but does not include the first moment of the following day. So rather than think like this:

…from today at 00:00am (midnight early this morning) to 12:00pm (midnight tonight).

…think like this…

from first moment of today running up to but not including first moment of tomorrow:
( >= 00:00:00.0 today AND < 00:00:00.0 tomorrow )

In database work, this approach means not using the BETWEEN operator in SQL.

Start of day

Furthermore, the first moment of the day is not always the time-of-day 00:00:00.0. Daylight Saving Time (DST) in some time zones, and possibly other anomalies, can mean a different time starts the day.

So let the java.time classes do the work of determining the start of a day with a call to LocalDate::atStartOfDay( ZoneId ). So we have to detour through LocalDate and back to ZonedDateTime as you can see in this example code.

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

Note the passing of the optional ZoneId. If omitted your JVM’s current default time zone is applied implicitly. Better to be explicit.

Time zone is crucial to date-time work. The Question and some other Answers are potentially flawed because the do not consciously handle time zone.

Convert

If you must use a java.util.Date or .Calendar, look for new conversion methods added to those old classes.

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

Span of time

By the way, if you are doing much work with spans of time take a look at:

  • Duration
  • Period
  • Interval
    The Interval class is found in the ThreeTen-Extra project, an extension to the java.time framework. This project is the proving ground for possible future additions to java.time.
    Interval todayMontreal = Interval.of( todayStart.toInstant() , tomorrowStart.toInstant() );

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 12

joe4java
joe4java

Reputation: 69

Using apache commons..

//For midnight today 
Date today = new Date(); 
DateUtils.truncate(today, Calendar.DATE);

//For midnight tomorrow   
Date tomorrow = DateUtils.addDays(today, 1); 
DateUtils.truncate(tomorrow, Calendar.DATE);

Upvotes: 2

Prabath
Prabath

Reputation: 11

Old fashioned way..

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

Upvotes: 0

gzg_55
gzg_55

Reputation: 61

Date now= new Date();
// Today midnight
Date todayMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY);

// tomorrow midnight
Date tomorrowMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY + DateUtils.MILLIS_PER_DAY);

Upvotes: 0

Montaser
Montaser

Reputation: 69

Pretty much as the answers before, but nobody mentioned AM_PM parameter:

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    cal.set(Calendar.AM_PM, Calendar.AM);

Upvotes: 1

Vadzim
Vadzim

Reputation: 26160

Date todayMidnightUTC = java.sql.Date.valueOf(LocalDate.now());
Date tomorrowMidnightUTC = java.sql.Date.valueOf(LocalDate.now().plusDays(1));
Date anyMidnightLocal = java.sql.Date.valueOf(LocalDate.from(dateTime.toInstant().atZone(ZoneId.systemDefault())));

But beware that java.sql.Date.toInstant() always throws UnsupportedOperationException.

Via LocalDate to java.util.Date and vice versa simpliest conversion?

Upvotes: -1

lshu
lshu

Reputation: 9

Because of one day is 24 * 60 * 60 * 1000 ms, the midnight of this day can be calculate as...

long now = System.currentTimeMillis();
long delta = now % 24 * 60 * 60 * 1000;
long midnight = now - delta;
Date midnightDate = new Date(midnight);`

Upvotes: 0

Mitch
Mitch

Reputation: 1734

I did this differently than everyone else here did. I'm new to Java, so maybe my solution is poor.

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

I'm not sure this works yet, but either way, I'd appreciate any feedback on this solution.

I'm confused by the statement above that you can calculate tomorrow by calling:

c.add(Calendar.DAY_OF_MONTH, 1);

If you add 1 to the day of the month and it's the 31st day, don't you get the 32nd day of the month?

Why are times/dates not all based on UTC in Java? I would think Timezones should only be needed when used with i/o, but internally should always be used in UTC. However, the classes seem to include Timezone info which seems not only wasteful, but prone to coding errors.

Upvotes: 1

timaschew
timaschew

Reputation: 16602

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);

JDK 8 - java.time.LocalTime and 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);

Joda-Time

If you're using a JDK < 8, I recommend Joda Time, because the API is really nice:

DateTime date = new DateTime().toDateMidnight().toDateTime();
DateTime tomorrow = date.plusDays(1);

Since version 2.3 of Joda Time DateMidnight is deprecated, so use this:

DateTime today = new DateTime().withTimeAtStartOfDay();
DateTime tomorrow = today.plusDays(1).withTimeAtStartOfDay();

Pass a time zone if you don't want the JVM’s current default time zone.

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

Upvotes: 417

Visvendra Singh Rajpoot
Visvendra Singh Rajpoot

Reputation: 1213

these methods will help you-

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();
}

Upvotes: 17

arganzheng
arganzheng

Reputation: 1334

java.time

If you are using Java 8 and later, you can try the java.time package (Tutorial):

LocalDate tomorrow = LocalDate.now().plusDays(1);
Date endDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant());

Upvotes: 7

Rajeev
Rajeev

Reputation: 1840

I know this is very old post. I thought to share my knowledge here !

For the date Mid night today with exact Time zone you can use following

public static Date getCurrentDateWithMidnightTS(){

    return new Date(System.currentTimeMillis() - (System.currentTimeMillis()%(1000*60*60*24)) - (1000*60 * 330));
}

Where (1000*60 * 330) is being subtracted i.e. actually related to time zone for example Indian time zone i.e. kolkata differs +5:30hrs from actual . So subtracting that with converting into milliseconds.

So change last substracted number according to you. I m creating a product i.e. only based in India So just used specific timestamp.

Upvotes: -1

rogerdpack
rogerdpack

Reputation: 66711

This appears to be an option:

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

to add a day to it, either

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();

I have a hunch the latter is preferred in case of something weird like daylight savings causing adding 24 hours to not be enough (see https://stackoverflow.com/a/4336131/32453 and its other answers).

Upvotes: 6

Javier Sculli
Javier Sculli

Reputation: 1

The simplest way with JodaTime

DateMidnight date = DateMidnight.now();

Upvotes: 0

Stephan
Stephan

Reputation: 43013

As of JodaTime 2.3, the toDateMidnight() is deprecated.

From Upgrade from 2.2 to 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

Here is a sample code without toDateMidnight() method.

Code

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

Output (may be different depending on your local time zone)

2013-09-28 00:00:00

Upvotes: 9

Anders B
Anders B

Reputation: 3457

Apache Commons Lang

DateUtils.isSameDay(date1, date2)

http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/time/DateUtils.html#isSameDay(java.util.Date, java.util.Date)

Upvotes: 0

Andrei Volgin
Andrei Volgin

Reputation: 41089

The easiest way to find a midnight:

Long time = new Date().getTime();
Date date = new Date(time - time % (24 * 60 * 60 * 1000));

Next day:

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

Upvotes: 40

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340693

Remember, Date is not used to represent dates (!). To represent date you need a calendar. This:

Calendar c = new GregorianCalendar();

will create a Calendar instance representing present date in your current time zone. Now what you need is to truncate every field below day (hour, minute, second and millisecond) by setting it to 0. You now have a midnight today.

Now to get midnight next day, you need to add one day:

c.add(Calendar.DAY_OF_MONTH, 1);

Note that adding 86400 seconds or 24 hours is incorrect due to summer time that might occur in the meantime.

UPDATE: However my favourite way to deal with this problem is to use DateUtils class from Commons Lang:

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

It uses Calendar behind the scenes...

Upvotes: 33

Related Questions