2012-10-29 17 views
5

Ho un compito complicato che ho battuto la testa contro il muro ora per alcuni giorni. Ho provato circa 4 approcci diversi, tuttavia ognuno sembra stallo e sta diventando estremamente frustrante.Dividere un intervallo di tempo in pezzi da altri intervalli di tempo

Ho un intervallo di tempo. Ad esempio, 14:30:00 fino alle 18:30:00. Considera questa fascia oraria il turno di lavoro di qualcuno. Durante questo intervallo di tempo, dichiarano di non poter lavorare dalle 15:30 alle 16:30 e dalle 17:30 alle 18:30. Devo modificare l'ora di inizio e di fine del turno originale per rimuovere i turni in conflitto.

L'array spostamento originale assomiglia a questo:

$original_shift[0]['start'] = '14:30:00'; 
$original_shift[0]['end'] = '18:30:00'; 

e gli intervalli del tempo per essere rimosso dallo sguardo spostamento originale così:

$subshift[0]['start'] = '15:30:00'; 
$subshift[0]['end'] = '16:30:00'; 
$subshift[1]['start'] = '17:30:00'; 
$subshift[1]['end'] = '18:30:00'; 

Ecco una visualizzazione:

enter image description here

Così, ho praticamente bisogno di mio turno originale assomigliare a questo quando ho finito:

$original_shift[0]['start'] = '14:30:00'; 
$original_shift[0]['end'] = '15:30:00'; 
$original_shift[1]['start'] = '16:30:00'; 
$original_shift[1]['end'] = '17:30:00'; 

Alcune complicazioni che ho anche bisogno di prendere in considerazione sono:

  1. Questi intervalli di tempo possono essere qualsiasi volte (non vincolata alla mezz'ora come ho usato nel mio esempio), tuttavia saprò con certezza al 100% che gli intervalli di tempo non disponibili inizieranno sempre e finiranno o tra l'inizio e la fine dell'orario di spostamento originale.

  2. I tempi non disponibili possono accumularsi e/o richiedere il tempo dell'intero spostamento dell'originale.

Non sto cercando qualcuno a "scrivere il mio codice" per quanto mi sto cercando qualcuno che ha affrontato con qualcosa di simile in passato e può avere una certa comprensione su come hanno compiuto esso.

+0

Ho fatto alcune precisazioni, tuttavia l'ultimo blocco di codice non mostra come farlo, mostra ciò di cui ho bisogno per produrre il prodotto finale. –

+0

può già essere segmentato lo spostamento dell'originale, ad es. può già contenere il tempo non disponibile? – Gordon

risposta

3

Come richiesto specificatamente per "un po 'di intuizione" piuttosto che per una risposta completa, personalmente andrei con gli array popolati con "minuti".

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

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

Farebbe quindi fare un po 'pokery jiggery per convertire 15:30:00 in 930 e 18:30:00 in 1110 (numero di minuti) che vi darà la differenza tra i tempi di inizio e fine.

Usa range() per riempire rapidamente il original matrice, carico nel vostro unavailable in un formato simile e quindi utilizzare le cose come array_intersect() e array_diff() per capire quale minuti dal passaggio originale non sono disponibili.

Da questo, creare l'array modified e leggere direttamente da lì all'output.

+0

Grazie! Per qualche ragione, non mi è mai venuto in mente di lavorare con il tempo in minuti (come numero intero). In realtà, ho i tempi in numeri interi basati su minuti da un passaggio precedente, quindi questo si integrava bene con quello che stavo facendo in origine. Sono stato in grado di trovare una soluzione con un po 'di lavoro in più rispetto a quello che avevi suggerito, ma mi hai aiutato a mettermi sulla giusta via del pensiero. –

1

Il codice dovrebbe parlare per sé:

$original_shift[0]['start'] = '14:30:00'; 
$original_shift[0]['end'] = '18:30:00'; 

$breaks[0]['start'] = '14:30:00'; 
$breaks[0]['end'] = '15:30:00'; 
$breaks[1]['start'] = '16:30:00'; 
$breaks[1]['end'] = '17:30:00'; 

$modified_shift = array(
    array('start' => $original_shift[0]['start']) 
); 

for($x = 0, $y = count($breaks), $z = 0; $x < $y; $x++){ 
    $modified_shift[$z]['end'] = $breaks[$x]['start']; 
    if($modified_shift[$z]['end'] != $modified_shift[$z]['start']){ 
     $z++;  
    } 
    $modified_shift[$z]['start'] = $breaks[$x]['end']; 
} 

$modified_shift[$z]['end'] = $original_shift[0]['end']; 

if($modified_shift[$z]['end'] == $modified_shift[$z]['start']){ 
    unset($modified_shift[$z]); 
} 
2

Hai bisogno di fare calcoli di time-range. Come mostra l'immagine, questa sembra una semplice sottrazione. Sarebbe bello avere solo oggetti che facciano questi.

Non avevo codice per questo pronto, quindi il seguente concetto è un po 'approssimativo, anche se probabilmente non così male.

A Range tipo che rappresenta un tempo da-a. Questi sono come DateTime in modo che i benefici di questi tipi esistenti possano essere utilizzati. Non ho usato molti dei benefici finora, tuttavia per il resto dell'applicazione questo può avere senso.

Il tipo Range contiene già alcuni metodi di confronto di base che pensavo fossero utili per eseguire parti dei calcoli.

Tuttavia, poiché un oggetto non può dividersi in due, ho anche creato un tipo Ranges che può rappresentare uno o più Range s. Era necessario avere qualcosa che potesse essere "diviso".

Ho imbrogliato un po 'qui perché ho implementato il calcolo della differenza come membro di Range, restituendo un array con uno o più oggetti Range. Il calcolo finale poi è solo avere uno spostamento e sottrarre gli intervalli più disponibile da essa:

$shift = new Ranges(new DateTime('14:30:00'), new DateTime('18:30:00')); 

$unavailables = new Ranges([ 
    new Range(new DateTime('15:30:00'), new DateTime('16:30:00')), 
    new Range(new DateTime('17:30:00'), new DateTime('18:30:00')), 
]); 

$shift->subtract($unavailables); 

Lo spostamento campate quindi:

14:30:00 - 15:30:00 
16:30:00 - 17:30:00 

Demo; Gist

non posso dire se vale la pena l'astrazione, ciò che è bello, con DateTime oggetti è che si può confrontare con >, < e =. Il vero vantaggio di queste classi potrebbe essere messo in luce quando hai bisogno di più calcoli tra Range e Ranges. Forse l'interfaccia non è ancora dolce, tuttavia i calcoli di base alla base sono già delineati nel codice.

Un avvertimento: la differenza tra 14:00-15:00 e 14:00-15:00 nel mio codice sarà 14:00-14:00. Mantengo l'ora di inizio per non andare a vuoto, ma puoi anche svuotare. L'oggetto Ranges dovrebbe gestirlo bene.

+0

Ci sono stati alcuni difetti per le operazioni inverse, ho aggiornato l'essenza e una demo aggiornata è qui: http://codepad.viper-7.com/jy2Uz5 – hakre

+0

Grazie, questo codice sembra molto promettente. Probabilmente l'avrei accettato come risposta (preferisco DateTime quando possibile), tuttavia un precursore (e qualcosa che ho omesso) è che il passo precedente, stavo convertendo il tempo da esso in minuti dritti (es. 480 per 8am) a un oggetto DateTime. La soluzione di Joe in basso suggeriva di lavorare direttamente con una versione del tempo di solo minuto, che in qualche modo non mi era mai venuta in mente. La sua soluzione funziona e mi fa risparmiare un passo, che è l'unica ragione per cui scelgo di sceglierla come risposta. Grazie mille per il lavoro svolto in questa risposta! –

+0

Internamente questa cosa è anche una matrice, tuttavia ho risparmiato per mantenere intervalli di numeri (un elemento al minuto) facendo confronti di inizio/fine. Funzionerebbe anche con i valori minimi di inizio e fine e ho persino pensato di rendere questi intervalli più astratti perché una volta (non basato sul tempo) aveva un bisogno simile.È stato divertente scriverlo, è stato fatto anche abbastanza velocemente, non sono pienamente soddisfatto dei nomi dei metodi. Ma anche se lavori con gli array, ti suggerisco di formare un tipo base per mettere insieme la gamma e i metodi per mantenere il codice snello. Buona fortuna con il vostro progetto. – hakre

Problemi correlati