0

How do I check between two time in android? I have opening time and closing time, I want to check if the closing time has passed using the specific country timezone.

 public void timeElapse(String start, String end, String tz){
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm aa", Locale.getDefault());
        SimpleDateFormat sdf = new SimpleDateFormat("hh:mm\\aa", Locale.getDefault());
        try {
            sdf.setTimeZone(tzs);
            Date currentTimeDate = sdf.parse(start);
            Date endTimeDate = sdf.parse(end);
            int a = currentTimeDate.compareTo(endTimeDate); // false / current time has not passed end time.
            int b = endTimeDate.compareTo(currentTimeDate); // true / end time has passed current time.

            Log.e("timeElapse", "("+end+") A = " + a + " B = " + b);
        } catch (ParseException ignored) {

        }
    }

Second attempt

public void timeElapse(String start, String end, String tz){
    SimpleDateFormat sdf = new SimpleDateFormat("hh:mm\\aa", Locale.getDefault());
    try {
        TimeZone tzs = TimeZone.getTimeZone(tz);
        sdf.setTimeZone(tzs);
        long currentTimeDate = sdf.parse(start).getTime();
        long endTimeDate = sdf.parse(end).getTime();
        if(currentTimeDate>endTimeDate){
            Log.e("timeElapse", "Time has passed");
        }else{
            Log.e("timeElapse", "You are on time");
        }
    } catch (ParseException ignored) {

    }
}

Usage

timeElapse("10:00AM", "10:00PM", "Asia/Kuala_Lumpur");
timeElapse("10:00AM", "12:00PM", "Asia/Kuala_Lumpur");
timeElapse("11:30AM", "05:00PM", "Asia/Kuala_Lumpur");
timeElapse("10:00AM", "01:00AM", "Asia/Kuala_Lumpur");

My code doesn't work. I get error java.text.ParseException: Unparseable date: "10:00AM"

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Peter
  • 1,860
  • 2
  • 18
  • 47
  • Generally you keep the times in a single time zone (usually UTC) and convert from the current time zone to UTC for the comparison. Keeping all the data in a single timezone makes the code easier to understand and reduces the chance of issues in the future. – Gabe Sechan Aug 29 '21 at 16:18
  • @GabeSechan please can you show example? – Peter Aug 29 '21 at 16:32
  • 1
    As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends. See if you either can use [desugaring](https://developer.android.com/studio/write/java8-support-table) or add [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project, in order to use java.time, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Aug 29 '21 at 17:19
  • Do your attempts work as expected? If you are getting any unexpected results, please spell them out for us. – Ole V.V. Aug 29 '21 at 17:21
  • @OleV.V. my code doesn't work I get error `java.text.ParseException: Unparseable date: "10:00AM"` – Peter Aug 29 '21 at 17:25
  • @Peter That’s crucial information. It belongs in the question, not in a comment. – Ole V.V. Aug 29 '21 at 17:40
  • How can the start be 10 AM and the end 1 AM? – Ole V.V. Aug 29 '21 at 18:26

1 Answers1

2

java.time through desugaring

Consider using java.time, the modern Java date and time API, for your time work.

Code has been edited after reading the question more closely.

private static final DateTimeFormatter TIME_PARSER
        = DateTimeFormatter.ofPattern("hh:mma", Locale.ENGLISH);

public static void timeElapse(String start, String end) {
    LocalTime currentTime = LocalTime.parse(start, TIME_PARSER);
    LocalTime endTime = LocalTime.parse(end, TIME_PARSER);
    if (currentTime.isAfter(endTime)) {
        System.out.println("Time has passed");
    } else {
        System.out.println("You are on time");
    }
}

Isn’t the code pretty self-explanatory? That’s one thing I find nice about java.time. And has been hinted in the comments, we need no time zone (except for corner cases). So I left out the third parameter. Let‘s try it out with your examples:

    timeElapse("10:00AM", "10:00PM");
    timeElapse("10:00AM", "12:00PM");
    timeElapse("11:30AM", "05:00PM");
    timeElapse("10:00AM", "01:00AM");

Output is:

You are on time
You are on time
You are on time
Time has passed

Doesn’t time zone matter? If your times fall in the fall back where clocks are turned backward and the same clock hours repeat, we’re at a loss to tell which is earlier. My code above does not take this corner case into account, and to do so, we would need to know the date too.

Original code

private static final DateTimeFormatter TIME_PARSER
        = DateTimeFormatter.ofPattern("hh:mma", Locale.ENGLISH);

public static void timeElapse(String start, String end, String tz){
    LocalTime startTime = LocalTime.parse(start, TIME_PARSER);
    LocalTime endTime = LocalTime.parse(end, TIME_PARSER);
    LocalTime now = LocalTime.now(ZoneId.of(tz));
    if (now.isBefore(startTime)) {
        System.out.println("Not open yet");
    } else if (now.isAfter(endTime)) {
        System.out.println("Time has passed");
    } else {
        System.out.println("You are on time");
    }
}

Isn’t the code pretty self-explanatory? That’s one thing I find nice about java.time. Let‘s try it out with your examples:

    timeElapse("10:00AM", "10:00PM", "Asia/Kuala_Lumpur");
    timeElapse("10:00AM", "12:00PM", "Asia/Kuala_Lumpur");
    timeElapse("11:30AM", "05:00PM", "Asia/Kuala_Lumpur");
    timeElapse("10:00AM", "01:00AM", "Asia/Kuala_Lumpur");

I ran this code near 2:15 AM in Malaysia, so as expected the output was a bit dull:

Not open yet
Not open yet
Not open yet
Not open yet

Let’s also try:

    timeElapse("12:00AM", "03:00AM", "Asia/Kuala_Lumpur");
    timeElapse("01:00AM", "02:00AM", "Asia/Kuala_Lumpur");
You are on time
Time has passed

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

What went wrong in your code?

You have got a backslash between the minutes and the AM/PM marker in your format pattern string: "hh:mm\\aa". This requires a backslash in your time strings, but they are like "10:00AM", that is, without any backslash. I believe that this caused your ParseException. There may also be an issue with specifying Locale.getDefault() for the formatter. AM and PM are hardly used in other languages than English but do have other names (texts) in some languages. You are requiring the text to be in the default language for your JVM (and your device).

Also be aware that if you wanted to compare the parsed times to the time now, that is easy with java.time. It is not with Date and SimpleDateFormat. SimpleDateFormat parses each string into the specified time of day on January 1, 1970, so comparing with the time now will not make sense.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • This is great, but have one thing I notice `timeElapse("10:00AM", "05:00AM", "Asia/Kuala_Lumpur")`, when opening around `10AM` and closing around `5AM`, it always show not open. Is there any way I can check if the closing time is next day? – Peter Aug 29 '21 at 19:18
  • 1
    @Peter It’s just a little bit more complicated. See for example [Check if a given time lies between two times regardless of date](https://stackoverflow.com/questions/17697908/check-if-a-given-time-lies-between-two-times-regardless-of-date). And search for more if you need more. – Ole V.V. Aug 29 '21 at 19:22