Forum Discussion
calculate date without holidays (only working days)
- 3 years ago
jcamilo1985 I am afraid I can't comment on this. Probably because my function uses recursive call. I don't know. It's quite easy to reproduce this function using List.Generate. I'll try to do that a bit later, mate.
- 3 years ago
Thank you very much for your commitment and interest in this topic AlienSx .
After several attempts, I was finally able to find the solution, but all thanks to the base that you gave me.Here I share it in case someone else needs it at some point.
In the same way thanks to the other people who read the thread and were interested.(start as date, days as number, holidays as list) as date => let dates = List.Generate( () => [ date = start, count = 1, holiday = List.Contains(holidays, start) or List.Contains({5, 6}, Date.DayOfWeek(start, Day.Monday)) ], each [count] <= days, each [ date = Date.AddDays([date], 1), count = [count] + (if [holiday] then 0 else 1), holiday = List.Contains(holidays, Date.AddDays([date], 1)) or List.Contains({5, 6}, Date.DayOfWeek(Date.AddDays([date], 1), Day.Monday)) ], each [date] ), result = List.LastN(dates, 1){0} in result
first of all thank you very much ronrsnfld for coming to the solution of the thread
1 - holidays are for Colombia
2 - no, we start counting the days from the departure date.
I annex the table of holidays that I have, the real table is older
| holydays |
| 1/01/2023 |
| 7/01/2023 |
| 8/01/2023 |
| 9/01/2023 |
| 14/01/2023 |
| 15/01/2023 |
| 21/01/2023 |
| 22/01/2023 |
| 28/01/2023 |
| 29/01/2023 |
| 4/02/2023 |
| 5/02/2023 |
| 11/02/2023 |
| 12/02/2023 |
| 18/02/2023 |
| 19/02/2023 |
| 25/02/2023 |
| 26/02/2023 |
| 4/03/2023 |
| 5/03/2023 |
| 11/03/2023 |
| 12/03/2023 |
| 18/03/2023 |
| 19/03/2023 |
| 20/03/2023 |
| 25/03/2023 |
| 26/03/2023 |
| 1/04/2023 |
| 2/04/2023 |
| 6/04/2023 |
| 7/04/2023 |
| 8/04/2023 |
| 9/04/2023 |
| 15/04/2023 |
| 16/04/2023 |
| 22/04/2023 |
| 23/04/2023 |
| 29/04/2023 |
| 30/04/2023 |
| 1/05/2023 |
| 6/05/2023 |
| 7/05/2023 |
| 13/05/2023 |
| 14/05/2023 |
| 20/05/2023 |
| 21/05/2023 |
| 22/05/2023 |
| 27/05/2023 |
| 28/05/2023 |
| 3/06/2023 |
| 4/06/2023 |
| 10/06/2023 |
| 11/06/2023 |
| 12/06/2023 |
| 17/06/2023 |
| 18/06/2023 |
| 19/06/2023 |
| 24/06/2023 |
| 25/06/2023 |
| 1/07/2023 |
| 2/07/2023 |
| 3/07/2023 |
| 8/07/2023 |
| 9/07/2023 |
| 15/07/2023 |
| 16/07/2023 |
| 20/07/2023 |
| 22/07/2023 |
| 23/07/2023 |
| 29/07/2023 |
| 30/07/2023 |
| 5/08/2023 |
| 6/08/2023 |
| 7/08/2023 |
| 12/08/2023 |
| 13/08/2023 |
| 19/08/2023 |
| 20/08/2023 |
| 21/08/2023 |
| 26/08/2023 |
| 27/08/2023 |
| 2/09/2023 |
| 3/09/2023 |
| 9/09/2023 |
| 10/09/2023 |
| 16/09/2023 |
| 17/09/2023 |
| 23/09/2023 |
| 24/09/2023 |
| 30/09/2023 |
| 1/10/2023 |
| 7/10/2023 |
| 8/10/2023 |
| 14/10/2023 |
| 15/10/2023 |
| 16/10/2023 |
| 21/10/2023 |
| 22/10/2023 |
| 28/10/2023 |
| 29/10/2023 |
| 4/11/2023 |
| 5/11/2023 |
| 6/11/2023 |
| 11/11/2023 |
| 12/11/2023 |
| 13/11/2023 |
| 18/11/2023 |
| 19/11/2023 |
| 25/11/2023 |
| 26/11/2023 |
| 2/12/2023 |
| 3/12/2023 |
| 8/12/2023 |
| 9/12/2023 |
| 10/12/2023 |
| 16/12/2023 |
| 17/12/2023 |
| 23/12/2023 |
| 24/12/2023 |
| 25/12/2023 |
| 30/12/2023 |
| 31/12/2023 |
Thank you.
- Generate a calender including the possible date range from which holidays and weekend days are removed.
- To add working days, we merely look for the position in the List of working days that corresponds to then number of working days you wish to add.
- In your specific case, since the departure date is counted as Day 1, you must subtract 1 from the number of days you are looking for.
- Note that in the code below, I took your list of holidays and put in in a Query named HolyDay for access. But there is also code commented out that can download the holiday list for many countries from the web. (Using a Table for this will be much faster, however.
- I don't know if you will run into the same problem you had with the other solution
//Note optional Holidays parameter
//You can substitute a self-generated List of holidays, or use the website in the code to download a list
// If you use the website, be sure to use a recognized country name
//If you are using holidays, you should separate this list and buffer the result for speed issues.
// as written, it will download this list every time the function executes
(start as datetime, numDays as number, optional Country as nullable text) =>
let
adjNumDays = Number.RoundAwayFromZero(Number.Abs(numDays*7/5))*2,
yrStart = Date.Year(start),
yrEnd = Date.Year(Date.AddDays(start,adjNumDays*Number.Sign(numDays))),
//Create list of country specific Holidays
holidays = HolyDays[holydays],
/*yrs = {List.Min({yrEnd,yrStart})..List.Max({yrEnd,yrStart})},
if Country = null then {} else
List.Accumulate(yrs,{},(state,current) =>
let
Source=Web.Page(Web.Contents("https://www.officeholidays.com/countries/" & Country & "/" & Number.ToText(current))),
Data0 = Source{0}[Data],
DateCol = Table.SelectColumns(Data0,"Date"),
fullDate = List.Transform(DateCol[Date], each Date.FromText(_ & " " & Number.ToText(current)))
in
state & fullDate),*/
//all Working dates
//Generates a list of working dates in either Ascending or Descending order
// based on the Sign of numDays
// starting with the first working date after Start
allWorkDates =
List.RemoveNulls(
List.Transform(
List.DateTimes(start, adjNumDays, #duration(Number.Sign(numDays),0,0,0)),
each if _ = start then _
else
if Date.DayOfWeek(_)=Day.Saturday
or Date.DayOfWeek(_)=Day.Sunday
or List.Contains(holidays, Date.From(_))
then null
else _)),
addWorkDays = if numDays = 0 then start else allWorkDates{Number.Abs(numDays)}
in
addWorkDays