tags:

views:

1295

answers:

5

I have a list of Date objects, and a target Date. I want to find the date in the list that's nearest to the target date, but only dates that are before the target date.

Example: 2008-10-1 2008-10-2 2008-10-4

With a target date of 2008-10-3, I want to get 2008-10-2

What is the best way to do it?

+2  A: 

I currently use the following method, but I'm not sure it's the most effective one, because this assumes an already sorted list, and (potentially) iterates over every single date in the list.

private Date getDateNearest(List<Date> dates, Date targetDate){
  for (Date date : dates) {
    if (date.compareTo(targetDate) <= 0) return date;
  }

  return targetDate;
}
Sietse
+1  A: 
private Date getDateNearest(List<Date> dates, Date targetDate){
 return new TreeSet<Date>(dates).lower(targetDate);
}

Doesn't require a pre-sorted list, TreeSort fixes that. It'll return null if it can't find one though, so you will have to modify it if that's a problem. Not sure of the efficency either :P

Keeg
This will cost the price of sorting the list nlog(n) then looking up the element in the list (log(n) from treesort documentation) and all that only to throw the ordered set out. (note that a set doesn't support duplicates, it doesn't matter here but it could bite elsewhere)
Jean
+1  A: 
Jean
+1  A: 

Although the answer from Keeg is valid in 1.6 in 1.5 there is no method lower() (We're unfortunate to develop against 1.5 :-( )

this one works in 1.5

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.TreeSet;

public class GetNearestDate {

  public static void main( String[] args ) throws ParseException {

    final SimpleDateFormat simpleDateFormat = new SimpleDateFormat( "dd.MM.yyyy HH:mm:ss" );

    List< Date > otherDates = Arrays.asList( new Date[]{
      simpleDateFormat.parse( "01.01.2008 01:00:00" ) ,
      simpleDateFormat.parse( "01.01.2008 01:00:02" ) } );
    System.out.println( simpleDateFormat.parse( "01.01.2008 01:00:00" ).equals(
      get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:01" ) ) ) );
    System.out.println( simpleDateFormat.parse( "01.01.2008 01:00:02" ).equals(
      get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:03" ) ) ) );
    System.out.println( null == get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:00" ) ) );
  }

  public static Date get( List< Date > otherDates , Date dateToApproach ) {
    final TreeSet< Date > set = new TreeSet< Date >( otherDates );
    set.add( dateToApproach );
    final ArrayList< Date > list = new ArrayList< Date >( set );
    final int indexOf = list.indexOf( dateToApproach );
    if ( indexOf == 0 )
      return null;
    return list.get( indexOf - 1 );
  }

}
dhiller
why use a treeset at all ? otherDates.add(datetoapproach); Collection.sort(ortherDate); indexOf magic and remove dateToApproach ...
Jean
well, first approach that came to my mind in the coffee break, although i'm sure, that Collections.sort would also work ;-)
dhiller
A: 

Have you looked at the JodaTime API? I seem to recall a feature like this being available.

Aidos