4

I want to implement a thread-safe function to remove the time part from java.util.Date.

I tried this way

private static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
public static Date removeTimeFromDate(Date date) {
        Date returnDate = date;

        if (date == null) {
            return returnDate;
        }

        //just have the date remove the time
        String targetDateStr = df.format(date);
        try {
            returnDate = df.parse(targetDateStr);
        } catch (ParseException e) {
        }

        return returnDate;
}

and use synchronized or threadLocal to make it thread-safe. But it there any better way to implement it in Java. It seems this way is a bit verbose. I am not satisfied with it.

Clark Bao
  • 1,743
  • 3
  • 21
  • 39
  • Just an aside, but it is generally unwise to keep a static reference to a DateFormat for [thread-safety reasons](http://stackoverflow.com/questions/5652518). – McDowell Oct 15 '11 at 11:39
  • You are right. I changed that after knowing it needs to be thread-safe. – Clark Bao Oct 15 '11 at 11:53

2 Answers2

9

A Date object holds a variable wich represents the time as the number of milliseconds since epoch. So, you can't "remove" the time part. What you can do is set the time of that day to zero, which means it will be 00:00:00 000 of that day. This is done by using a GregorianCalendar:

GregorianCalendar gc = new GregorianCalendar();
gc.setTime(date);
gc.set(Calendar.HOUR_OF_DAY, 0);
gc.set(Calendar.MINUTE, 0);
gc.set(Calendar.SECOND, 0);
gc.set(Calendar.MILLISECOND, 0);
Date returnDate = gc.getTime();
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
  • 1
    Probably this is just me, but I prefer Calendar to GregorianCalendar. – DwB Oct 15 '11 at 11:37
  • 1
    Note that time zone matters, and midnight may not exist in that time zone... see my answer. – Jon Skeet Oct 15 '11 at 11:39
  • @JonSkeet: I'm not very familiar with working with TimeZones. Is specifying the timezone as constructor argument enough? – Martijn Courteaux Oct 15 '11 at 11:41
  • @MartijnCourteaux: Yes, that would be fine - but the OP needs to decide *which* time zone they're interested in. Additionally, you may end up with an invalid local time by setting it to midnight. – Jon Skeet Oct 15 '11 at 12:55
4

A Date holds an instant in time - that means it doesn't unambiguously specify a particular date. So you need to specify a time zone as well, in order to work out what date something falls on. You then need to work out how you want to represent the result - as a Date with a value of "midnight on that date in UTC" for example?

You should also note that midnight itself doesn't occur on all days in all time zones, due to DST transitions which can occur at midnight. (Brazil is a common example of this.)

Unless you're really wedded to Date and Calendar, I'd recommend that you start using Joda Time instead, as that allows you to have a value of type LocalDate which gets rid of most of these problems.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • It is using Date already.So I cannot change to Joda Time. And I guess in my usage,it doesn't need to be so accurate. As long as the date part is correctly calculated in its local time. Then that is okay. – Clark Bao Oct 15 '11 at 12:21
  • @ClarkBao: But that's the point - you need to specify which time zone you mean... and if you try setting the calendar to an invalid value, it may well fail when you call `getTime`. If you're doing a lot of date work you should definitely consider changing everything to Joda Time - it's a much nicer API. – Jon Skeet Oct 15 '11 at 12:54
  • the input Date is normally new Date(). Will it be a problem? I find the result is the same as date format way with the Calendar way above. – Clark Bao Oct 15 '11 at 13:15
  • final Date targetDate = new Date(); System.out.println(targetDate); final GregorianCalendar cal = new GregorianCalendar(); cal.setTime(targetDate); System.out.println(cal.getTime()); I find these two are same. – Clark Bao Oct 15 '11 at 13:28
  • @ClarkBao: That's just taking the current instant in time. But you need to work out which time zone you want to consider for turning that into a date. – Jon Skeet Oct 15 '11 at 13:42
  • Ah,I suppose this program is only located in one location and serves for the same location. So this will not be a problem.This piece of code only serves for an internal process. – Clark Bao Oct 16 '11 at 03:56
  • @ClarkBao: Okay, in that case the default time zone should be okay. Personally I would *explicitly* use that though, to make it clear that it's not just been overlooked. – Jon Skeet Oct 16 '11 at 07:31
  • Thanks for pointing this out. You are very right about the time zone if serving for worldwide purpose. – Clark Bao Oct 16 '11 at 10:18