From a given Date I need to calculate midnight of its day. Here's what I came up with. It's so ugly that I figure there must be a better way.
private Date day(Date creation) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(creation);
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();
}
Suggestions?
Kent
The Excel DAYS function returns the number of days between two dates. With a start date in A1 and end date in B1, =DAYS(B1,A1) will return the days between the two dates.
You should consider the built-in date API obselete. Instead use the Joda date and time API.
Here's a drop-in replacement for your method.
private Date day(Date creation) {
return new DateMidnight(creation).toDate();
}
Here's a simple test:
public static void main(String[] args) {
final Date creation = new Date();
final Date midnight = new Foobar().day(creation);
System.out.println("creation = " + creation);
System.out.println("midnight = " + midnight);
}
The output is:
creation = Sun May 31 10:09:38 CEST 2009
midnight = Sun May 31 00:00:00 CEST 2009
JODA might have a better solution, at the cost of another dependency on a library. I'm looking at its DateMidnight property. I'm sorry that I can't answer more authoritatively, but I'm not a JODA user myself.
If you're looking for local time, that's the best you're going to get. And although you may consider it ugly, there's (potentially) a lot going on behind the scenes.
If you want midnight UTC, the following will work:
public static void main(String[] argv)
throws Exception
{
final long MILLIS_PER_DAY = 24 * 3600 * 1000L;
long midnightUTC = (System.currentTimeMillis() / MILLIS_PER_DAY) * MILLIS_PER_DAY;
}
Edit: I really don't recommend using local dates in "production" code. They cause more trouble than they're worth -- consider a person on the US west coast who suddenly finds his/her "day" trimmed by 3 hours because an east coast computer has a different idea of midnight.
JODA is the way to go if you have serious calendar needs, at least until JSR-310 gets into the JDK (1.7 maybe, if not 1.8).
That being said, there are a couple of things that could be done to make this code a little nicer.
import static java.util.Calendar.*;
...
private static final List<Integer> TIME_FIELDS =
Arrays.asList(HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND);
private Date day(Date creation) {
Calendar c = getInstance();
c.setTime(creation);
for(int field : TIME_FIELDS) c.set(field, 0);
return c.getTime();
}
That won't win any performance awards. You could do a standard for loop relying on the specific field values (the Calendar class has a FIELD_COUNT field kind of implying you can do something like that) but that risks issues across JDK implementations and between versions.
Using the date4j library :
DateTime start = dt.getStartOfDay();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With