Localizando intervalos em intervalos de datas

15

Dada uma lista de períodos rcomo entrada, saída ou retorno de qualquer intervalo não encontrado r.

Para fins deste exemplo, a entrada estará em YYYY-MM-DDformato.

Digamos que você tenha três períodos:

[2019-01-01, 2019-02-01]
[2019-02-02, 2019-04-05]
[2019-06-01, 2019-07-01]

Você pode ver que há uma lacuna entre 2019-04-05e 2019-06-01.

A saída será essa lacuna: [2019-04-06, 2019-05-31]

Regras

  • A entrada e a saída podem estar em qualquer formato de data ou coleção razoável, desde que consistente.
  • Suponha que a entrada não esteja ordenada.
  • Seu período não precisa ser [latest, earliest], mas deve seguir a regra 2.
  • Suponha que não haja datas sobrepostas na entrada

Casos de teste:

Entrada: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-04-05],[2019-06-01, 2019-07-01]]

Resultado: [[2019-04-06, 2019-05-31]]


Entrada: [[2019-01-01, 2019-02-01],[2018-02-02, 2018-04-05],[2019-06-01, 2019-07-01]]

Resultado: [[2018-04-06, 2018-12-31], [2019-02-02, 2019-05-31]]


Entrada: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-03-02],[2019-03-03, 2019-07-01]]

Resultado: []


Entrada: [[2019-01-01, 2019-02-01], [2019-11-02, 2019-11-20]]

Resultado: [[2019-02-02, 2019-11-01]]


Entrada: [[2019-01-01, 2019-02-01],[2019-02-03, 2019-04-05]]

Saída: [[2019-02-02, 2019-02-02]]ou[[2019-02-02]]

Oliver
fonte
5
Sugiro refazer todas as datas de exemplo para o formato ISO, YYYY-MM-DDpois o formato atual é estrangeiro para muitas pessoas e ficou ainda mais difícil de analisar devido ao uso de pequenos dias do mês12.
Adám 18/02/19
@ Adám Boa ideia, atualizada.
Oliver
Podemos receber entradas como datas de automação OLE do .NET?
Adám 18/02/19
@ Adám Sim. Qualquer formato de data razoável é aceitável.
Oliver
1
As datas serão ordenadas? Além disso, dentro de um par de datas, a última será a última?
Modalidade de ignorância

Respostas:

4

APL (Dyalog Extended) , 28 25 24 bytes

Função de prefixo tácito anônimo. Argumento e resultado são matrizes de 2 colunas de números de dias desde uma época, cada linha representando um intervalo.

1 ¯1+⍤1∘{⍵⌿⍨1<-⍨/⍵}1⌽⍢,∧

Experimente online! A Infunção de pré-processador converte de uma lista de pares de listas de 3 elementos (datas na ordem ISO) em uma matriz de 2 colunas de IDNs, números de dias internacionais (dias desde 1899-12-31). A Outfunção pós-processador converte de uma matriz de IDNs para uma matriz de listas de 3 elementos.

 classificar linhas ascendentes

1⌽ gire ciclicamente as datas um passo à esquerda
⍢, enquanto arrasta (achatada) - depois, modifique novamente a forma original

1 ¯1+ adicione um e um negativo
⍤1 usando essa lista para cada linha
 do resultado de
{} o seguinte lambda:
 o argumento
-⍨/ subtrai a data do lado esquerdo da data do lado direito, a
1< máscara no sentido da linha onde as diferenças excedem um
⍵⌿⍨ filtro (por exemplo, onde os intervalos não são adjacentes) as linhas por essa máscara

Adão
fonte
3

C # (compilador interativo do Visual C #) , 108 bytes

n=>{n.Sort();for(int i=0;;)Write(n[i].b.AddDays(1)==n[++i].a?"":n[i-1].b.AddDays(1)+""+n[i].a.AddDays(-1));}

Saídas imprimindo no formato DD/MM/YYYY 12:00:00 AMDD/MM/YYYY 12:00:00 AM. Causará uma exceção IndexOutOfRange, que é boa por meta consenso.

Experimente online!

Se recebermos informações na forma de dias desde a época do unix, podemos fazer isso ...

83 bytes

n=>{n.Sort();for(int i=0;;)Print(n[i].b+1==n[++i].a?"":n[i-1].b+1+" "+(n[i].a-1));}

Experimente online!

Podemos jogar isso ainda mais com o /u:System.Array bandeira, por ...

78 bytes

n=>{Sort(n);for(int i=0;;)Print(++n[i].b==n[++i].a--?"":n[i-1].b+" "+n[i].a);}

Experimente online!

Modalidade de ignorância
fonte
2

Perl 5, 130 bytes

/-(\d+)-/,$_=strftime"%Y-%m-%d",0,0,0,$'+($|--||-1),$1-1,$`-1900 for@F=sort@F;$,lt$;&&say"$, $;"while($,,$;)=@F[++$i,$i+1],++$i<@F

TIO

Nahuel Fouilleul
fonte
2

Bash, 125 bytes

set `sort<<<$1`;shift;for a;{ s=$[x++%2?-1:1]day;c=`date -d$a\ $s +%Y-%m-%d`;[ $p ]&&{ [[ $p < $c ]]&&echo $p $c;p=;}||p=$c;}

TIO

Nahuel Fouilleul
fonte
2

Perl 6 , 46 bytes

{@_.sort[1..*-2].map:{$^a+1,$^b-1 if $b>$a+1}}

Experimente online!

Leva uma lista de Datepares.

Nwellnhof
fonte
Alguma idéia de por que esse possível golfe controla a saída da data?
Jo rei
@JoKing Notei isso também e registrei um bug .
Nwellnhof 19/02/19
2

PHP, 208 197 190 177 bytes

pedaços robustos estavam sentados em uma parede ... embora a nova abordagem tivesse algum potencial de golfe.

function($a){sort($a);for($m=$x=$a[0][0];$f=$m<=$x;$f^$g&&print($g=$f)?"$m/":"$n
",$m=date("Y-m-d",strtotime($n=$m)+9e4))foreach($a as$d)$x=max($x,$d[1|$f&=$m<$d[0]|$m>$d[1]]);}

A função pega uma série de faixas [início, fim] no formato ISO, imprime intervalos de folga. Experimente online .


demolir

function($a){
    sort($a);                           # sort ranges (for easy access to min date)
    for($m=$x=$a[0][0];$f=$m<=$x;       # loop from min date to max date, 1. set flag
        $f^$g&&print($g=$f)?"$m/":"$n\n",       # 4. flag changed: backup flag, print date
        $m=date("Y-m-d",strtotime($n=$m)+9e4)   # 5. backup and increment date
    )foreach($a as$d)
        $x=max($x,$d[1                          # 2. find max date
            |$f&=$m<$d[0]|$m>$d[1]              # 3. date found in ranges: clear flag
        ]);
}
Titus
fonte
1

Gelatina , 13 bytes

FṢṖḊs2+Ø+>/Ðḟ

A geléia (atualmente) não tem datas internas, portanto, ela usa dias desde a época.
A lista de entrada de intervalos (pares de números inteiros) pode estar em ordem e direções diferentes.
O resultado é uma lista de intervalos ascendentes em ordem crescente.

Experimente online! (formatos de rodapé para mostrar uma lista vazia como[])

Quão?

Nota: Isso depende da garantia de que "não há datas sobrepostas na entrada", conforme declarado nas regras.

FṢṖḊs2+Ø+>/Ðḟ - Link: list of pairs of integers
F             - flatten
 Ṣ            - sort
  Ṗ           - pop (remove tail)
   Ḋ          - dequeue (remove head)
    s2        - split into twos
       Ø+     - literal [1,-1]
      +       - add (vectorises)
           Ðḟ - filter discard those for which:
          /   -   reduce by:
         >    -     greater than?
Jonathan Allan
fonte
Interessante, eu não sabia que Jelly não tinha data de suporte. Essa é a abordagem usual? Usar dias desde a época?
dana
Os dias desde a época são, acredito, usados ​​por alguns sistemas (talvez o Excel). Segundos desde a época é mais comum (por exemplo, Unix). Eu apenas fui com algo que parece cobrir os requisitos, embora de maneira bastante relaxada.
Jonathan Allan
Boo, você pode calcular as datas manualmente . ; P Os dias desde a época são realmente usados ​​com mais frequência para idiomas que não suportam datas. Eu sinto que isso facilita muito esse desafio.
Kevin Cruijssen 22/02/19
@KevinCruijssen heh, concordou.
Jonathan Allan
1

C # (compilador interativo do Visual C #) , 103 bytes

x=>{var(a,_)=x[0];foreach(var(b,c)in x.OrderBy(y=>y)){if(a<b)Print((a,b.AddDays(-1)));a=c.AddDays(1);}}

Experimente online!

Entrada é uma lista de tuplas de data de início / término. Emite cada intervalo ausente para STDOUT.

// x: input list of start/end date tuples
x=>{
  // variable definitions...
  // a: 1 day after the end date of the previous range
  // b: start of the current range
  // c: end of the current range

  // start by deconstructing the start date of the first tuple
  // into a. a will then be a DateTime and will contain a value
  // at least a large as the smallest start date.
  var(a,_)=x[0];
  // iterate over sorted ranges
  foreach(var(b,c)in x.OrderBy(y=>y)){
    // if the day after the end of the previous range is less
    // than the start of the current range, then print the
    // missing days.
    if(a<b)
      Print((a,b.AddDays(-1)));
    // save the day after the current range to a for next iteration
    a=c.AddDays(1);
  }
}
dana
fonte
128
somente ASCII
Hah - se você imprimir como Modalidade de Ignorância, poderá ficar muito pequeno - Experimente on-line!
dana
Agradável. Também wtf seu método de entrada para os dois últimos
ASCII só de
Bem, na verdade ... isso parece realmente incorreto
somente ASCII
1
Sim, isso parece bom agora
apenas ASCII
1

R , 88 bytes

function(a,b=a[order(a$x),],d=c(b$x[-1]-b$y[-nrow(b)],0))data.frame(b$y+1,b$y+d-1)[d>1,]

Experimente online!

Isso leva um quadro de dados de intervalos de datas como entrada e gera um quadro de dados com os intervalos ausentes. Estou bastante certo de que este poderia ser golfed mais, mas eu corri em problemas com c, cbinde outros decapagem a classe data.

Nick Kennedy
fonte