I was trying to get the first Friday of the quarter of today's date or any given date. Let's say the date is 12/06/2020, which falls to the 2nd quarter of the year. I should be able to get the first Friday of the 2nd Quarter and that should be April 3rd.
I was only been able to get the quarter of a given date, which you can see in the code below. Been stuck here for a while. Thanks in advance.
quarter = Int((Month(Now) + 2) / 3)
Here's a function that takes a date and returns the first Friday of the quarter:
Function FirstFridayOfTheQuarter(MyDate As Date) As Date
Dim FirstDayOfTheQuarter As Date
FirstDayOfTheQuarter = DateSerial(Year(MyDate), Int((Month(MyDate) - 1) / 3) * 3 + 1, 1)
FirstFridayOfTheQuarter = DateAdd("d", (13 - Weekday(FirstDayOfTheQuarter)) Mod 7, FirstDayOfTheQuarter)
End Function
This function is taking advantage of the Weekday function that returns:
1 for a Sunday
2 for a Monday
3 for a Tuesday
4 for a Wednesday
5 for a Thursday
6 for a Friday
7 for a Saturday
In case you want a non VBA solution:
My formula is:
=CEILING(EOMONTH(DATE(YEAR(A1);ROUNDUP(MONTH(A1)/3;0)+(ROUNDUP(MONTH(A1)/3;0)-1)*2;1);-1)-5;7)+6
Related
I have the Year, Week-of-Year and Day-of-the-Week as follows:
Year = 2022 (A2) ; Week Year = 35 (B2); Week Day = 4 or Thursday (C2)
and I would like to estimate the Date as dd.mm.yyyy, which is highlighted in yellow as it shows in the EXCEL picture.
I tried many formulas, but I am sure there might be an easy one.
I think you are counting the weeks starting from zero because for 9/1/2022 (YYYY/MM/DD format) the corresponding week is 36 as per the result of function WEEKNUM(DATE(2022,9,1)). In order to use the logic to multiply the number of weeks by 7. You need to use as a reference the first day of the year, if it was a Sunday, if not then go back to the previous Sunday, so you can count the entire week. Bottom line use as a reference date, the Sunday of the first week of the year, not the first day of the year (YYYY/1/1)
Here is the approach we use in cell E2:
=LET(y, A2:A6, wk, B2:B6, wDay, C2:C6, fDay, DATE(y,1,1), seq, SEQUENCE(7),
fDay - IF(WEEKDAY(fDay)=1,0, WEEKDAY(fDay,2)) + 7*wk
+ XLOOKUP(wDay, TEXT(seq,"dddd"), seq-1))
We use the LET function to avoid repeating the same calculation. The following expression finds the previous Sunday if the first day of the year (fDay) was not a Sunday:
fDay - IF(WEEKDAY(fDay)=1,0, WEEKDAY(fDay,2))
The XLOOKUP function is used to get the numeric representation of the weekday and use the TEXT function to generate the weekdays in a long format. Since we count the entire week, if the weekday is a Sunday (column C in my screenshot), then we don't need to add any day to our reference date, that is why we use seq-1.
Here is the output for several sample data. Assuming the week count starts with zero, if not the formula needs to be adjusted as also the input data.
Notice that the year 2021 started on a Friday, so if we want to find a day for the first week (0) before Friday it will return a date from the previous year. Like in the case of Monday. If you want an error message instead, then the formula can be modified as follow:
=LET(y, A2:A6, wk, B2:B6, wDay, C2:C6, fDay, DATE(y,1,1), seq, SEQUENCE(7),
result, fDay - IF(WEEKDAY(fDay)=1,0, WEEKDAY(fDay,2)) + 7*wk
+ XLOOKUP(wDay, TEXT(seq,"dddd"), seq-1),
IF(YEAR(result) <> y, "ERROR: Date from previous year", result))
I found the solution:
Year = 2022 (A2) ; Week Year = 35 (B2); Week Day = 4 or Thursday (C2)
=DATE (A2,1,3)-WEEKDAY(DATE(A2,1,3)) + 7 * B2 + C2 - 6
I found this solution, but you need to do further testing if it really works.
I calculate month from week: =+MONTH(DATE(YEAR(A2);1;1)+B2*7-1)
I calculate week day number from week day name: =MATCH(D2;{"Monday";"Tuesday";"Wednesday";"Thursday";"Friday";"Saturday";"Sunday"};0)
And then make date using: =DATE(A2;C2;E2)
Output is not how it should be
given_day = datetime.date(2022,10,31)
dates = given_day + datetime.timedelta(days=+1)
for i in range(0 - given_day.weekday(), 7 - given_day.weekday()):
print(given_day.strftime("%A"))
Output should start from Monday and end to Sunday
Output I get is:
Monday
Monday
Monday
Monday
Monday
Monday
Monday
Where i made a mistake :(
I can't make head or tail of your code, but the following works:
given_day = datetime.date(2022,10,31)
for i in range(0 + given_day.weekday(), 7):
print(given_day.strftime("%A"))
given_day += datetime.timedelta(days=1)
We can find different approaches to determining the week of the month, and even though there are many pages on 1:4 and/or 1:5, there is very few around 1:6 approach.
So to give you a bit of the context, I am working with a pivot table in Excel which gets its values from a Power Query source.
In Power Query, there is a function Date.WeekOfMonth which takes in the date and returns a number between 1 and 6.
In this definition, weeks start from Sunday and ends on Saturday.
So, for example, the first two days of October 2021 -i.e. Fri & Sat- fall in the 1st week of Oct, while the 3rd day of Oct 2021 starts the second week, and then the last day of October 2021,i.e. Oct 31, is the only day in the 6th week.
I had an automation task on hand in which I needed to pull data from the Power Query-generated pivot, so I had to implement a piece of code in VBA which calcs weeks the same.
Unfortunately, I couldn't find any prepared snippet, so after implementing I though it might worth sharing.
(Any comments and suggestions appreciated)
The DatePart function is perfect for this. Using DatePart with the interval set to "weeks" you can find the week of a given date. Then you subtract the number of weeks before the first day of that month (which sets the first day to week = 1).
Function WeekNumOfDate(D As Date) As Integer
WeekNumOfDate = DatePart("ww", D) - DatePart("ww", DateSerial(Year(D), Month(D), 1)) + 1
End Function
Here is a second version of the function that has the ability to set the FirstDayOfWeek argument:
Function WeekNumOfDate(D As Date, Optional FirstDayOfWeek As VbDayOfWeek = vbSunday) As Integer
WeekNumOfDate = DatePart("ww", D, FirstDayOfWeek) - DatePart("ww", DateSerial(Year(D), Month(D), 1), FirstDayOfWeek) + 1
End Function
As an example for using FirstDayOfWeek: With FirstDayOfWeek set to vbThursday, the date "Nov 5th, 2021" will return as Week 2, whereas it would by default be counted as Week 1. November 1st to 3rd of 2021 will be week 1, and then 4th to 10th will be week 2.
Its implementation in VBA is:
Function WeekOfMonth(My_Date As Date)
If Day(My_Date) > Day(My_Date - 1) And Weekday(My_Date) > Weekday(My_Date - 1) Then
WeekOfMonth = WeekOfMonth(My_Date - 1)
ElseIf Day(My_Date) > Day(My_Date - 1) And Weekday(My_Date) < Weekday(My_Date - 1) Then
WeekOfMonth = WeekOfMonth(My_Date - 1) + 1
Else
WeekOfMonth = 1
End If
End Function
Note that even though the above function is recursive, its time and space complexity is an expression of order N, which here cannot exceed 31.
I am trying to find the week number for a fiscal year which is starts on first sunday of February. I have got it to a point where I can get the week number which starts on first of every year (in my case feb).
Not able to start it from First Sunday. Below is what I've come up with.
=IF(AND(MONTH($E2)=2,DAY($E2)=1),1,ROUNDUP(($E2-DATE(YEAR($E2)-IF(MONTH($E2)<2,1,0),2,0)+WEEKDAY(DATE(YEAR($E2)-IF(MONTH($E2)<2,1,0),2,0)))/7,0))
I would also like it to end on Saturday of last week of the year.
For example: in Feb 2016, the week count should start from 7thFeb2016 and the count should end on 4thFeb2017.
Use this formula to find week number of given date:
=IF(A1>=IF(WEEKDAY(DATE(YEAR(A1),2,1),1)=1,DATE(YEAR(A1),2,1),DATE(YEAR(A1),2,7-WEEKDAY(DATE(YEAR(A1),2,1),1)+2)),ROUNDUP((A1-IF(WEEKDAY(DATE(YEAR(A1),2,1),1)=1,DATE(YEAR(A1),2,1),DATE(YEAR(A1),2,7-WEEKDAY(DATE(YEAR(A1),2,1),1)+2))+1)/7,0),ROUNDUP((A1-IF(WEEKDAY(DATE(YEAR(A1),2,1),1)=1,DATE(YEAR(A1)-1,2,1),DATE(YEAR(A1)-1,2,7-WEEKDAY(DATE(YEAR(A1)-1,2,1),1)+2))+1)/7,0))
I hope you want this.
UPDATED
If you want week number of fiscal quarter, use this:
=ROUNDUP(MOD(=IF(A1>=IF(WEEKDAY(DATE(YEAR(A1),2,1),1)=1,DATE(YEAR(A1),2,1),DATE(YEAR(A1),2,7-WEEKDAY(DATE(YEAR(A1),2,1),1)+2)),ROUNDUP((A1-IF(WEEKDAY(DATE(YEAR(A1),2,1),1)=1,DATE(YEAR(A1),2,1),DATE(YEAR(A1),2,7-WEEKDAY(DATE(YEAR(A1),2,1),1)+2))+1)/7,0),ROUNDUP((A1-IF(WEEKDAY(DATE(YEAR(A1),2,1),1)=1,DATE(YEAR(A1)-1,2,1),DATE(YEAR(A1)-1,2,7-WEEKDAY(DATE(YEAR(A1)-1,2,1),1)+2))+1)/7,0)),13.01),0)
I just chucked this together (no doubt there is a more elegant way to do this). You can use it by putting it into a Module in your VBA editor and then on the worksheet use the function =AltWeekNumber(E2)
Function AltWeekNumber(endDate As Range) As Date
Dim startDate As Date
startDate = FirstFebruarySunday(year(endDate.Value))
If startDate > endDate Then
startDate = FirstFebruarySunday(year(endDate.Value) - 1)
End If
AltWeekNumber = DateDiff("w", startDate, endDate.Value, vbSunday)
End Function
Private Function FirstFebruarySunday(year As Integer) As Date
For i = 1 To 7
If Weekday(DateSerial(year, 2, i)) = 1 Then
FirstFebruarySunday = DateSerial(year, 2, i)
Exit Function
End If
Next i
End Function
I am writing an AppleScript which generates an MS Excel spreadsheet every month. I need to know how many days are in the current month, then go trough all months and decide if a given day is a weekday or a holiday.
I suppose I would save holidays (from this web http://kalendar365.cz/statni-svatky/2016 as table and access them locally) for this.
My question is:
How do I get the last day in a month?
How do I efficiently loop trough all days in the current month and decide if it is Sunday, Saturday or a day specified somewhere else (for example, in a text file of xlsx spreadsheet)?
pbell's answer is promising, but the GetLastDay function doesn't work correctly for months that have fewer than 31 days; here's a function that fixes that:
# Returns the number of days in the month that the given date falls in.
# Example:
# my GetNumberOfDaysInMonth(current date)
on GetNumberOfDaysInMonth(aDate)
local aDateCopy
copy aDate to aDateCopy
set day of aDateCopy to 1
if month of aDateCopy is December then
set year of aDateCopy to ((year of aDateCopy) + 1)
set month of aDateCopy to 1
else
set month of aDateCopy to ((month of aDateCopy) + 1)
end if
return day of (aDateCopy - 1 * days)
end GetNumberOfDaysInMonth
The approach is based on setting the date to the 1st of the month, then incrementing the month (possibly rolling over into the next year), and subtracting 1 day, which works correctly with all dates, even in leap years.
How about a simple no-function-needed method?
set currdate to the current date
set nextmonth to currdate + (30 * days)
set {year:y, month:m, day:d, time:t} to nextmonth
set ms to m as string --month as string
set ys to y as string --year as string
set firstday to date (m & " 1," & y as string) --midnight at the first day of next month
set lastday to (firstday - 1) --minus one second
return lastday -- last day of the this month at 11:59 PM
As for weekends and holidays in Excel, doesn't Excel provide its own functions for that, as dirk-reichel mentioned?
However, if you want to use AppleScript to filter out these days using a pre-specified list of holidays, maybe this example will help. It loops through October through December of 2022, with USA holidays Halloween, Thanksgiving and Christmas Day specified. Note that Christmas Day happens to land on a Sunday in 2022.
set weekend to {"Saturday", "Sunday"}
set holidays to {date "October 31, 2022", date "November 24, 2022", date "December 25, 2022"}
set workdays to {}
set my_date to (date "Saturday, October 1, 2022 at 12:00:00 AM")
repeat
set dy to the weekday of my_date
set mydy to dy as string
if weekend does not contain mydy and holidays does not contain my_date then
set workdays to workdays & my_date
end if
set my_date to my_date + (1 * days)
if my_date contains (date "January 1, 2023") then --specify an end date for your loop
exit repeat
end if
end repeat
return workdays
The script below contains the 2 routines you're looking for : GetlastDay and isWorkingDay :
set myDate to current date -- just for example !
set N to GetlastDay(myDate)
log N --> number of days in month of myDate
set A to IsWorkingday(myDate)
log A --> true if Monday to Friday, false if Saturday/Sunday
on GetlastDay(LDate) -- return last day of month of LDate
copy LDate to L -- to not change LDate
set L's day to 32 -- = first day of next month
set L to L - (1 * days) -- last day of month
return day of L
end GetlastDay
on IsWorkingday(LDate) -- true if date is not Saturday or Sunday
set SD to weekday of LDate
return (SD is not in {Saturday, Sunday})
end IsWorkingday