-1

i have 5 times example:

4:21 AM

12:1 PM

3:32 PM

6:30 PM

8:4 PM

and the current time is

10:4 AM

I want to do a comparison What is the next time closest to the current time

the result will be:

NEXT TIME : 12:1 PM

Black.JAC
  • 25
  • 1
  • 6

3 Answers3

1

You can turn a time to a date object and then into a long (milliseconds since Jan 1, 1970), and calculate the difference in milliseconds

long diffInMs = currentDate.getTime() - anotherDate.getTime();

And then check which has the smallest difference, but being also equal to or greater than zero. Negative difference means old date and you want the next closest date

To convert the times to dates check this: https://stackoverflow.com/a/8826392/2597775

Basically, it says:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

String inputString = "00:01:30.500";

Date date = sdf.parse("1970-01-01 " + inputString);
sebasira
  • 1,739
  • 1
  • 22
  • 41
  • no bro you don't understand me.. wait me i will share you photo – Black.JAC Sep 12 '18 at 17:29
  • both of the answers exactly answered your question, convert to epoch time, subtract and compare them. They were really nice to give you the code or even the method instead of pseudo code. Your question showed that you haven't done anything toward the problem yet. – Toan Le Sep 12 '18 at 21:22
1

Update: Added logic to rollover at midnight, and added alternative using binary search.

First parse the inputs to a time in milliseconds of the day, by parsing the time string as if it's in UTC time zone.

Then find the smallest value on or after the "current" value, or just smallest value if no value is on or after the "current" value (rollover).

Example:

public static String findNext(String current, String... times) throws ParseException {
    SimpleDateFormat fmt = new SimpleDateFormat("hh:mm a");
    fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
    long currentMillis = fmt.parse(current).getTime();
    long bestMillis = 0, minMillis = 0;
    String bestTime = null, minTime = null;
    for (String time : times) {
        long millis = fmt.parse(time).getTime();
        if (millis >= currentMillis && (bestTime == null || millis < bestMillis)) {
            bestMillis = millis;
            bestTime = time;
        }
        if (minTime == null || millis < minMillis) {
            minMillis = millis;
            minTime = time;
        }
    }
    return (bestTime != null ? bestTime : minTime);
}

Test

System.out.println(findNext("10:4 AM",
                            "4:21 AM", "12:1 PM", "3:32 PM", "6:30 PM", "8:4 PM"));
System.out.println(findNext("10:4 PM",
                            "4:21 AM", "12:1 PM", "3:32 PM", "6:30 PM", "8:4 PM"));

Output

12:1 PM
4:21 AM

If the given times are guaranteed to already be sorted, then it can be done with a binary search:

public static String findNext(String current, String... times) {
    SimpleDateFormat fmt = new SimpleDateFormat("hh:mm a");
    fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
    int idx = Arrays.binarySearch(times, current, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            try {
                return fmt.parse(s1).compareTo(fmt.parse(s2));
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        }
    });
    if (idx < 0)
        idx = -idx - 1;
    return times[idx < times.length ? idx : 0];
}
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Calling `findNext` with `10:4 PM` will return `null`. Maybe it should wrap around and return `4:21 AM`, not sure. If so, adding `if(bestTime == null) return times[0];` at the end of the method would work, assuming the reference times are sorted. – RaffleBuffle Sep 12 '18 at 17:49
  • @SirRaffleBuffle But if `times` values are already sorted, then a binary search would be much better. No such assumption can be made, since question didn't specifically say so. Just because sample data is sorted, doesn't mean actual data will be. – Andreas Sep 12 '18 at 18:01
  • @SirRaffleBuffle it's true!! i change the time of phone to **9:4 PM** and the function return **NULL** !!!!!!!! why ?? it was supposed to show me then next time ( **4:21 AM** ) – Black.JAC Sep 13 '18 at 05:33
  • this code for VB.NET and it work 100% can you convert it to JAVA android – Black.JAC Sep 13 '18 at 06:08
  • well. bro @Andreas i will test and back for you.. now please can you add array-names for these 5 times 4:21 AM **- Morning** 12:1 PM **- Day** 3:32 PM **- Sunset** 6:30 PM **- Night** 8:4 PM **- Midnight** – Black.JAC Sep 13 '18 at 20:05
  • i mean i need give 5 names for this 5 times,,, to show it in result `System.out.println(findNext("10:4 AM", "4:21 AM", "12:1 PM", "3:32 PM", "6:30 PM", "8:4 PM")); `Output: 12:1 PM - Morning – Black.JAC Sep 13 '18 at 20:13
  • @Black.JAC How could I do that when I don't know what time frame e.g. **Sunset** covers? Since sunset today is at 7:47 PM where I am, why would 3:32 PM be considered sunset? – Andreas Sep 13 '18 at 20:15
  • @Andreas bro this names **(Morning, sunset.....etc)** just for example, you can add any names **( John, Mark, Smith, Andreaa, Beghy )** – Black.JAC Sep 13 '18 at 20:19
  • @Black.JAC Even worse. Since I see no names *mentioned in the question*, should I run a random text generator to just label each time something arbitrary? Maybe you should create another question, providing relevant information needed to answer your new question. – Andreas Sep 13 '18 at 20:20
  • @Andreas no no bro.. don't make generator or random names! i need names are fixed put names for this five 5 are ( John , Mark , Smith , Andreaa , Beghy ) – Black.JAC Sep 13 '18 at 20:29
  • @Black.JAC So you're saying that input is not a list of 5 strings with those time values, but a list of 5 objects with `time` and `name` fields, and that you want the result to the the *object* after the "current" time, not the `time` string? If so, your question should have said so. – Andreas Sep 13 '18 at 20:50
  • Maybe I did not explain clearly but I meant I wanted the final result so **NEXT TIME: Morning (4:21 AM) after (6) Hour And (17) Minutes.** – Black.JAC Sep 13 '18 at 21:27
  • @Black.JAC So what is stopping you from modifying the code in this answer to instead provide input as objects, not string, and searching those? – Andreas Sep 13 '18 at 21:48
  • @Andreas how!! i don't know how to do that – Black.JAC Sep 14 '18 at 04:39
-1

i specially design a function to solve your problem , use function as you needed.

it will works for you surely.

/**
 *
 * @author Niravdas
 */
public class TimeDiff {
    String[] times = { "04:21 AM", "12:01 PM", "03:32 PM", "06:30 PM", "08:04 PM"};
    String findingafter="10:04 AM";

    public TimeDiff()
    {
        int time=nextTimeArrayIndex(findingafter,times);
        if(time>=0)
            System.out.println("NEXT TIME: "+times[time]);
    }

    public static void main(String argv[])
    {
        new TimeDiff();
    }
    int  nextTimeArrayIndex(String Finding,String[] fromArray)
    {
        int shortest=-1,shortestsec=-1;
        long minsecdif=(24*60*60+1),minsec=(24*60*60+1);
        int hr=Integer.parseInt(Finding.substring(0, 2));
        int min=Integer.parseInt(Finding.substring(3, 5));
        long seconds = convertToSec(hr, min, 0, Finding.substring(Finding.length()-2));
        System.out.println("seconds :" + seconds);
          for(int i=0;i<fromArray.length;i++)
          {
              int temphr=Integer.parseInt(fromArray[i].substring(0, 2));
              int tempmin = Integer.parseInt(fromArray[i].substring(3,5));
              long tempsec = convertToSec(temphr, tempmin, 0, fromArray[i].substring(Finding.length()-2));
              System.out.println("Compared to :" + tempsec);
              if((tempsec - seconds) > 0 && minsecdif > (tempsec - seconds))
              {
                  minsecdif = (tempsec - seconds);
                  shortest = i;
              }
              if(minsec > tempsec)
              {
                  minsec = tempsec;
                  shortestsec=i;
              }
          }
          if(shortest >=0)
          {
              return  shortest;
          }
          else
          {
              return  shortestsec;
          }


    }
    long convertToSec(int hr,int min,int sec,String AMorPM)
    {
        if(hr==12)
        {
               hr=0;
        }
        long secs = (hr*60*60) + (min*60) + (sec*60);
        if(AMorPM.equalsIgnoreCase("PM"))
        {
            secs += (12*60*60);
        }
        return secs;

    }     

}

i hope it will solve your problem.

Niravdas
  • 371
  • 2
  • 19