Accurate Time Math For VB Including Division - vb.net

The Problem I am having is with doing time mathematics in VB.
I am currently volunteering at a school and Helping with their Before/Aftercare system
So the goal for before care would be to take a time stamp and compare it to the time school starts that day and find how many half hours are in that given time difference rounding up to the nearest half hour.
For Example. A child Gets to Morning Care at 7:36 School starts at 9:30.
What I want my program to do is
9:30-7:36 = 1 hour 54 minutes
1 hour 54 minutes / 30 minutes = 3.XXX
round that up to 4 multiply by price per hour and my cost is 12
The code I have seems to be off by 15 minutes. I will display the code I use below. Please help by letting me know if there are logic issues or if the method chosen for time math is Poor
'Creating all my variables including half constant half variable times to
compare against
Dim DateIn As DateTime = System.DateTime.Now
Dim Month As Integer = Microsoft.VisualBasic.DateAndTime.Month(DateIn)
Dim Year As Integer = Microsoft.VisualBasic.DateAndTime.Year(DateIn)
Dim Day As Integer = Microsoft.VisualBasic.DateAndTime.Day(DateIn)
Dim DateMorning As New Date(Year, Month, Day, 7, 30, 0)
Dim DateSchoolStart As New Date(Year, Month, Day, 9, 30, 0)
Dim halfHour As System.TimeSpan = New TimeSpan(0, 0, 30, 0)
Dim ticksHalfHour As Long = halfHour.Ticks
Dim count As Integer
Dim cost As Integer
'Portion of a function that calculates cost if the time is in the right zone
If (DateIn >= DateMorning And DateIn < DateSchoolStart) Then
CareTime = DateSchoolStart.Subtract(DateIn)
Dim CareTicks As Long = CareTime.Ticks
count = ReturnCount(CareTicks, ticksHalfHour)
cost = count * price
WriteReport(cost, Year, Month, Day, name)
MessageBox.Show("Welcome to morning care " & name & "!")
Return cost
End If
' function that divides the two longs and does a mod calculation
Function ReturnCount(ByVal tick1 As Long, tick2 As Long) As Integer
If (tick1 Mod tick2 = 0) Then
count = tick1 / tick2
Return count
Else
count = 1 + (tick1 / tick2)
Return count
End If
End Function
I believe this is the relevant portion of the code. If you see a flaw in my logic or have a simpler way of achieving my goal your input would be much appreciated.

Related

Calculate difference in month and years between two date in vb.net

i have a question for you, my first one. Im trying to calculate the difference in years and months between 2 dates using vb.net. I'm just started working with vb and im new to programming, so i might sound really dumb. This is my expected output:
date1 1/6/2015 date2 1/1/2019 3 years 7 months and so on.
if date2 is < than data1 then the program should return a negative value in months/years. day number are irrelevant, i just want to know how many months/years.
This is the code that i found and it works if data1 is > than data2 but doesn't if data2 is > than data1.
Dim data1 As DateTime = ("1/3/2021") # working examples
Dim data2 As DateTime = ("1/5/2022")
Public Shared Function GetDateSpanText(fromDate As DateTime, toDate As DateTime) As String
Dim years As Integer = 0, months As Integer = 0, days As Integer = 0
Do Until toDate.AddYears(-1) < fromDate
years += 1
toDate = toDate.AddYears(-1)
Loop
Do Until toDate.AddMonths(-1) < fromDate
months += 1
toDate = toDate.AddMonths(-1)
Loop
Do Until toDate.AddDays(-1) < fromDate
days += 1
toDate = toDate.AddDays(-1)
Loop
Return String.Format("{0} Year(s) {1} Month(s) {2} Day(s)", years, months, days)
End Function
how can i make it work the other way? there are functions that can do this?
thanks to everyone
The simplest way to deal with dates and time intervals is using the TimeSpan struct.
Take a look at this snippet:
Sub Test()
Dim startDate As New Date(2022, 8, 17)
Dim endDate As New Date(2023, 10, 15)
Dim timeBetween As TimeSpan = endDate - startDate ' TimeSpan objects represents a time interval
Dim yearsBetween As Double = timeBetween.TotalDays / 365
Dim monthsBetween As Double = yearsBetween * 12
' Try using simplified string interpolation, like this:
Console.WriteLine($"Years between: {yearsBetween}; months between: {monthsBetween}") ' Note the $ sign at string beginning
End Sub
Using TimeSpan is conveninent because it gives you access to wathever time fraction you want to use:
timeBetween.TotalDays ' Represents the whole time interval in days (double)
timeBetween.TotalHours ' Represent the whole time interval in hours (double)
timeBetween.Days ' Represents the days part only (integer)
As you may guess, you need to substract the oldest date from the newest date to get a positive TimeSpan.
Note: the TimeSpan struct can not provide you .TotalMonths or .TotalYears methods because months and years are not always of the same length (months can vary between 28 and 31 days and years can be 365 or 366 days). That's why you need to do the calculation yourself like in the code I posted.
This is a perfect example of why you need to think logic first and code second. You already have all the code you need. All you have to do is check the relative order of the dates and switch them before the calculation if necessary, then negate the numbers at the end if you switched them. All the rest of the code is exactly the same. If you'd thought about the logic first then you wouldn't have had to ask the question at all.
Public Shared Function GetDateSpanText(fromDate As DateTime, toDate As DateTime) As String
Dim swapped = False
If fromDate > toDate Then
Dim temp = fromDate
fromDate = toDate
toDate = temp
swapped = True
End If
Dim years As Integer = 0, months As Integer = 0, days As Integer = 0
Do Until toDate.AddYears(-1) < fromDate
years += 1
toDate = toDate.AddYears(-1)
Loop
Do Until toDate.AddMonths(-1) < fromDate
months += 1
toDate = toDate.AddMonths(-1)
Loop
Do Until toDate.AddDays(-1) < fromDate
days += 1
toDate = toDate.AddDays(-1)
Loop
If swapped Then
years = -years
months = -months
days = -days
End If
Return String.Format("{0} Year(s) {1} Month(s) {2} Day(s)", years, months, days)
End Function

wrong value converting integer data to date on vb.net

I have a series of data that I get from an access control device, the data is the following:
Cardno, Pin, Verified, DoorID, EventType, InOutState, Time_second
3189959,13978762,4,2,0,0,676132501
Time_second(676132501) should be "2021-01-14 14:58:54.000"
this is my code
Dim sDate As Integer = 676132501
Dim dtDateTime As System.DateTime = New DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)
dtDateTime = dtDateTime.AddSeconds(sDate).ToLocalTime()
the value returned is : #6/5/1991 10:35:01 AM#, please help
A quick google search of those field names you gave in the question landed on a technical spec doc of something called "PullSDK", which appears to be what you're using. I won't link to it here because I could not find an official source.
The doc gives a formula for decoding these timestamps. Translated to VB.Net it is as follows:
Function DecodeDateTime(ByVal t As Integer) As DateTime
Dim year, month, day, hour, minute, second As Integer
second = t Mod 60
t /= 60
minute = t Mod 60
t /= 60
hour = t Mod 24
t /= 24
day = t Mod 31 + 1
t /= 31
month = t Mod 12 + 1
t /= 12
year = t + 2000
Return New DateTime(year, month, day, hour, minute, second)
End Function
The value you gave, 676132501 is decoded as 2021-01-15 15:35:01 - which is slightly different than your stated expectation. You might want to carefully check the source of that data to verify your assumptions.
As an aside - in evaluating that formula, no amount of adding seconds to some base value would suffice. This is because they've encoded the day into a space that always has 31 values within a month - even for months with less than 31 days. That makes this encoding inefficient, as there will be some values that represent dates that don't actually exist.

Find the day given date and number of days

Am looking a function that would aid me to auto detect due date when duration period number is entered in duration textbox.Am having challenge since all the months do not end with same date number i.e. 31 as some end on 30.
NOTE: The function should be able to automatically calculate up to next year if lets say user inputs 3 while in November 2018 its means the duration period will go up January 2019
See the picture below
Dim start_date As Date = dtpStart.Value
Dim totalDays As Integer = 3 * 30
Dim ts As TimeSpan = start_date.Add(totalDays)
Dim end_date As Date = ts
I have tried the above but its giving me an error "value of type integer can not be converted to system.TimeSpan."
If i understand you correctly, if a user enters 3 you want to advance 3 times 30 days later from the start_date.
Dim start_date = dtpStart.Value
Dim end_date = start_date.AddDays(3* 30)
In terms of a function, you could have:
private function AddDays(Byval start_date as Date, Byval amount as integer) as Date
Dim end_date = start_date.AddDays(amount)
return end_date
end function
The usage would be:
Dim new_date = AddDays(dtpStart.Value, 3*30)

Calculate X amount of hrs ahead only counting 9-5 hrs

I'm trying to get a quick ETA on some pre-determined values, 16 and 40. So for example, I need my code to quickly calculate an ETA on an item if it takes 16 hours, but only count the 9-5 (8) hours per day. Obviously I'd need to include the remaining hours of that day, which I have in the code snipped below. However I'm giving myself an ofly sore head trying to work out the best way to proceed with the code. Perhaps someone's got a good idea?
Dim TargetTime as Integer = 16
Dim currentHr As Integer = current.Hour
Dim TodaysRemainingHours As Integer = 0
If currentHr >= 9 AndAlso currentHr < 17 Then
'Count remaining hours
TodaysRemainingHours = (17- currentHr)
Else
'Dont count today
TodaysRemainingHours = 0
End If
My plan is:
TargetTime - TodaysRemainingHours --- Gives the value to count
to.
Somehow calculate the hours based on 9-5 time spans only.
Display lblOutput as: "ETA: 2pm 25/11/2016"
As you can see I know how to get the vaule I need to count to, but I need some help with firstly only counting the hours in each day from 9-5 and then returning the actual hour estimated. This isn't for anything profitable, it's a personal ETA program.
Thank you topshot, your comment helped me work it out! The below code seems to work for me, I haven't identified any issues anyway. I had to make sure I wasn't counting the remaining hours in the current day if the time is past 5pm as well. Thank you.
Dim TargetTime As Integer = 16
Dim current As Datetime = DateTime.now
Dim currentHr As Integer = current.Hour
Dim TodaysRemainingHours As Integer = 0
If currentHr >= 9 AndAlso currentHr < 17 Then
'Count remaining hours
TodaysRemainingHours = (17 - currentHr)
Else
'Dont count today
TodaysRemainingHours = 0
End If
If currentHr >= 9 AndAlso currentHr < 17 Then
'Deduct todays hours from target time.
TargetTime = (TargetTime - TodaysRemainingHours)
'Display results
MsgBox("ETA: " & Now.AddDays(TargetTime / 8))
Else
'Skip todays hours and count from tomorrow morning at 9am
Dim Tomorrow As DateTime = Today.AddDays(1)
Dim TomorrowMorning As TimeSpan = new TimeSpan(09, 00, 0)
Tomorrow = Tomorrow.Date + TomorrowMorning
'Display results
MsgBox("ETA: " & Tomorrow.AddDays(TargetTime / 8))
End If

VB.NET Make a Date out of just Day

My user will typically enter some trip info including a day and month but typically they just enter the day. For example they would enter "TRIP1500/31" where the 31 is implied that its in JULY. The trip date can be at most 7 days in the past or 7 days in the future. So now what Im trying to do is guess what month that day is meant to be. So far I have:
Dim diff As Integer = CInt(tripDay) - Date.Now.Day
Select Case diff
Case 0
'same day so its probably current month
End Select
What I'm having trouble with is the other cases where the current day and the trip day overlap month-to-month. If the current day and trip day are in current month then the most difference they can be is +/-7 days but what about the other cases? Any help appreciated.
Function GetTripDate(day As Integer) As Date
Dim today As Date = Date.Today
For i As Integer = -7 To 7
Dim dt As Date = today.AddDays(i)
If dt.Day = day Then Return dt
Next
Throw New ArgumentOutOfRangeException("Invalid trip day.")
End Function
This gives you the date(incl. month) of the nearest date with the given day:
Dim maxDiffDays = 7
Dim tripDay = 31
Dim today = Date.Today
Dim tripDate = New Date(today.Year, today.Month, tripDay)
Dim tripDates = {tripDate.AddMonths(-1), tripDate, tripDate.AddMonths(1)}
Array.Sort(Of Date)(tripDates, Function(d1, d2) ((today - d1).Duration).CompareTo((today - d2).Duration))
Dim nearestDate = tripDates.First()
If ((today - nearestDate).Days <= maxDiffDays) Then
Console.WriteLine("Nearest month for trip date is: " & nearestDate.Month)
End If
It creates a Date from a given day, then it creates the two surrounding dates one month after and previous this date. This array will be sorted from the positive timespan from today(TimeSpan.Duration). So the firs't date in the array is the nearest date with the correct month.