Forum Discussion
Date / Time difference excluding weekends and factoring working hours
- 1 year ago
so complicated...
(from, to, optional st, optional et) => [s_time = st ?? #time(8, 0, 0), e_time = et ?? #time(17, 0, 0), start = List.Min({from, to}), end = List.Max({from, to}), start_date = Date.From(start), end_date = Date.From(end), gen = List.Generate( () => [c = start_date, sod = List.Max({start, start_date & s_time}), eod = List.Min({end, c & e_time})], (x) => x[c] <= end_date, (x) => [c = Date.AddDays(x[c], 1), sod = c & s_time, eod = List.Min({end, c & e_time})], (x) => if Date.DayOfWeek(x[c], Day.Monday) > 4 then null else x[eod] - x[sod] ), result = if List.NonNullCount({from, to}) < 2 then null else List.Sum(gen)][result]
Difference in days?
Difference in time. After I can convert in days if I have to.
Examples :
18/09/2024 08:00:00 -> 18/09/2024 10:00:00 = 02:00:00
18/09/2024 08:00:00 -> 19/09/2024 10:00:00 = 11:00:00 according working between 08:00:00 and 17:00:00 each day (so 08:00:00 -> 17:00:00 + 08:00:00 -> 10:00:00)
- dufoq31 year agoCommunity Champion
Check this. Ignore first 4 rows (I've added them just for test purpose).
You can edit shiftStart and shiftEnd in Helper step.
EDIT: I've added option where you can decide whether you want to include or exclude weekends:Output
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("nVZRbuwwCLxKtd+rLGA7iX2Vam9Q9e/d/zng2NQmaVJppRUTDMMATj4/H7i+IL4IiD5gTgESwOP5IKgorskXtPzez3wsmsfcjWPxT8cQkisOGqWKHmRb89PxmE+ZBlJGYcp17MZWPm4u7gOXBJjCYh3M6JYGdvr+R5rlBxqT22K4CZvx/e/ry/KEKPTJjNtQYeGCos/GHld58kMIwne24ioUkatzEtc1Y+5S+2ChFM/Udy+E2sr8y8U+H/NEzdj0XIv6IeWz0iADvVYNNKoTUDUQuoIdWmg4q6YoXf7U1nAXE64H6NWIe2DXhyiTF83a4zhPXDs0o7lsYpZ5HFCcL+6ReJc0SzVGF7RQwIvVxEZ1Ajzh7S00yPibCkPbFWKZgj9Ab1ws3qvNZAPzWFIb4jyMvrttpUdwRxBPShAx+tK9KYi7pTsElUaMQeHZTC6LqvegpdG1CylQU+R6F0F70RgNJQ1eWNT4Qqz7tO25s9AyMHZEWjriPDE4YawGrX1fcefAU4SW7gqVW9uvIshaDe3CpYOJ5jv7+PVkb4Hrek50h2lAxZSNgZOLJopnQmMnNOkJYYOodi4zkc5xP9VnhVqrPwkiHbwsCJPz5RUazbc31O+NAQ3zrTTLr2n4nhnTXNX9oJrBha/jEYU71RCeVYP1WhjQe72h+GsaXtcBLWt16Z7BbgL5M2pAs7Dv938=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [début = _t, dateEC = _t, DiffEC = _t, dateT = _t, dateF = _t]), ChangedType = Table.TransformColumnTypes(Source,{{"dateF", type datetime}, {"dateT", type datetime}, {"DiffEC", type duration}, {"dateEC", type datetime}, {"début", type datetime}}), Helper = [ shiftStart = #time(8,0,0), shiftEnd = #time(17,0,0), includeWeekends = "no", //type "yes" if you want to include weekends. Type "no" if you want to exclude weekends workingHours = shiftEnd - shiftStart ], fn_WorkingDuration = (previousStep as table, start as text, end as text, optional colName as text)=> let // Ad_StartColumn = Table.DuplicateColumn(ChangedType, "début", "S"), // Ad_EndColumn = Table.DuplicateColumn(Ad_StartColumn, "dateEC", "E"), Ad_StartColumn = Table.DuplicateColumn(previousStep, start, "S"), Ad_EndColumn = Table.DuplicateColumn(Ad_StartColumn, end, "E"), Ad_SDate = Table.AddColumn(Ad_EndColumn, "S Date", each DateTime.Date([S]), type date), Ad_STime = Table.AddColumn(Ad_SDate, "S Time", each DateTime.Time([S]), type time), Ad_EDate = Table.AddColumn(Ad_STime, "E Date", each DateTime.Date([E]), type date), Ad_ETime = Table.AddColumn(Ad_EDate, "E Time", each DateTime.Time([E]), type time), // Weekends excluded Ad_WorkingDays = Table.AddColumn(Ad_ETime, "Working Days", each try [ a = List.Dates([S Date], Duration.TotalDays([E Date] - [S Date]) +1, #duration(1,0,0,0)), //weekends included b = List.Select(a, (x)=> Date.DayOfWeek(x, Day.Monday) < 5), //weekends excluded c = if Text.Trim(Text.Lower(Helper[includeWeekends])) = "yes" then a else b ][c] otherwise null, type list), // [S Date] and [E Date] excluded Ad_FullDaysHours = Table.AddColumn(Ad_WorkingDays, "Full Days Hours", each try [ a = List.RemoveItems([Working Days], { [S Date], [E Date]}), b = Helper[workingHours] * List.Count(a) ][b] otherwise null, type duration), Ad_FirstDayHours = Table.AddColumn(Ad_FullDaysHours, "Fist Day Hours", each try if [S Date] = List.First([Working Days]) then (if [S Date] = [E Date] then List.Min({ [E Time], Helper[shiftEnd] }) else Helper[shiftEnd]) - List.Max({ [S Time], Helper[shiftStart] }) else #duration(0,0,0,0) otherwise null, type duration), Ad_LastDayHours = Table.AddColumn(Ad_FirstDayHours, "Last Day Hours", each try if [S Date] = [E Date] then #duration(0,0,0,0) else if [E Date] = List.Last([Working Days]) then Helper[workingHours] else #duration(0,0,0,0) otherwise null, type duration), // Ad_TotalWorkingDuration = Table.AddColumn(Ad_LastDayHours, "Total Working Duration", each [Full Days Hours] + [Fist Day Hours] + [Last Day Hours], type duration), Ad_TotalWorkingDuration = Table.AddColumn(Ad_LastDayHours, if colName <> null then colName else "Total Working Duration" , each [Full Days Hours] + [Fist Day Hours] + [Last Day Hours], type duration), _RemovedColumns = Table.RemoveColumns(Ad_TotalWorkingDuration,{"S", "E", "S Date", "S Time", "E Date", "E Time", "Working Days", "Full Days Hours", "Fist Day Hours", "Last Day Hours"}) in _RemovedColumns, StepBack = ChangedType, Ad_dateECDuration = fn_WorkingDuration(StepBack, "début", "dateEC", "dateEC duration"), Ad_dateTDuration = fn_WorkingDuration(Ad_dateECDuration, "début", "dateT", "dateT duration"), Ad_dateFDuration = fn_WorkingDuration(Ad_dateTDuration, "début", "dateF", "dateF duration") in Ad_dateFDuration- Heremion1 year agoFrequent Visitor
Hello, Thanks for your help and time.
If I want to make this diff between two of my datetime field, where do I have to put them because I see start and end but they're text field, not datetime field.
Thanks
- dufoq31 year agoCommunity Champion
Hi, I'm not sure if I understand your question. Could you be more specific please? Add some screenshots with detailed explenation please.