views:

4820

answers:

5

In Java, given a timestamp, how to reset the time part alone to 00:00:00 so that the timestamp represents the midnight of that particular day ?

In T-SQL, this query will do to achieve the same, but I don't know how to do this in Java.

SELECT CAST( FLOOR( CAST(GETDATE() AS FLOAT ) ) AS DATETIME) AS 'DateTimeAtMidnight';

+3  A: 

Assuming your "timestamp" is a java.util.Date, which is represented as the number of milliseconds since the beginning of the epoch (Jan 1, 1970), you can perform the following arithmetic:

public static Date stripTimePortion(Date timestamp) {
    long msInDay = 1000 * 60 * 60 * 24; // Number of milliseconds in a day
    long msPortion = timestamp.getTime() % msInDay;
    return new Date(timestamp.getTime() - msPortion);
}
thoroughly
Note that if the Date here is actually a java.sql.Timestamp instance, you would miss setting nanos to 0 which would probably bite you in the ass later.
Alex Miller
Also, you're making an assumption that leap seconds never affect the millis since the epoch. I think that's true but I'm not sure if it's guaranteed.
Alex Miller
According to the javadoc for java.sql.Timestamp, getTime() should still return milliseconds. The getNanos() will return nanoseconds.
thoroughly
+11  A: 

You can go Date->Calendar->set->Date:

Date date = new Date();                      // timestamp now
Calendar cal = Calendar.getInstance();       // get calendar instance
cal.setTime(date);                           // set cal to date
cal.set(Calendar.HOUR_OF_DAY, 0);            // set hour to midnight
cal.set(Calendar.MINUTE, 0);                 // set minute in hour
cal.set(Calendar.SECOND, 0);                 // set second in minute
cal.set(Calendar.MILLISECOND, 0);            // set millis in second
Date zeroedDate = cal.getTime();             // actually computes the new Date

I love Java dates.

Note that if you're using actual java.sql.Timestamps, they have an extra nanos field. Calendar of course, knows nothing of nanos so will blindly ignore it and effectively drop it when creating the zeroedDate at the end, which you could then use to create a new Timetamp object.

I should also note that Calendar is not thread-safe, so don't go thinking you can make that a static single cal instance called from multiple threads to avoid creating new Calendar instances.

Alex Miller
A: 

Since I don't do much DateTime manipulation, this might not be the best way to do it. I would spawn a Calendar and use the Date as source. Then set hours, minutes and seconds to 0 and convert back to Date. Would be nice to see a better way, though.

Jan Gressmann
A: 

Using Calendar.set() would certanly be "by the book" solution, but you might also use java.sql.Date:

java.util.Date originalDate = new java.util.Date();
java.sql.Date wantedDate = new java.sql.Date(originalDate.getTime());

That would do exactly what you want since:

To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.

Since java.sql.Date extends java.util.Date, you can freely use it as such. Be aware that wantedDate.getTime() will retrieve original timestamp though - that's why you don't want to create another java.util.Date from java.sql.Date!

Domchi
This is pretty dangerous I think. java.sql.Date doesn't work like java.util.Date and still holds the full value. If you try to get the h/m/s from it, it throws IllegalArgumentException. It also inherits java.util.Date equals so won't compare as expected necessarily.
Alex Miller
+6  A: 

If you're using commons lang you can call DateUtils.truncate.

Here's the javadoc documentation.

It does the same thing @Alex Miller said to do.

ScArcher2