2

I'm trying to make a function which I want to only work between given time.

i.e: If startTime is "13:00" and endTime is "14:00" then every day when the user uses my app at/between this time then call the function, else do nothing.

Here's what I came across while trying to figure out but this doesn't work.


 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.UK);

       try {
           Date inTime = sdf.parse("13:00");
           Date outTime = sdf.parse("14:00");
           if (outTime != null) {
               if (isTimeAfter(inTime, outTime)) {
                   Toast.makeText(SplashScreenActivity.this, "Time validation success", Toast.LENGTH_LONG).show();
               }
               else {
                   Toast.makeText(SplashScreenActivity.this, "Exit time must be greater then entry time", Toast.LENGTH_LONG).show();
               }
           }
       } catch (ParseException e) {
           e.printStackTrace();
           Toast.makeText(SplashScreenActivity.this, "Parse error", Toast.LENGTH_LONG).show();
       }


public static boolean isTimeAfter(Date startTime, Date endTime) {
       return !endTime.before(startTime);
   }

Any help is appreciated, thanks!

UPDATE 1:

 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.UK);
       Date now = new Date(System.currentTimeMillis());

       try {
           Date inTime = sdf.parse("03:19");
           Date outTime = sdf.parse("03:21");

           if (now.after(inTime) && now.before(outTime)) {
               Toast.makeText(SplashScreenActivity.this, "Time validation success", Toast.LENGTH_LONG).show();
           } else {
               Toast.makeText(SplashScreenActivity.this, "Nope, it isn't wokring", Toast.LENGTH_LONG).show();
           }
       } catch (ParseException e) {
           e.printStackTrace();
           Toast.makeText(SplashScreenActivity.this, "Parse error", Toast.LENGTH_LONG).show();
       }
a_local_nobody
  • 7,947
  • 5
  • 29
  • 51
Steven Rõgrê
  • 165
  • 1
  • 13

2 Answers2

4

tl;dr

LocalTime start = null ;
LocalTime end = null ;
try
{
    start = LocalTime.parse( "03:19" ) ;
    end = LocalTime.parse( "03:21" ) ;
} 
catch ( DateTimeParseException e ) 
{
    … handle faulty input
}

LocalTime currentTimeOfDay = LocalTime.now( ZoneId.systemDefault() ) ;
if( 
    ( ! currentTimeOfDay.isBefore( start ) )   // "Is not before …" is a briefer way of asking "Is equal to or later than …".
    &&
    currentTimeOfDay.isBefore( end )
)
{ … within target times }
else
{ … outside target times }

Stop using Date & SimpleDateFormat

The Answer by Yoni is close to being the right solution, but continues your confusion by using java.util.Date class. Never use java.util.Date, just stop, let it go, move on.

Those legacy date-time classes are a wretched mess. Sun, Oracle, and the JCP community gave up on them years ago with the adoption of JSR 310. So should you.

You said:

i.e: If startTime is "13:00" and endTime is "14:00" then every day when the user uses my app at/between this time then call the function, else do nothing.

LocalTime

Represent your start and end times.

LocalTime start = LocalTime.of( 13 , 0 ) ;
LocalTime end = LocalTime.of( 14 , 0 ) ;

Capture the current moment as seen in a particular time zone.

ZoneId

You can assume the user wants to use the JVM’s default time zone.

ZoneId zoneId = ZoneId.systemDefault() ;

If critical, you should confirm with the user their intended time zone. Specify a real time zone name using format of Continent/Region, never the 2-4 letter pseudo-zones such as IST, EST, PST, etc.

ZoneId zoneId = ZoneId.of( "America/Edmonton" ) ;

ZonedDateTime

With the time zone issue decided, capture the current moment as seen in that zone.

ZonedDateTime now = ZonedDateTime.now( zoneId ) ;

Extract the time-of-day value from that moment.

LocalTime currentTimeOfDay = now.toLocalTime() ;

Compare LocalTime objects

Compare with your target start-end.

Generally best to define spans of time using the Half-Open approach, where the beginning is inclusive while the ending is exclusive.

if( 
    ( ! currentTimeOfDay.isBefore( start ) )   // "Is not before …" is a briefer way of asking "Is equal to or later than …".
    &&
    currentTimeOfDay.isBefore( end )
)
{ … within target times }
else
{ … outside target times }

Parsing

If you must obtain your start and end time-of-day values by parsing text in standard ISO 8601 format where the hour is 24-hour clock (0-23) and padding zeros are utilized, then simply call LocalTime.parse method. No need to specify a formatting pattern. No need to specify a Locale.

LocalTime start = LocalTime.parse( "03:19" ) ;
LocalTime end = LocalTime.parse( "03:21" ) ;

To protect against faulty inputs, trap for DateTimeParseException.

LocalTime start = null ;
LocalTime end = null ;
try
{
    start = LocalTime.parse( "03:19" ) ;
    end = LocalTime.parse( "03:21" ) ;
} 
catch ( DateTimeParseException e ) 
{
    … handle faulty input
}

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • While your solution seems great the issue is compatibility. "LocalTime" requires API 26+ and my app supports devices running 21, hence the reason why I'm looking for a method that can run on all devices. – Steven Rõgrê Feb 24 '21 at 22:43
  • @StevenRõgrê The latest versions of Android tooling bring most of the *java.time* functionality to earlier Android via “API desugaring”. – Basil Bourque Feb 25 '21 at 03:08
  • I did mention in my anwser to use LocalTime, but you are correct it might be confusing as I put the Date version first. I've updated my anwser and only left the LocalTime example to avoid any confustion. It's also the way it should be used. – Yoni Feb 25 '21 at 08:31
1

The problem is you are comparing your 2 fixed dates. You check that 13:00 is after 14:00. Which is always going to be true.

What you want to compare to is the current time. You want the current time to be after the start time and before the end time.

As of java 8, it's also recommended to make use of LocalTime instead of Date. This solves a lot of issues you might encounter with timezones and such.

To get the current time, you could make use of LocalTime.now(). The code snippet looks something like this then

LocalTime now = LocalTime.now();
now.isAfter(startTime) && now.isBefore(endTime);
Yoni
  • 1,370
  • 7
  • 17