Calculate X amount of hrs ahead only counting 9-5 hrs - vb.net

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

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

Why does msgbox with these variables produce an error?

apologies if this is a basic question, but I am self-teaching myself VBA PowerPoint and would appreciate it if someone could explain why I am getting an overflow error.
I have been trying to get the time my program user spends performing an activity using DateDiff and Now to set the start and end timers. My approach is to get the number of seconds and then work out how many days, minutes, hours and seconds will make up this number.
The below code works, however, whenever I use the Messagebox (Msgbox) function I get an overflow error. For example if you look at the code below everything works, until you uncomment one of my commented MsgBoxes and then the program crashes with a Run-time error '6': Overflow. I note the actual crash occurs on one of the subsequent calculation lines below the uncommented message box. I note the first MsgBox which is uncommented does not crash the computer.
I would be grateful if someone could explain why the computer crashes and second are there any changes to my code required in order to make it reliable to use?
Thank you for any comments!
Sub NewTimer()
Dim TimeStart As Date
Dim TimeEnd As Date
Dim Days As Long
Dim Hours As Long
Dim Hours2 As Long
Dim Hours3 As Long
Dim Minutes As Long
Dim Minutes2 As Long
Dim Seconds As Long
Dim TimePassed As String
Dim Seconds2 As Long
Seconds = Int(DateDiff("s", Now, Now + 1))
MsgBox "The total number of seconds that make up this number is " & Seconds
Days = Int(DateDiff("d", Now, Now + 1))
MsgBox "The total number of days in this number is " & Days
Hours2 = Seconds - (Days * 24 * 60 * 60) 'This gets the number of seconds remaining
Hours3 = Hours2 / (60 * 60) 'This works out the number of hours
Hours = Int(Hours3)
'MsgBox Hours
Minutes = Seconds - (Days * 24 * 60 * 60) - (Hours * 60 * 60) ' Hours2 - (Hours * 60 * 60)
'MsgBox Minutes
Minutes2 = Int(Minutes / 60)
'MsgBox Minutes2
'Minutes2 = Minutes / 60
Seconds = Seconds - (Days * 24 * 60 * 60) - (Hours * 60 * 60) - (Minutes2 * 60)
MsgBox "The time taken is " & Days & " days, " & Hours & " hours, " & Minutes2 & " minutes and " & Seconds & " seconds."
As other comments, when I ran your code I had no issues at all. However, you can achieve the same result with this code. See if it helps:
Sub NewTimer()
Dim TimeStart As Double
Dim TimeEnd As Double
Dim TimeDiff As Double
Dim Days As Long
Dim TimeDiffString As String
TimeStart = Now
TimeEnd = TimeStart + 4 + TimeValue("04:13:25")
TimeDiff = TimeEnd - TimeStart
Days = Int(TimeDiff)
TimeDiffString = Days & " days, " & Hour(TimeDiff) & " hours, " & Minute(TimeDiff) & " minutes and " & Second(TimeDiff) & " seconds."
MsgBox TimeDiffString
End Sub
Edit: follow-up to comments below.
In office applications, you can safely think of dates and times as decimal (floating point) numeric values, where the integer part is the number of days and the fraction part is a fraction of the day. Examples will make this clear:
1.5 is a day and a half -> 1 day and 12 hours -> 36 hours etc.
1 day and 2 hours is 1 + 2/24
1 hour is 1 / 24, approx. 0.041667
1 minute is 1 / (24 * 60), approx. 0.000694
1 second is 1 / (24 * 60 * 60), approx. 0.000012 and so on.
Office applications give you many functions you can use to format dates/times. For example in VBA:
Hour() gives you the hour on the clock. Hour(1.27) = Hour(3.27) = Hour(295.27) = 6
Minute() gives you the minutes on the clock. Minute(1.27) = Minute(3.27) = Minute(295.21) = 28
Second() gives you the seconds on the clock. Second(1.27) = Second(3.27) = Second(295.21) = 48
This is the same as saying that (6 hours + 28 minutes + 48 seconds) adds up to 0.27 of 1 day.
Day() gives you the calendar day of the month, where day 1 is defined depending on the context and your settings. For example in Excel VBA day 1 is generally December 31, 1899. therefore, Day(295.21) = 21 because 295.21 is 294 days after December 31, 1899 which corresponds to October 21, 1900.
Month() gives you the calendar month of the year. Therefore, Month(295.27) = 10
Year() gives you the calendar year. Therefore, Year(295.27 = 1900
This explains why I separated the day (the integer part of DateDiff in the code). If for example DateDiff = 295.27, then Day(DateDiff) is going to give you 21 not the 295 days you expect.
Homework: in the code above work out what fraction TimeValue("04:13:25") should result in. Check your answer with this code - no cheating ;):
Sub CheckMyAnswer()
MsgBox Format(TimeValue("04:13:25"), "0.000000")
End Sub
Phew, hope this helps. I am sure if you google the issue you will find far better explanations and plenty of videos, too.

How do I calculate Hours between dates with a 8-hour work day and accounting for weekends? (VB.net)

I need some help calculating hours worked between two dates, but with an 8-hour work day. I also need to adjust for weekends so I don't say someone took longer then they actually did. I am using VB.net
For example, date1 is 1/23/2020 9:00:00 AM, the start date, and date2 is 1/27/2020 1:30:00 PM, the finish time.
If I run this code:
Dim hours As double = DateDiff(DateInterval.hour, date1, date2)
it would give me the total hours, but would include weekends and not filter it for an 8 hour day.
How can I filter out workday times and weekends? Any help in refining this would be appreciated
One possible option
'Get all days between the start date and the end date
Dim midDays As Date() = Enumerable.Range(0, endDate.Subtract(startDate.AddDays(1)).Days).Select(Function(offset) startDate.AddDays(offset)).ToArray
'Filter out any weekend days
Dim weekdays As Date() = midDays.Where(Function(day) day.DayOfWeek <> DayOfWeek.Saturday AndAlso day.DayOfWeek <> DayOfWeek.Sunday).ToArray
'Assume all days are a full 8 hours
Dim hoursWorked As Decimal = weekdays.Count * 8
This essentially creates a list of all days between the start and end date. Remove weekends from the list and calculates 8 hours for each remaining day.
Of course you would then add the hours from the first and last day to the total.
Simple loop
Dim td As DateTime
If endDate < startDate Then
'switch
td = endDate
endDate = startDate
startDate = td
End If
Dim hours As Integer = 0
td = startDate
While td < endDate
If td.DayOfWeek <> DayOfWeek.Saturday AndAlso td.DayOfWeek <> DayOfWeek.Sunday Then
hours += 8
End If
td = td.AddDays(1)
End While

How do you separate integers into two separate variables?

I encountered a problem with my code. I made a program which asks the user(s) to enter a 'number of days' which is then separated into weeks and remainder of days.
Here is the code I've written so far (please click the link because I have not been given permission to post images yet):
Some guidance would be appreciated.
The if is wrong and if the number of days >= 7 days will need to be recomputed.
Dim weeks As Integer
Dim days As Integer
'....
weeks = days \ 7
If days >= 7 Then
days = days - (weeks * 7)
'...
End If
I agree the if statement is incorrect. I am just adding another way to accomplish the same thing in case people are interested.
Dim weeks As Integer = 0
Dim days As Integer = 0
'...
If days >= 7 Then
weeks = days / 7
days = days % 7
'...
End If

Accurate Time Math For VB Including Division

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.