Reputation:
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?
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
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
Reputation: 161
JDK8 - Java Time Module way:
LocalDateTime todayMidnight = LocalDate.now().atStartOfDay();
Also work:
LocalDateTime todayMidnight = LocalDateTime.now().with(LocalTime.MIDNIGHT);
Upvotes: 10
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.
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.
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.
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 );
By the way, if you are doing much work with spans of time take a look at:
Duration
Period
Interval
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() );
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
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
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
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
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
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
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
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
Reputation: 16602
// 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);
LocalTime midnight = LocalTime.MIDNIGHT;
LocalDate today = LocalDate.now(ZoneId.of("Europe/Berlin"));
LocalDateTime todayMidnight = LocalDateTime.of(today, midnight);
LocalDateTime tomorrowMidnight = todayMidnight.plusDays(1);
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
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
Reputation: 1334
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
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
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
Reputation: 1
The simplest way with JodaTime
DateMidnight date = DateMidnight.now();
Upvotes: 0
Reputation: 43013
As of JodaTime 2.3, the toDateMidnight()
is deprecated.
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
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
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
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