Split a Time Range into Pieces by Other Time Ranges

Split a time range into pieces by other time ranges

As you specifically asked for "some insight" rather than a full working answer, I'd personally go with arrays populated with "minutes".

$shift = array(
'start' => '15:30:00',
'end' => '18:30:00',

'original' => array(),
'unavailable' => array(),
'modified' => array()
);

You'd then do some jiggery pokery to convert 15:30:00 into 930 and 18:30:00 into 1110 (number of minutes) which will give you the difference between start and end times.

Use range() to quickly fill up the original array, load in your unavailable in a similar format and then use things like array_intersect() and array_diff() to work out which minutes from the original shift are unavailable.

From that, build up the modified array, and read directly from there to your output.

Split a time range into pieces by other time ranges in javascript

I has created an example as you want. I think code is something tough and long so if it helpful for you then use otherwise ignore it.

    var obj = {        s: '14:30',        e: '18:30'    }    var deviation = [{            s: '15:30',            e: '16:30'        },        {            s: '17:30',            e: '18:30'        }]
$(document).ready(function () { deviation.push(obj); var newArr = []; $(deviation).each(function (index, value) { newArr.push(value.e); newArr.push(value.s); }); var newArr = newArr.sort(); var $timeArr = []; lastVal = ''; $(newArr).each(function (index, value) {
if (index == 0) { lastVal = value; } else { var stTime = lastVal; var endTime = value;
lastVal = endTime; var pushObj = { s: stTime, e: endTime } var lsstKey = newArr.length - 1; if (index != lsstKey) { $timeArr.push(pushObj); } } }); document.getElementById("myarray").innerHTML = JSON.stringify($timeArr); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script><p id="myarray"></p>

Split Time range into multiple time periods based on interval in Python

You can do arithmetic on datetime objects by adding timedelta objects.

You probably need to decide exactly what behaviour is required if the interval per period is not an exact divisor of the total, but this example would give a final short period in that case.

import datetime

tstart = datetime.datetime(2020,8,24,9,30)
tend = datetime.datetime(2020,8,24,11,30)
interval = datetime.timedelta(minutes=30)

periods = []

period_start = tstart
while period_start < tend:
period_end = min(period_start + interval, tend)
periods.append((period_start, period_end))
period_start = period_end

print(periods)

This gives (with newlines inserted for readability):

[(datetime.datetime(2020, 8, 24, 9, 30), datetime.datetime(2020, 8, 24, 10, 0)),
(datetime.datetime(2020, 8, 24, 10, 0), datetime.datetime(2020, 8, 24, 10, 30)),
(datetime.datetime(2020, 8, 24, 10, 30), datetime.datetime(2020, 8, 24, 11, 0)),
(datetime.datetime(2020, 8, 24, 11, 0), datetime.datetime(2020, 8, 24, 11, 30))]

For the string output format that you want, you could do something like this:

def format_time(dt):
return dt.strftime("%Y-%m-%d %H:%M")

print(['{} - {}'.format(format_time(start), format_time(end))
for start, end in periods])

to give:

['2020-08-24 09:30 - 2020-08-24 10:00',
'2020-08-24 10:00 - 2020-08-24 10:30',
'2020-08-24 10:30 - 2020-08-24 11:00',
'2020-08-24 11:00 - 2020-08-24 11:30']

Split up date range into chunks to join back into one table KDB+/Q

Something like this should chunk it for you:

raze{select from t where date within x}each(first;last)@\:/:d group"m"$d:sd+til 1+ed-sd

Do not use where date.month=x as you had suggested - at least not for historical queries

How to split the time range into multiple rows

Here is a recursive CTE solution:

with cte as (
select
employeecode,
startdatetime,
dateadd(hour, 1, datetimefromparts(year(startdatetime), month(startdatetime), day(startdatetime), datepart(hour, startdatetime), 0, 0, 0)) enddatetime
enddatetime maxdatetime
from mytable
union all
select employeecode, enddatetime, dateadd(hour, 1, enddatetime), maxdatetime
from cte
where enddatetime < maxdatetime
)
select employeecode, startdatetime,
case when enddatetime < maxdatetime then enddatetime else maxdatetime end as enddatetime
from cte

Basically, the anchor of the CTE performs computes the end of the first range, using datetimefrompart(). Then we iteratively generate the following ranges, until the maximum date time is reached. We can then display the results with the outer query, while adjusting the end date of the last range.

Dividing a date range into equal chunks containing a set number of day chunks in JavaScript?

Start with the start date and add maxDays to get the end of the block. If the block date is greater than the end date, use the end date instead. Then add maxDays to the start and go again until the start is >= than the end.

Copy dates before pushing into the array so don't affect original or ongoing processing.

function getDateBlocks(start, end, maxDays) {
let result = [];
// Copy start so don't affect original
let s = new Date(start);

while (s < end) {
// Create a new date for the block end that is s + maxDays
let e = new Date(s.getFullYear(), s.getMonth(), s.getDate() + maxDays);
// Push into an array. If block end is beyond end date, use a copy of end date
result.push({start:new Date(s), end: e <= end? e : new Date(end)});
// Increment s to the start of the next block which is one day after
// the current block end
s.setDate(s.getDate() + maxDays + 1);
}
return result;
}

console.log(getDateBlocks(new Date(2021,0,1), new Date(2021,0,20), 6));

Split an array of date range items each with a start and an end timestamp which can overlap each other into separate arrays of non overlapping ranges?

A generic approach has to work itself recursively through any given original timetable (source array) in order to detect/generate as much time tables which each feature just non-overlapping time range items.

A recursive implementation would call itself repeatedly as long as there are, within a processed array, still overlapping time range items found.

Part of the approach is, that such a self recursive function does create a shallow copy of the passed time table and also does sort it exactly once, at the time of being called initially.

function parseTime(value) {
return new Date(value).getTime();
}
function getParsedTimeRangeFromItem({ start, end }) {
return {
start: parseTime(start),
end: parseTime(end),
}
}

function orderByTimeRangeAscending(a, b) {
const { start: aStart, end: aEnd } = getParsedTimeRangeFromItem(a);
const { start: bStart, end: bEnd } = getParsedTimeRangeFromItem(b);

return (aStart - bStart) || (aEnd - bEnd);
}

function createTimetablesOfNonOverlappingTimeRanges(timetable, result) {
// at initial call time only ...
if (!Array.isArray(result)) {
// ... create the result array ...
result = [];
// ... and also a shallow and sorted copy
// of the initially passed `timetable`.
timetable = [...timetable].sort(orderByTimeRangeAscending);
}
const rejected = [];

let idx = -1;
let item, nextItem;

while (
(item = timetable[++idx]) &&
(nextItem = timetable[idx + 1])
) {
// detect `nextItem` as overlapping time range item ...
if (parseTime(item.end) > parseTime(nextItem.start)) {

// ... and reject it from the `timetable` reference.
rejected.push(timetable.splice((idx + 1), 1)[0])
--idx;
}
}
// add the sanitized but mutated `timetable` to `result`.
result.push(timetable);

// in case of any rejected time range item trigger self recursion.
if (rejected.length >= 1) {
result =
createTimetablesOfNonOverlappingTimeRanges(rejected, result);
}
return result;
}

const timetable = [
{ class: 'one', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'two', start: '2021-11-16T10:00:00', end: '2021-11-16T11:00:00' },
{ class: 'three', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'four', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
{ class: 'five', start: '2021-11-16T10:00:00', end: '2021-11-16T11:00:00' },
{ class: 'six', start: '2021-11-16T09:00:00', end: '2021-11-16T10:00:00' },
];

console.log(
'[...timetable].sort(orderByTimeRangeAscending) ...',
[...timetable]
.sort(orderByTimeRangeAscending)
);
console.log(
'createTimetablesOfNonOverlappingTimeRanges(timetable) ...',
createTimetablesOfNonOverlappingTimeRanges(timetable)
);
console.log('un-mutated original source array ...', { timetable });
.as-console-wrapper { min-height: 100%!important; top: 0; }


Related Topics



Leave a reply



Submit