Java вычитает массив временных диапазонов из родительского временного диапазона

#java-time

#java-time

Вопрос:

Временные диапазоны (представляющие длины видео) представлены в строках этого формата: HH:mm:ss . Предположим, у меня есть родительский временной диапазон, который выглядит следующим образом: 00:00:59 представляет видео длиной 59 секунд.

Теперь у меня есть массив пар временных диапазонов, которые я должен удалить из видео, потому что в течение этих временных диапазонов в видео не произошло ничего интересного. Например, входной массив:

 [
00:00:10 to 00:00:20, 
00:00:30 to 00:00:35, 
00:00:35 to 00:00:40
]
 

Я хочу удалить эти неважные диапазоны из 59-секундного видео и вычислить оставшиеся допустимые сегменты видео. В приведенном выше случае идеальным результатом будет:

 [
00:00:00 to 00:00:10, 
00:00:20 to 00:00:30, 
00:00:40 to 00:00:59
]
 

Комментарии:

1. Я бы не искал библиотеку, а рассматривал это как упражнение по алгоритмам.

2. java.time.Duration и LocalTime .

Ответ №1:

Сортировка, итерация и включение

  1. Сортируйте входные интервалы по времени их начала (должны быть исключены)
  2. Выполните итерацию по каждому входному интервалу, чтобы исключить
  3. Включает любой интервал между концом предыдущего исключенного интервала и началом текущего исключенного интервала
  4. В конце проверьте наличие любого оставшегося интервала путем сравнения с общей длиной
 import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class SequenceTest {

    public static void main(String[] args) {
        final SequenceTest sequenceTest = new SequenceTest();
        sequenceTest.computeIncludeIntervals(59,
            Arrays.asList((new int[][]{{10, 20}, {30, 35}, {35, 40}})));
        sequenceTest.computeIncludeIntervals(40,
            Arrays.asList((new int[][]{{10, 20}, {30, 35}, {35, 40}})));
        sequenceTest.computeIncludeIntervals(41,
            Arrays.asList((new int[][]{{10, 20}, {30, 35}, {35, 40}})));
        sequenceTest.computeIncludeIntervals(41,
            Arrays.asList((new int[][]{{0, 20}, {30, 35}, {36, 40}})));

    }

    protected List<int[]> computeIncludeIntervals(final int totalLength, List<int[]> excludeIntervals) {
        // sort the sequence by start time - O(NlogN)
        excludeIntervals.sort((a, b) -> a[0] == b[0] ? Integer.compare(a[1], b[1])
            : Integer.compare(a[0], b[0]));

        int previousEnd = 0; // initial state
        final List<int[]> result = new ArrayList<>();
        for (int[] exclude : excludeIntervals) {
            if (previousEnd < exclude[0]) {
                int[] include = new int[]{previousEnd, exclude[0]};
                result.add(include);
            }
            previousEnd = Math.max(previousEnd, exclude[1]);
        }

        // remaining tail
        if (previousEnd < totalLength) {
            result.add(new int[]{previousEnd, totalLength});
        }

        System.out.println("Total Length: "   totalLength   ", Input: "   excludeIntervals.stream()
            .map(interval -> interval[0]   ":"   interval[1])
            .collect(Collectors.joining(", ")));
        System.out.println("Included: "   result.stream().map(interval -> interval[0]   ":"   interval[1])
            .collect(Collectors.joining(", ")));

        return resu<
    }
}
 

Фактическое решение

  1. Напишите преобразователь для преобразования входной даты и времени в эпоху времени unix
  2. Используйте описанный выше подход для вычисления интервалов включения
  3. Преобразование включает интервалы в эпохальное время в текущее время с использованием обратного преобразования

Ответ №2:

Я написал 2 класса: TimeRange и TimeRangeSet.

Использование:

 public static void main(String[] args) throws ParseException
{
    TimeRange minuend = new TimeRange("00:00:00", "00:00:59");
    
    TimeRangeSet subtrahendSet = new TimeRangeSet();
    
    subtrahendSet
        .addRange("00:00:10", "00:00:20")
        .addRange("00:00:30", "00:00:35")
        .addRange("00:00:35", "00:00:40");
        
    TimeRangeSet differenceSet = minuend.minus(subtrahendSet);
    
    System.out.println("t "   minuend);
    System.out.println("minust"   subtrahendSet);
    System.out.println("equalst"   differenceSet);
}
 

Вывод:

          00:00:00 to 00:00:59
minus   [00:00:10 to 00:00:20, 00:00:30 to 00:00:35, 00:00:35 to 00:00:40]
equals  [00:00:00 to 00:00:10, 00:00:20 to 00:00:30, 00:00:40 to 00:00:59]
 

Диапазон времени:

 import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.temporal.ValueRange;

public class TimeRange implements Comparable <TimeRange>
{
    private ValueRange valueRange;
    
    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
            
    public TimeRange(ValueRange valueRange)
    {
        this.valueRange = valueRange;
    }
    
    public TimeRange(String fromTime, String toTime) throws ParseException
    {
        this
        (
            ValueRange.of(simpleDateFormat.parse(fromTime).getTime(), simpleDateFormat.parse(toTime).getTime())
        );
    }
    
    public TimeRangeSet minus(TimeRangeSet subtrahendSet)
    {
        TimeRangeSet difference = new TimeRangeSet();
        
        subtrahendSet.forEach
        (
            (subtrahend) ->
            {
                TimeRangeSet subDifference = new TimeRangeSet();
                subDifference.addAll(minus(subtrahend));
                difference.addAll(subDifference.minus(subtrahendSet));
            }
        );
        
        return difference;
    }
        
    public TimeRangeSet minus(TimeRange subtrahend)
    {
        TimeRangeSet difference = new TimeRangeSet();
        
        long A  = valueRange.getMinimum();
        long B  = valueRange.getMaximum();
        long C  = subtrahend.valueRange.getMinimum();
        long D  = subtrahend.valueRange.getMaximum();
        
                
        if ( B <= C )                                       //  A-----------B
            difference.addRange(ValueRange.of(A, B));       //              C-------D
        else
            
        if ( A >= D )                                       //          A-----------B
            difference.addRange(ValueRange.of(A, B));       //  C-------D
        else
            
        if ( (A >= C)  amp;amp; (A < D) amp;amp; (B > D) )              //  A---------------B
            difference.addRange(ValueRange.of(D, B));       //  C-------D                                               
        else
            
        if ( (A < C)  amp;amp; (B > C) amp;amp; (B <= D) )              //  A---------------B
            difference.addRange(ValueRange.of(A, C));       //          C-------D                   
        else
            
        if ( (A < C)  amp;amp; (B > C) amp;amp; (B > D) )               //  A---------------B
        {                                                   //      C-------D
            difference.addRange(ValueRange.of(A, C));
            difference.addRange(ValueRange.of(D, B));
        }
        
        return difference;
    }
    
    public String toString()
    {
        return String.format("%tT to %tT", valueRange.getMinimum(), valueRange.getMaximum());
    }
    
    
    @Override
    public int compareTo(TimeRange input)
    {
        return this.toString().compareTo(input.toString());
    }
}
 

TimeRangeSet:

 import java.text.ParseException;
import java.time.temporal.ValueRange;
import java.util.TreeSet;


public class TimeRangeSet extends TreeSet <TimeRange>
{
    private static final long serialVersionUID = 1L;

    public TimeRangeSet addRange(ValueRange valueRange)
    {
        super.add(new TimeRange(valueRange));
        return this;
    }
    
    public TimeRangeSet addRange(String fromTime, String toTime) throws ParseException
    {
        super.add(new TimeRange(fromTime, toTime));
        return this;
    }
    
    public TimeRangeSet minus(TimeRangeSet subtrahendSet)
    {       
        subtrahendSet.forEach
        (
            (subtrahend) ->
                ((TimeRangeSet) this.clone()).forEach
                (
                    (minuend) ->
                    {
                        if (this.addAll(minuend.minus(subtrahend)))
                            this.remove(minuend);
                    }
                )
        );
        
        return this;
    }
}