Android Code Snippet [B4X] Calculating the next scheduled time

Name: Find the next scheduled time.

Description by example: You need to start a service each day at 5 am, 6:30 am and 8 pm. You need to find the ticks values of the next scheduled time, either today or tomorrow if it is after 8pm.

B4X:
Dim t As Long = FindNextTime(Array As Double(5, 6.5, 20))
Log($"Next time is: $DateTime{t}"$)

Sub FindNextTime(Times As List) As Long
   Times.Sort(True)
   For Each st As Double In Times
     If SetHours(st) > DateTime.Now Then
       Return SetHours(st)
     End If
   Next
   Return DateTime.Add(SetHours(Times.Get(0)), 0, 0, 1)
End Sub

Sub SetHours(st As Double) As Long
  Dim hours As Int = Floor(st)
  Dim minutes As Int = Round(60 * (st - hours))
  Return DateUtils.SetDateAndTime(DateTime.GetYear(DateTime.Now), _
  DateTime.GetMonth(DateTime.Now), DateTime.GetDayOfMonth(DateTime.Now), hours, minutes, 0)
End Sub
 
Last edited:

somed3v3loper

Well-Known Member
Licensed User
Longtime User
And if I need for example 3:17
Should I pass 3.28 ?
I do not think it is very accurate
 

somed3v3loper

Well-Known Member
Licensed User
Longtime User
B4X:
FindNextTime(Array As Double(12+01/60,3+00/60))
Can some one explain why does this code return 3:00 ?
When time is before both
 

Myr0n

Active Member
Licensed User
Longtime User
B4X:
FindNextTime(Array As Double(12+01/60,3+00/60))
Can some one explain why does this code return 3:00 ?
When time is before both

What time is it at your place?
 

Myr0n

Active Member
Licensed User
Longtime User
;)

10pm = 22hrs
 

somed3v3loper

Well-Known Member
Licensed User
Longtime User
;)

10pm = 22hrs
Right but shouldn't FindNextTime choose 12:01 which is 00:01 ?
Why did it skip 12 and chose 03:00 ? Aren't 12AM and 03AM supposed to be next day and 12AM is first ?'

Sorry for my stupid mistake :)
To explain : I thought 12 is like when we say 10 or 9 or any AM time
I should've typed 00:01
 
Last edited:

Myr0n

Active Member
Licensed User
Longtime User
Right but shouldn't FindNextTime choose 12:01 which is 00:01 ?
Why did it skip 12 and chose 03:00 ? Aren't 12AM and 03AM supposed to be next day and 12AM is first ?'

Sorry for my stupid mistake :)
To explain : I thought 12 is like when we say 10 or 9 or any AM time
I should've typed 00:01

It's ok probably you are tired o_O

We are here to help each other ;) even if we are like this o_O at a moment :)

Just remember we have only 24hrs, we would like to have more hours sometime, but we don't
 

anOparator

Active Member
Licensed User
Longtime User
How would $"$Time{t}"$ be used to launch an event?
I've tried
B4X:
Sub Service_Start(...)
If DateTime.Time(DateTime.Now) = $"$Time{t}"$ Then
CallSub(Main, "Label2_Click")
End If
End Sub
among other things but I need help from there. This
calculate snippet is very handy.
Thanks in advance
edit:
Just found 'Comparing the system time as a string, Jan. 2014'.
Am wondering, Since this tracks the System time, is it Not heavy on the CPU.
 
Last edited:

anOparator

Active Member
Licensed User
Longtime User
How would $"$Time{t}"$ be used to launch an event?
I've tried
B4X:
Sub Service_Start(...)
If DateTime.Time(DateTime.Now) = $"$Time{t}"$ Then
CallSub(Main, "Label2_Click")
End If
End Sub
among other things but I need help from there. This
calculate snippet is very handy.
Thanks in advance
edit:
Just found 'Comparing the system time as a string, Jan. 2014'.
Am wondering, Since this tracks the System time, is it Not heavy on the CPU.
B4X:
Dim now = DateTime.Time(DateTime.Now) As String

Sub Service_Start(...)
If now => $"$Time{t}"$ Then
Log ("The current time is: " & now)
Log("Next start time is : "  $Time{t}"$
      CallSubDelayed(Main, "Button1_  Click")
Else
       Log(" the time now is: " & now)
Log("the next start time is : " $Time{t}"$)
CallSubDelayed(Main, "Button2_Click")
End If
End Sub
Now, to launch the event at $" $Time{t}"$
 
Last edited:

Declan

Well-Known Member
Licensed User
Longtime User
I am using a slightly edit version of the above examples:
I need to CallSubDelayed at 7:00am, 2:00pm and 8:00pm.
My Service:
B4X:
#Region  Service Attributes
    #StartAtBoot: True
    #ExcludeFromLibrary: True
#End Region

Sub Process_Globals
    Dim t As Long = FindNextTime(Array As Double(7, 14, 20))
    Log($"Next time is: $Time{t}"$)   
    Dim now = DateTime.Time(DateTime.Now) As String
End Sub

Sub Service_Create

End Sub

Sub Service_Start (StartingIntent As Intent)
    If now = $"$Time{t}"$ Then
        Log ("The current time is: " & now)
        Log($"Next time is: $Time{t}"$)
    '        CallSubDelayed(Main, "ActionPop")
    Else
        Log(" the time now is: " & now)
        Log($"Next time is: $Time{t}"$)
    '     Do Nothing
    End If

End Sub

Sub FindNextTime(Times As List) As Long
   Times.Sort(True)
   For Each st As Double In Times
     If SetHours(st) > DateTime.Now Then
       Return SetHours(st)
     End If
   Next
   Return DateTime.Add(SetHours(Times.Get(0)), 0, 0, 1)
End Sub

Sub SetHours(st As Double) As Long
   Dim hours As Int = Floor(st)
   Dim minutes As Int = 60 * (st - hours)
   Return DateUtils.SetDateAndTime(DateTime.GetYear(DateTime.Now), _
       DateTime.GetMonth(DateTime.Now), DateTime.GetDayOfMonth(DateTime.Now), hours, minutes, 0)
End Sub

Sub Service_TaskRemoved
    'This event will be raised when the user removes the app from the recent apps list.
End Sub

'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub Service_Destroy

End Sub

I have a problem with this:
B4X:
Sub Service_Start (StartingIntent As Intent)
    If now = $"$Time{t}"$ Then
        Log ("The current time is: " & now)
        Log($"Next time is: $Time{t}"$)
    '        CallSubDelayed(Main, "ActionPop")
    Else
        Log(" the time now is: " & now)
        Log($"Next time is: $Time{t}"$)
    '     Do Nothing
    End If

End Sub

I receive the following error in the debug log:
B4X:
Next time is: 07:00:00
** Service (starter) Create **
** Service (starter) Start **
Error occurred on line: 24 (Starter)
java.lang.ArrayIndexOutOfBoundsException: length=2; index=2
    at anywheresoftware.b4a.debug.RDebugUtils.solveBoolean(RDebugUtils.java:134)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:708)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:337)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:247)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at b4a.example.starter.handleStart(starter.java:101)
    at b4a.example.starter.onStartCommand(starter.java:69)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3128)
    at android.app.ActivityThread.access$2100(ActivityThread.java:178)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1568)
    at android.os.Handler.dispatchMessage(Handler.java:111)
    at android.os.Looper.loop(Looper.java:194)
    at android.app.ActivityThread.main(ActivityThread.java:5637)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)
 

Myr0n

Active Member
Licensed User
Longtime User
I am using a slightly edit version of the above examples:
[/CODE]

I did a copy paste of your code to a new project, I added dbutils library to my project I ran the project and I did not have any errors.

This is my log

Next time is: 07:00:00
** Service (starter) Create **
** Service (starter) Start **
the time now is: 06:32:07
Next time is: 07:00:00
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **


Probably you are including something else in your code
 

udg

Expert
Licensed User
Longtime User
Hi all,
today I started experimenting with a reminder app, so this thread sounded a good starting point.
So far I have the Starter service that starts my Reminder service (later I'll set Starter as #StartAtBoot) which in its Service_Start has the following:
B4X:
t = FindNextTime(Array As Double(12+56/60, 12+57/60, 12+58/60, 12+59/60))

the effect is that (surprisingly) it gets started at 12:56 , 12:58 and then programmed for tomorrow at 12:56.

Could it be that rounding plays a role in "skipping" some schedules? Should we modify
B4X:
Dim minutes As Int = 60 * (st - hours)  'original
in some way?

Note: I plan to record schedule times as strings formatted as "HH:mm", so my question is rised just to better understand the original code and its eventual limits of proper usage.

udg
 
Last edited:

ilan

Expert
Licensed User
Longtime User
Ok now this is something new to me.

B4x can use an array as double as a list?
Will it work for any array?
 

udg

Expert
Licensed User
Longtime User
Hi Ilan,
from the List definition:
"Lists are similar to dynamic arrays. You can add and remove items from a list and it will change its size accordingly.
A list can hold any type of object. However if a list is declared as a process global object it cannot hold activity objects (like views).
Basic4android automatically converts regular arrays to lists. So when a List parameter is expected you can pass an array instead."


udg
 
Top