Autor Zpráva
Quick91
Profil *
Mám stránky-dělám rezervační systém. (už. jméno: xxx;heslo: xxx) a na té stránce jak vybíráte "puntíky" (půlhodinové časové intervaly) vpravo se do formuláře vypisují ty hodnoty(id) a já z toho potřebuju vytvořit intervaly. Nevímzda PHP nebo JavaScript bude lepší a zda má někdo nějaké řešení. Budu to vlád do MySQL databáze.

Př.: Zadám 11:00:00,11:30:00 -> 11:00:00-12:00:00
Zadám 11:00:00,11:30:00,12:00:00,15:00:00,15:30:00 -> 11:00:00-12:30:00,15:00:00-16:00:00
Alphard
Profil
Potenciální "díru" nenajdete jinak než projitím všech hodnot výsledného spojitého intervalu. Doplňuji, že je zde ještě teoretická možnost spočítat prvky a porovnat počet se správným, ale tím nezjistíte, co chybí, takže jste zase u té iterace.
Takže seřadit vzestupně, vzít první hodnotu a zjistit, jestli další bezprostředně následuje. Pokud ne, vytvořit nový interval. Mám v php verzi pro dny, kdyby vás to zajímalo.
l564
Profil
Mohu se zeptat co Vás vedlo k tomu odstranit patičku původního autora? Protože asi identický css mít nemůžete.

- Patička: peCan.cz
Quick91
Profil *
l564:
Styly budu komplet pekopávat, nehodlám to opsat


l564:
Rád bych tu verzi se dny viděl, zkoušel jsem to stěmi dírami, ale nedařilo se mi to moc


Alphard:
Rád bych tu verzi se dny viděl, zkoušel jsem to stěmi dírami, ale nedařilo se mi to moc
Quick91
Profil *
Alphard:
Ahoj, mohl by jsi mi prosim ukazat to tve reseni, stale neco pisu v PHP, ale vysledek neni spravny :/ V PHPcku delam s timto projektem poprve
Keeehi
Profil
function timeToInt($time) {
    $parts = explode(":",$time);
    return $parts[0] * 3600 + $parts[1] * 60 + $parts[2];
}

$vstup = array("11:00:00","11:30:00","12:00:00","15:00:00","15:30:00");

$predchozi = false;
foreach ( $vstup as $cas ) {
    if ( $predchozi === false ) {
        $vystup = array($cas);
        $predchozi = timeToInt($cas);
    } else {
        if ( timeToInt($cas) - $predchozi == 30 * 60 ) {
            $predchozi = timeToInt($cas);
        } else {
            $vystup[] = $predchozi;
            $predchozi = timeToInt($cas);
            $vystup[] = $predchozi;
        }
    }
}

if ( $count($vystup) % 2 == 1 ) {
    $vystup[] = $predchozi;
}

// výsledkem je pole array("začátek 1", "konec 1", "začátek 2", "konec 2", "začátek 3", "konec 3", ....)
Tori
Profil
Quick91:
Kdybyste měl v DB uložené všechny časy, kdy je možné hřiště rezervovat, tak se volné časy najdou jedním dotazem - inspirace zde: hloupy dotaz - mysql - vyhazeni vsech vyskytu v druhym slupci. Někde tu byl dotaz konkrétně na rezervace časů a dohledání volných intervalů, který už nemůžu bohužel najít, ale myslím že se tam porovnávaly zrovna tyhle dvě varianty - načíst z DB všechny rezervace pro dané datum a zpracovat v PHP vs. uložit do DB všechny možné časy a načíst jen volné.

Mimo dotaz: u datepickeru se myslím dá nastavit, aby se daly vybrat jen budoucí datumy. Pak byste to upozornění mohl dát do <noscript>u.
Alphard
Profil
Quick91:
Odpověděl bych, ale viděl jsem jen první část [#4] Quick91, diskuse není chat, pište najednou. Teď už odpověděl [#6] Keeehi. Ten algoritmus vypadá použitelně, jen si tam musíte dodělat přičtení půlhodiny k poslední mezi intervalu, abyste to měl dle požadavků [#1], současná podoba ukládá vždy ty počáteční.

[#7] Tori
Do toho vlákna jsem myslím psal taky, konkrétně že ukládat všechna data je spíš cesta do pekel. Ty tady ale asi myslíš jen ukládání rezervací, to by mohlo mít menší paměťové nároky, přesto bych to asi nepreferoval.
Tori
Profil
Alphard:
Ty tady ale asi myslíš jen ukládání rezervací,
Tak, ne všechny existující možnosti a jejich stav, ale jen rezervovatelné časy (pro jeden den) + do další tabulky zamluvené rezervace. Co by tam vlastně bylo lepší: datum + čas samostatně, nebo datum + ID času (FK)?
Quick91
Profil *
Tori:
Moc děkuji za algoritmus. Bohužel je tam někde ukrytá chybka, které pro $vystup[0] vrati pocatecni hodnotu, ale $vystup[1] mi vraci cislo 68400.
Při vypsání pole pomocí print_r($vystup) to pro souvsly vyber casu vypise jen 2hodnotu, tu prvni spravnou a tu druhou(68400) :(
Chyba je v tomto: return $parts[0] * 3600 + $parts[1] * 60 + $parts[2];, nechybí tomu dodělat ještě převod z čísla zpět na čas?
Alphard
Profil
[#10] Quick91
Je tam pár překlepů, něco jsem na tom testoval, tady je mírně upravená verze, pořád ale ne do podoby, kterou chcete (přičtení půlhodiny ke konečné hodnotě):
<?php
function timeToInt($time) {
    $parts = explode(":",$time);
    return $parts[0] * 3600 + $parts[1] * 60 + $parts[2];
}
 
$vstup = array("11:00:00","11:30:00","12:00:00","15:00:00","15:30:00","17:30:00");
 
$predchozi = false;
foreach ( $vstup as $cas ) {
    if ( $predchozi === false ) {
        $vystup = array($cas);
        $predchozi = $cas;
    } else {
        if ( timeToInt($cas) - timeToInt($predchozi) == 30 * 60 ) {
            $predchozi = $cas;
        } else {
            $vystup[] = $predchozi;
            $predchozi = $cas;
            $vystup[] = $predchozi;
        }
    }
}
 
if ( count($vystup) % 2 == 1 ) {
    $vystup[] = $predchozi;
}

var_dump($vystup);

array (size=6)
  0 => string '11:00:00' (length=8)
  1 => string '12:00:00' (length=8)
  2 => string '15:00:00' (length=8)
  3 => string '15:30:00' (length=8)
  4 => string '17:30:00' (length=8)
  5 => string '17:30:00' (length=8)

Tori:
Měl jsem tady rozepsanou odpověď, ale vlastně nevím. Z hlediska návrhu db by asi bylo lepší odkazovat se na id času (když už někde existuje, ať je přímá vazba), ale nevím, jestli s tím prakticky nebude víc problémů než užitku. Záleží, jak by se s tím pracovalo.
Tori
Profil
Alphard:
No mně pak ještě došlo, že kdyby si zadavatel později vymyslel, že chce umožnit rezervace libovolně dlouhých intervalů (třeba 10:12 - 10:33) tak u vaší verze se zpracováním v PHP by nebylo potřeba skoro nic měnit by se to asi líp zpracovalo v PHP než přes DB, protože ta druhá verze (uložený seznam rezervovatelných časů) by se musela zcela překopat. Takže z toho hlediska je váš přístup výhodnější.
Tori
Profil
Další alternativa:
$tmp = array();
foreach($vstup as $val) {
    $parts = explode(":", $val);
    $tmp[] = $parts[0] * 3600 + $parts[1] * 60 + $parts[2];
}

$probiha = false;
$j = 0;
$vystup = array();

for ($t = strtotime('1970-01-01 '.reset($vstup)); $t <= end($tmp); $t += 30*60) {
    if ($t == $tmp[$j]) {
        if (!$probiha) { $vystup[] = $vstup[$j]; }
        $probiha = true;
        $j++;
    } elseif ($probiha) {
        $vystup[] = gmdate('H:i:s', $t);
        $probiha = false;
    }
}
$vystup[] = gmdate('H:i:s', $t);

var_dump($vystup);
Quick91
Profil *
Moc děkuji za algoritmy, moc mi to pmohlo a tento poblém je již zdárně vyřešen :)

Celkové řešení mám podle již výše zmíněného, ale ještě jsem doplnil o funkci intToTime
function timeToInt($time) {
    $parts = explode(":",$time);
    return $parts[0] * 3600 + $parts[1] * 60 + $parts[2];
}

function intToTime($time) {
   if(($time % 3600) == 0) { 
    $part1 = $time/3600;
    $part2 = ($time-$part1*3600)/60;
    $part3 = $time - $part1*3600 - $part2*60;
    } else {
    $part1 = ($time/3600) - (1/2); 
    $part2 = (($time-$part1*3600)/60);
    $part3 = $time - $part1*3600 - $part2*60;
    }
    return str_pad($part1, 2, "0").":".str_pad($part2, 2, "0").":".str_pad($part3, 2, "0");
}


$vstup = explode(",", $policko);

 
$predchozi = false;
foreach ( $vstup as $cas ) {
    if ( $predchozi === false ) {
        $vystup = array($cas);
        $predchozi = $cas;
    } else {
        if ( timeToInt($cas) - timeToInt($predchozi) == 30 * 60 ) {
            $predchozi = $cas;
        } else {
            $vystup[] = intToTime((timeToInt($predchozi))+30*60);
            $predchozi = $cas;
            $vystup[] = $predchozi;
        }
    }
}
 
if ( count($vystup) % 2 == 1 ) {
    $vystup[] = intToTime((timeToInt($predchozi))+30*60);
}

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0