Android Question DateTime Dialog Arithmetic

RichardN

Well-Known Member
Licensed User
Longtime User
I am struggling with the time values that come out of the TimeDialog. It seems I can determine the interval between two absolute values, I can also add those intervals to another absolute value and get the correct result. My problem is that I am unable to display an interval (HH:mm) derived from two other values. The last line of the code does not give the correct value. I tried looking at the DateUtils but I don't see anything that helps.

Can anyone provide a correct solution please?

DateTime Arithmetic:
Sub Activity_Create(FirstTime As Boolean)
    
    DateTime.TimeFormat = "HH:mm"
    Dim td As TimeDialog   
    td.Is24Hours = True
    
    Dim StartTime,FinishTime, TotalTime, EachPeriod As Long
    
    td.Show("Enter Start Time","Start Time","OK","Cancel","",Null)
    Dim StartTime As Long = td.TimeTicks
    
    
    td.Show("Enter Finish Time","Start Time","OK","Cancel","",Null)
    FinishTime = td.TimeTicks
    
    TotalTime = FinishTime - StartTime
    EachPeriod = TotalTime / 3
    
    Dim FirstPeriodStarts, SecondPeriodStarts, ThirdPeriodStarts As Long
    
    FirstPeriodStarts = StartTime
    SecondPeriodStarts = FirstPeriodStarts + EachPeriod
    ThirdPeriodStarts = SecondPeriodStarts + EachPeriod
    
    Log(DateTime.Time(StartTime))                         'These values all correct
    Log(DateTime.Time(SecondPeriodStarts))
    Log(DateTime.Time(ThirdPeriodStarts))
    Log(DateTime.Time(FinishTime))
    
    Log(DateTime.Time(TotalTime))                       'Does not work!
    
End Sub
 

emexes

Expert
Licensed User
display an interval (HH:mm) derived from two other values
TotalTime and EachPeriodTime intervals are in milliseconds, so if you divide them by 60000 (1 minute = 60 seconds x 1000 ms) it will give you the time intervals in minutes and if you divide them by 3600000 (1 hour = 60 minutes x 60 seconds x 1000 ms) it will give you the time intervals in hours (eg 1.1 = 1 hour 6 minutes).

The easiest way to format them as HH:MM is probably to add midnight of an arbitrary (but non-daylight-savings-shift) date to the time interval, and use just the time portion of the formatted result.

Or you could do it "manually" eg something like:
B4X:
Dim MM As Int = TotalTime / 60000    'I am pretty certain that integer division rounds down
Dim HH As Int = MM / 60
MM = MM - HH * 60

Dim HHMM as String = NumberFormat(HH, 2, 0) & ":" & NumberFormat(MM, 2, 0)
 
Last edited:
Upvote 0

RichardN

Well-Known Member
Licensed User
Longtime User
I went for a different solution. In my application using DateUtils.PeriodBetween(TimeStart,TimeEnd) and then formatting the result proved easier (see below)

Unfortunately when trying to input two times (in my case always within 24 hours of each other) the Time Dialog outputs an absolute figure. So if you want to determine the time difference between 00:00 and 08:30 it is fairly easy. It gets more complicated when you ask for 23:30 to 09:00 because the start-to-finish calculation gives a negative result (remember both dialog outputs are TODAY). The logic of figuring this out to work in all circumstances will drive you round the bend!

Calculating a time interval period:
Sub TimeDifference(TimeStart As Long, TimeEnd As Long) As String
    
    If TimeEnd < TimeStart Then TimeEnd = TimeEnd + DateTime.TicksPerDay     'Correct end-time to the next day if less
    
    Dim pd As Period
    pd = DateUtils.PeriodBetween(TimeStart,TimeEnd)
    
    Dim hrs As Int = pd.Hours
    Dim mins As Int = pd.Minutes
    
    Return NumberFormat2(hrs,2,0,0,False) & ":" & NumberFormat2(mins,2,0,0,False)
    
End Sub
 
Upvote 0

RichardN

Well-Known Member
Licensed User
Longtime User
As in the subroutine above:

B4X:
If TimeEnd < TimeStart Then TimeEnd = TimeEnd + DateTime.TicksPerDay     'Correct end-time to the next day if less
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
If TimeEnd < TimeStart Then TimeEnd = TimeEnd + DateTime.TicksPerDay 'Correct end-time to the next day if less
If you use the DateUtils.PeriodBetween approach, you have to also include the date component in the calculation as the parameters have to reflect an instance of date/time.
In your calculations, you are adding a day's ticks when the time difference is negative to come up with a positive time differential, but what happens when you are dealing with daylight savings time, your calculations will be off by 1 hour, if say, you use: 23:30 and 9:00. Your calculations are ok when the start time is less than the end time.
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
subroutine above:
Here is what I think a sub in line with what you are doing that would work even with DST. If it does not fit in your scheme and scenario, just toss it:
B4X:
Log(TimeDifference("23:30", "9:00"))
Log(TimeDifference("11:30", "13:00"))


Sub TimeDifference(TimeSart As String, TimeEnd As String) As String
    DateTime.TimeFormat = "HH:mm"
    Dim t1 As Long = TimeSart.SubString2(0, TimeSart.IndexOf(":"))*DateTime.TicksPerHour
    Dim t2 As Long = TimeEnd.SubString( TimeEnd.IndexOf(":")+1)*DateTime.TicksPerMinute
    
    If t2 < t1 Then 'Correct end-time to the next day if less
        DateTime.DateFormat = "yyyy-MM-dd"   'or whatever format you normally use 
        Dim d2 As String = DateTime.date(DateTime.Now)   'today
        Dim d1 As String = DateTime.Date(DateTime.Add(DateTime.Now ,0,0,-1))      'yesterday
        
        DateTime.DateFormat = "yyyy-MM-dd HH:mm"
        t1=DateTime.DateParse(d1 & " " & TimeSart)
        t2=DateTime.DateParse(d2 & " " & TimeEnd)        
    End If
    
    Dim pd As Period
    pd = DateUtils.PeriodBetween(t1,t2)  
    Return $"$2.0{pd.Hours}:$2.0{pd.Minutes}"$
End Sub
 
Upvote 0
Top