How to get the previous working day excluding weekend and holidays - vb.net

I would like to get the previous working day excluding weekend and holiday using VB Net in UiPath.
I referenced this:how-to-determine-if-a-date-is-a-holiday, however I get errors when put the code.
I tried add Sub and End Sub, but I still get the same error.
Here's the code
Sub GetWorkdays()
Dim todayVar As Date = Today
Debug.Print(isHoliday(todayVar.AddDays(1)))
End Sub
Function isHoliday(ByVal dt As Date)
Return getHolidayList(dt.Year).Any(Function(x) x = dt)
End Function
Public Function getHolidayList(ByVal vYear As Integer) As List(Of Date)
Dim FirstWeek As Integer = 1
Dim SecondWeek As Integer = 2
Dim ThirdWeek As Integer = 3
Dim FourthWeek As Integer = 4
Dim LastWeek As Integer = 5
Dim HolidayList As New List(Of Date)
' http://www.usa.gov/citizens/holidays.shtml
' http://archive.opm.gov/operating_status_schedules/fedhol/2013.asp
' New Year's Day Jan 1
HolidayList.Add(DateSerial(vYear, 1, 1))
' Martin Luther King, Jr. third Mon in Jan
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 1, 1), DayOfWeek.Monday, ThirdWeek))
' Washington's Birthday third Mon in Feb
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 2, 1), DayOfWeek.Monday, ThirdWeek))
' Memorial Day last Mon in May
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 5, 1), DayOfWeek.Monday, LastWeek))
' Independence Day July 4
HolidayList.Add(DateSerial(vYear, 7, 4))
' Labor Day first Mon in Sept
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 9, 1), DayOfWeek.Monday, FirstWeek))
' Columbus Day second Mon in Oct
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 10, 1), DayOfWeek.Monday, SecondWeek))
' Veterans Day Nov 11
HolidayList.Add(DateSerial(vYear, 11, 11))
' Thanksgiving Day fourth Thur in Nov
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 11, 1), DayOfWeek.Thursday, FourthWeek))
' Christmas Day Dec 25
HolidayList.Add(DateSerial(vYear, 12, 25))
'saturday holidays are moved to Fri; Sun to Mon
For i As Integer = 0 To HolidayList.Count - 1
Dim dt As Date = HolidayList(i)
If dt.DayOfWeek = DayOfWeek.Saturday Then
HolidayList(i) = dt.AddDays(-1)
End If
If dt.DayOfWeek = DayOfWeek.Sunday Then
HolidayList(i) = dt.AddDays(1)
End If
Next
'return
Return HolidayList
End Function
Private Function GetNthDayOfNthWeek(ByVal dt As Date, ByVal DayofWeek As Integer, ByVal
WhichWeek As Integer) As Date
'specify which day of which week of a month and this function will get the date
'this function uses the month and year of the date provided
'get first day of the given date
Dim dtFirst As Date = DateSerial(dt.Year, dt.Month, 1)
'get first DayOfWeek of the month
Dim dtRet As Date = dtFirst.AddDays(6 - dtFirst.AddDays(-(DayofWeek + 1)).DayOfWeek)
'get which week
dtRet = dtRet.AddDays((WhichWeek - 1) * 7)
'if day is past end of month then adjust backwards a week
If dtRet >= dtFirst.AddMonths(1) Then
dtRet = dtRet.AddDays(-7)
End If
'return
Return dtRet
End Function
This is the error:
How do I solve the errors?
Here's the editor view:

ByVal and WhichWeek need to be on the same line.
Sub GetWorkdays()
Dim todayVar As Date = Today
Debug.Print(isHoliday(todayVar.AddDays(1)))
End Sub
Function isHoliday(ByVal dt As Date)
Return getHolidayList(dt.Year).Any(Function(x) x = dt)
End Function
Public Function getHolidayList(ByVal vYear As Integer) As List(Of Date)
Dim FirstWeek As Integer = 1
Dim SecondWeek As Integer = 2
Dim ThirdWeek As Integer = 3
Dim FourthWeek As Integer = 4
Dim LastWeek As Integer = 5
Dim HolidayList As New List(Of Date)
' http://www.usa.gov/citizens/holidays.shtml
' http://archive.opm.gov/operating_status_schedules/fedhol/2013.asp
' New Year's Day Jan 1
HolidayList.Add(DateSerial(vYear, 1, 1))
' Martin Luther King, Jr. third Mon in Jan
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 1, 1), DayOfWeek.Monday, ThirdWeek))
' Washington's Birthday third Mon in Feb
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 2, 1), DayOfWeek.Monday, ThirdWeek))
' Memorial Day last Mon in May
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 5, 1), DayOfWeek.Monday, LastWeek))
' Independence Day July 4
HolidayList.Add(DateSerial(vYear, 7, 4))
' Labor Day first Mon in Sept
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 9, 1), DayOfWeek.Monday, FirstWeek))
' Columbus Day second Mon in Oct
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 10, 1), DayOfWeek.Monday, SecondWeek))
' Veterans Day Nov 11
HolidayList.Add(DateSerial(vYear, 11, 11))
' Thanksgiving Day fourth Thur in Nov
HolidayList.Add(GetNthDayOfNthWeek(DateSerial(vYear, 11, 1), DayOfWeek.Thursday, FourthWeek))
' Christmas Day Dec 25
HolidayList.Add(DateSerial(vYear, 12, 25))
'saturday holidays are moved to Fri; Sun to Mon
For i As Integer = 0 To HolidayList.Count - 1
Dim dt As Date = HolidayList(i)
If dt.DayOfWeek = DayOfWeek.Saturday Then
HolidayList(i) = dt.AddDays(-1)
End If
If dt.DayOfWeek = DayOfWeek.Sunday Then
HolidayList(i) = dt.AddDays(1)
End If
Next
'return
Return HolidayList
End Function
Private Function GetNthDayOfNthWeek(ByVal dt As Date, ByVal DayofWeek As Integer,
ByVal WhichWeek As Integer) As Date
'specify which day of which week of a month and this function will get the date
'this function uses the month and year of the date provided
'get first day of the given date
Dim dtFirst As Date = DateSerial(dt.Year, dt.Month, 1)
'get first DayOfWeek of the month
Dim dtRet As Date = dtFirst.AddDays(6 - dtFirst.AddDays(-(DayofWeek + 1)).DayOfWeek)
'get which week
dtRet = dtRet.AddDays((WhichWeek - 1) * 7)
'if day is past end of month then adjust backwards a week
If dtRet >= dtFirst.AddMonths(1) Then
dtRet = dtRet.AddDays(-7)
End If
'return
Return dtRet
End Function
Also, not telling us what the error is or which line isn't very helpful...

Related

Query to return records within the same business year

Why are records which were entered before 31/07/2021 still showing in this query? I want to show records in the current business year only.
Company business year Starts in 01/08/YYYY and end on 31/07/YYYY the next year. Can the query works for every business year? i.e. "at this point of time next year".
I have this SQL code so far:
SELECT
FORMAT(DATEADD("m", 5, [OrderDate]), "\Qq") AS Quarter, *
FROM
tblOrders
WHERE
[OrderDate] BETWEEN DateSerial(Year(Date()) - 1, 8, 1)
AND DateSerial(Year(Date()), 8, 0)
ORDER BY
tblOrders.OrderDate DESC;
DateSerial(Year(Date()) - 1, 8, 1) returns 01.08.2020 and DateSerial(Year(Date()), 8, 0) returns 31.07.2021. So in the end you are getting all the dates between 01.08.2020 and 31.07.2021.
I guess you could make the Year(Date()) dynamic. In case current date is equal or past 01.08.XXXX but not past 31.12.XXXX then it should be current year and current year + 1 otherwise it should stay as it is now - current year - 1 and current year.
Maybe something like this:
SELECT
FORMAT(DATEADD("m", 5, [OrderDate]), "\Qq") AS Quarter, *
FROM
tblOrders
WHERE
[OrderDate] BETWEEN IIF(Date() >= DateSerial(Year(Date()), 8, 1) AND Date() <= DateSerial(Year(Date()), 13, 0), DateSerial(Year(Date()), 8, 1), DateSerial(Year(Date()) - 1, 8, 1))
AND IIF(Date() >= DateSerial(Year(Date()), 8, 1) AND Date() <= DateSerial(Year(Date()), 13, 0), DateSerial(Year(Date()) + 1, 8, 0), DateSerial(Year(Date()), 8, 0))
ORDER BY
tblOrders.OrderDate DESC;
You can use these two functions found in module DateBank here: VBA.Date.
' Returns the primo calendar date of the specified financial/fiscal year.
' Returns the primo calender date of the current financial year, if no
' financial year is specified.
'
' 2021-05-09. Gustav Brock. Cactus Data ApS, CPH.
'
Public Function DateFinancialYearPrimo( _
Optional ByVal FinancialYear As Integer) _
As Date
Dim Month As Integer
Dim Day As Integer
Dim Years As Integer
Dim Primo As Date
Month = VBA.Month(DateFinancialStart())
Day = VBA.Day(DateFinancialStart())
If IsYear(FinancialYear) Then
Years = FinancialYear - VBA.Year(FinancialStart)
If Month = MinMonthValue And Day = MinDayValue Then
' The financial year is the calendar year.
Else
Years = Years - 1
End If
Else
Years = VBA.Year(DateCalendar(Date)) - VBA.Year(FinancialStart)
End If
Primo = DateAdd("yyyy", Years, FinancialStart)
DateFinancialYearPrimo = Primo
End Function
' Returns the ultimo calendar date of the specified financial/fiscal year.
' Returns the ultimo calender date of the current financial year, if no
' financial year is specified.
'
' 2021-05-09. Gustav Brock. Cactus Data ApS, CPH.
'
Public Function DateFinancialYearUltimo( _
Optional ByVal FinancialYear As Integer) _
As Date
Dim Ultimo As Date
Ultimo = DateAdd("d", -1, DateAdd("yyyy", 1, DateFinancialYearPrimo(FinancialYear)))
DateFinancialYearUltimo = Ultimo
End Function
' Gets or sets the start day and month of the financial/fiscal year as a
' date value applied a neutral year.
'
' The start month can be any month.
' The start day can be any day less than or equal 28, which is the
' highest day value valid for any month.
'
' Default value is January 1st.
'
' Examples:
' ' Set financial year.
' StartDate = DateFinancialStart(10, 1)
' ' StartDate -> 2000-10-01
'
' ' Get financial year.
' StartDate = DateFinancialStart
' ' StartDate -> 2000-10-01
' EndDate = DateFinancialEnd
' ' EndDate -> 2000-09-30
'
' 2021-05-08. Gustav Brock. Cactus Data ApS, CPH.
'
Public Function DateFinancialStart( _
Optional ByVal StartMonth As Integer, _
Optional ByVal StartDay As Integer) _
As Date
' Validate input.
If IsMonth(StartMonth) And IsDayAllMonths(StartDay) Then
FinancialStart = DateSerial(Year(DefaultStart), StartMonth, StartDay)
End If
If FinancialStart = #12:00:00 AM# Then
FinancialStart = DefaultStart
End If
DateFinancialStart = FinancialStart
End Function
Note: Partial code only.

vb.net find 4th Wednesday of month with visual basic

I am trying to find the fourth Wednesday of the current Month and Year when a form loads
I have converted numerous C# code to Visual Basic with no results
Would someone explain what is wrong with this code OR explain how to accomplish this in VB Code
Private Sub SurroundingSub()
Dim thisDate As Date = Today
tbMonth.Text = thisDate.ToString("MMMM")
tbYear.Text = thisDate.ToString("yyyy")
Dim month As Integer
month = tbMonth.Text
Dim year As Integer
year = tbYear.Text
Dim fourthWed As Date = New Date(year, month, 4)
tbFour.Text = fourthWed.ToLongDateString
While fourthWed.DayOfWeek <> DayOfWeek.Wednesday
fourthWed = fourthWed.AddDays(1)
tbFour.Text = fourthWed.ToShortDateString
End While
End Sub
This is a JavaFX statement that I am trying to implement in VB.Net
if(TorF.equals("F") && today.isAfter(fourthTUEofMONTH))
This sets the date
public void setDATES() throws IOException, SQLException{
today = LocalDate.now();
fourthTUEofMONTH = LocalDate.now();
fourthTUEofMONTH = fourthTUEofMONTH.with(TemporalAdjusters.dayOfWeekInMonth(4, DayOfWeek.TUESDAY));
endMONTH = LocalDate.now();
endMONTH = endMONTH.with(TemporalAdjusters.lastDayOfMonth());
}
For a more general solution, with my function you can easily find the first, second, third, forth or fifth sunday, monday, tuesday, wednesday or whatever you want:
Public Function GetXDayOfWeek(Day As DateTime,
DayOfWeek As DayOfWeek,
Optional Index As Integer = 1) As DateTime
Dim First As New Date(Day.Year, Day.Month, 1)
Dim Diff As Integer = (DayOfWeek - First.DayOfWeek + 7) Mod 7
Return First.AddDays(Diff + (Index - 1) * 7)
End Function
So if you want to find the forth wednesday of the current month, use it like:
Dim DateToFind As DateTime = GetXDayOfWeek(Today, DayOfWeek.Wednesday, 4)
Your while statement will stop on the first Wednesday it finds, not the fourth. Keep track of the number of Wednesdays you encounter as you iterate and once you find the fourth then you can update tbFour.
Also as mentioned in the comments you'll want to start at the first day of the year.
Dim fourthWed As Date = New Date(year, month, 1)
Dim wednesdayCursor As Integer = 0
While wednesdayCursor < 4
If fourthWed.DayOfWeek = DayOfWeek.Wednesday Then
wednesdayCursor += 1
End If
fourthWed = fourthWed.AddDays(1)
End While
'Subtract one day because we added one on loop:
fbFour.Text = fourthWed.AddDays(-1).ToShortDateString()
You should make the function of getting the fourth Wednesday into a separate method, perhaps generalizing it for any day of the week, but just for the fourth Wednesday...
Module Module1
Function FourthWedOfMonth(dt As DateTime) As Integer
Dim currDate = New DateTime(dt.Year, dt.Month, 1)
Dim nWednesdays = 0
While nWednesdays < 4
If currDate.DayOfWeek = DayOfWeek.Wednesday Then
nWednesdays += 1
End If
currDate = currDate.AddDays(1)
End While
Return currDate.Day - 1
End Function
Sub Main()
For mo = 1 To 12
Console.Write(FourthWedOfMonth(New DateTime(2020, mo, 17)) & " ")
Next
Console.ReadLine()
End Sub
End Module
Outputs the correct days for 2020:
22 26 25 22 27 24 22 26 23 28 25 23
If you wanted the DateTime of the fourth Wednesday, you could
Function FourthWedOfMonth(dt As DateTime) As DateTime
Dim currDate = New DateTime(dt.Year, dt.Month, 1)
Dim nWednesdays = 0
While nWednesdays < 4
If currDate.DayOfWeek = DayOfWeek.Wednesday Then
nWednesdays += 1
End If
currDate = currDate.AddDays(1)
End While
Return New DateTime(dt.Year, dt.Month, currDate.Day - 1)
End Function
and then Console.WriteLine(FourthWedOfMonth(DateTime.Today).ToString("dd-MMM-yyyy")) would output "22-Jul-2020" (at the time of writing).
I'd find the fourth Wednesday of the current month this way:
Private Sub FourthWednesdayOfCurrentMonth()
Dim firstOfMonth As DateTime = DateTime.Today.AddDays(-1 * (DateTime.Today.Day - 1))
Dim firstWednesday As DateTime = firstOfMonth.AddDays((7 + (DayOfWeek.Wednesday - firstOfMonth.DayOfWeek)) Mod 7)
Dim fourthWednesday As DateTime = firstWednesday.AddDays(21)
tbYear.Text = fourthWednesday.Year
tbMonth.Text = fourthWednesday.Month
tbFour.Text = fourthWednesday.Day
End Sub
Written generically for any day of the week, that would change to:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim fourthWednesday As DateTime = FourthWeekDayOfCurrentMonth(DayOfWeek.Wednesday)
tbYear.Text = fourthWednesday.Year
tbMonth.Text = fourthWednesday.Month
tbFour.Text = fourthWednesday.Day
End Sub
Private Function FourthWeekDayOfCurrentMonth(ByVal WeekDay As DayOfWeek) As DateTime
Dim firstOfMonth As DateTime = DateTime.Today.AddDays(-1 * (DateTime.Today.Day - 1))
Dim firstWeekday As DateTime = firstOfMonth.AddDays((7 + (WeekDay - firstOfMonth.DayOfWeek)) Mod 7)
Return firstWeekday.AddDays(21)
End Function

How to find weeks between two dates

How to find week's starting date between two dates.
Example:
date1: 4th March 2014.
date2: 18th March 2014.
Then it should return list of weeks begining date as
2014-03-03, 2014-03-10, 2014-03-17
So first you want to get the first day of the week of the start-date? This gives your desired list:
Dim firstDate = New Date(2014, 3, 4)
Dim daysToFirstDay As Int32 = DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek - firstDate.DayOfWeek
firstDate = firstDate.AddDays(daysToFirstDay) ' -1 day in this case
Dim lastDate = New Date(2014, 3, 17)
Dim days As Int32 = (lastDate - firstDate).Days + 1 ' including last
Dim result As List(Of Date) = Enumerable.Range(0, days).
Select(Function(d) firstDate.AddDays(d)).
Where(Function(day) day.DayOfWeek = DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek).
ToList()
It's using LINQ to create a range of Dates between the start-and end-date. Then it uses the current DateTimeFormatInfo's FirstDayOfWeek property to return only week-starting days.
Function GetWeekStartDates(startDate As Date, endDate As Date) As List(Of Date)
Dim result As New List(Of Date)
Dim checkDate = startDate
Dim Is1stWeek As Boolean = True
Do While checkDate <= endDate
If checkDate.DayOfWeek = DayOfWeek.Monday Then
result.Add(checkDate)
If Is1stWeek Then Is1stWeek = False
Else
If Is1stWeek Then
result.Add(checkDate.AddDays(-checkDate.DayOfWeek + 1))
Is1stWeek = False
End If
End If
checkDate = checkDate.AddDays(1)
Loop
Return result
End Function

Getting Dates of Current week does not work as expected

iam trying to get the Dates (Monday - Sunday) for the current Week.
This is my current Code:
Dim kw As Integer = DatePart(DateInterval.WeekOfYear, Now, , FirstWeekOfYear.FirstFourDays)
If DatePart(DateInterval.Weekday, Now, Microsoft.VisualBasic.FirstDayOfWeek.Sunday) = 6 Then
kw = kw + 1
End If
Dim CurrDateFirstDay As Date = DateAdd(DateInterval.Day, 1, ReturnDateForWeekNumber(kw))
For i = 1 To 7
strCurrDay = FormatDateTime(CurrDateFirstDay, DateFormat.LongDate)
........
My Problem is that my code starts at 16.01.2013 and the last date is Thuesday 22.01.2013 next week. Why is that? Why does he start Wednesday 16.01.2013 and not Monday 14.01.2013? And why do i get returned dates of the next week? What iam doing wrong?
Edit:
ReturnDateForWeekNumber:
Public Shared Function ReturnDateForWeekNumber(ByVal iWeek As Integer) As DateTime
Return DateAdd(DateInterval.WeekOfYear, iWeek - 1, FirstDayOfYear)
End Function
What am I doing wrong?
You should step through your code in the debugger and observe the result, as I did:
Dim kw As Integer = DatePart(DateInterval.WeekOfYear, Now, , FirstWeekOfYear.FirstFourDays)
This returns the current week, which is week 3.
If DatePart(DateInterval.Weekday, Now, Microsoft.VisualBasic.FirstDayOfWeek.Sunday) = 6 Then
kw = kw + 1
End If
This checks if the weekday is the 6th day of the week (friday). We're not friday so If condition is not entered.
Dim CurrDateFirstDay As Date = DateAdd(DateInterval.Day, 1, ReturnDateForWeekNumber(kw))
This adds one day to the result of ReturnDateForWeekNumber, which returns:
Return DateAdd(DateInterval.WeekOfYear, iWeek - 1, FirstDayOfYear)
This adds 2 (week 3 minus 1) weeks to the first day of the year (Jan 1st), a tuesday. Jan 1st + 2 weeks = January 15th.
Now remember that you add one day to ReturnDateForWeekNumber, that's why CurrDateFirstDay has a value of January 16th.
Edit
I think your code is overly complicated and uses a lot of legacy VB6 functions. I would do it this way:
Dim myDate As Date = DateTime.Today
Dim dayDiff As Integer = myDate.DayOfWeek - DayOfWeek.Monday
Dim currentDay As Date = myDate.AddDays(-dayDiff) 'Monday
For i = 1 to 7
Console.WriteLine(currentDay)
'Do something with current day
currentDay = currentDay.AddDays(1)
Next
You might have to do some adjustments for your case but I believe this approach is simpler and less error prone.
Dim dateStartDateOfWeek As Date = GetWeekStartDate(52, 2014)
Dim dateEndDateOfWeek As Date = DateAdd(DateInterval.Day, 7, dateStartDateOfWeek)
Private Function GetWeekStartDate(ByVal weekNumber As Integer, ByVal year As Integer) As Date
Dim startDate As New DateTime(year, 1, 1)
Dim weekDate As DateTime = DateAdd(DateInterval.WeekOfYear, weekNumber - 1, startDate)
Return DateAdd(DateInterval.Day, (-weekDate.DayOfWeek) + 1, weekDate)
End Function

Calculate days of month

Is there any method for calculating the number of days in a month?
Yes:
Const July As Integer = 7
Const Feb As Integer = 2
' daysInJuly gets 31. '
Dim daysInJuly As Integer = System.DateTime.DaysInMonth(2001, July)
' daysInFeb gets 28 because the year 1998 was not a leap year. '
Dim daysInFeb As Integer = System.DateTime.DaysInMonth(1998, Feb)
' daysInFebLeap gets 29 because the year 1996 was a leap year. '
Dim daysInFebLeap As Integer = System.DateTime.DaysInMonth(1996, Feb)
Credit goes to MSDN.
http://authors.aspalliance.com/aspxtreme/sys/DateTimeClassDaysInMonth.aspx
Public Shared Function DaysInMonth ( _
ByVal year As Integer, _
ByVal month As Integer _
} As Integer
Dim d As New DateTime(2010, 4, 1)
Dim month As Integer = d.Month
While d.Month = month
Console.WriteLine(d.[Date])
d = d.AddDays(1)
End While
You can of course change how you output the Date to format it to your will.
To get the number of days of current month
Dim CurrentMonthDays As Int16 = DateTime.DaysInMonth(DateTime.Now.Year,DateTime.Now.Month)
Use an array: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Add one to Feb if (year mod 400 = 0) or ( (year mod 4 = 0) and not (year mod 100 = 0) )
You have two simple solutions:
5546>>m&1|30^(m==2)*2+(m==2&&y%4==0)))
or
(62648012>>m*2&3)+28+(m==2&&y%4==0)))
where m is the number of month and y is the year.
this solution is the same below, an array, but the array is bit masked in magic numbers.