Autor | Zpráva | ||
---|---|---|---|
Marecek Profil * |
#1 · Zasláno: 5. 4. 2013, 12:19:53 · Upravil/a: Marecek
Dobrý deň,
potreboval by som zistiť rozdiel medzi dvoma dátumami, vytvoril som si na to funkciu.. function pocetDni($from, $to) { $first_date = strtotime($from); $second_date = strtotime($to); $offset = $second_date - $first_date; return floor($offset/60/60/24); } Funkcia je síce fajn ale stále mám 2 problémy.. 1., ak dáte napr. pocetDni("2013-03-30", "2013-04-30") vráti 30 čo v určitej situácií je ok ale ja reálne chcem aby zahrnul aj prvý deň (30.03-2013) a posledný deň (30.04.2013) teda správne by to malo byť 32. Chcem to vyriešiť nejako inteligentne, teda nie natvrdo +2.. príde mi to ako "nepekné" riešenie.. 2. Druhá vec sú dátumy ktoré trvajú dlhšie obdobie, napr. pocetDni("2005-04-20", "2013-04-30") vráti 2932, ak si odmyslím že neráta aj začiatočný a konečný deň tak by to podľa mojich prepočtov malo byť 2931 (s tými dňami 2933).. predpokladám že problém je v prestupných rokoch ale vôbec nemám predstavu ako to vyriešiť.. ďakujem za prípadnú radu, námet.. poznámka, funkciu datediff použiť nemôžem verzia php je 5.2... a ďalšia vec je že by som v prípade že počet dní je väčší ako rok, potreboval urobiť prevod na roky a zbytok v dňoch napr. pocetDni("2013-03-30", "2013-04-30") a výsledok by bol 8 rokov a xx dní. |
||
ShiraNai7 Profil |
Vyzkoušej tohle. Funkce vrací pole. První prvek (0) je počet roků, druhý (1) počet dnů.
Formátování do řetězce "x roků a x dnů" nechám na tobě. Použít ji můžeš například takto: list($roky, $dny) = pocetDni('datum od zde', 'datum do zde');
function pocetDni($from, $to) { $from = new DateTime($from); $to = new DateTime($to); $fromYear = $from->format('Y'); $toYear = $to->format('Y'); $fromDay = 1 + $from->format('z'); $toDay = 1 + $to->format('z'); if ($toYear < $fromYear || $toYear == $fromYear && $toDay < $fromDay) { throw new InvalidArgumentException('Invalid dates - "to" must be greater than or equal to "from"'); } if ($toYear === $fromYear) { return array(0, 1 + $toDay - $fromDay); } else { $yearCount = $toYear - $fromYear - 1; $dayCount = date('z', mktime(12, 0, 0, 12, 31, $fromYear)) - $fromDay + $toDay; if ($dayCount == date('z', mktime(12, 0, 0, 12, 31, $toYear))) { $dayCount = 0; ++$yearCount; } elseif ($dayCount >= 365) { $yearCount += floor($dayCount / 365); $dayCount %= 365; } return array($yearCount, $dayCount); } } Zkouška: var_dump(pocetDni('2013-03-30', '2013-04-30')); Výsledek: array(2) { [0]=> int(0) [1]=> int(32) } Zkouška: var_dump(pocetDni('2013-03-30', '2014-04-30')); Výsledek: array(2) { [0]=> int(0) [1]=> int(395) } Zkouška: var_dump(pocetDni('1999-03-01', '2013-03-01')); Výsledek: array(2) { [0]=> int(14) [1]=> int(0) } |
||
Joker Profil |
#3 · Zasláno: 5. 4. 2013, 13:35:35
ShiraNai7:
Ta funkce ale nebere ohled na přestupné roky. Například od 1. 3. 1999 do 1. 3. 2013 je to přesně 14 let, ale ta funkce vrátí 14 let a 5 dní. Krom toho „První prvek (0) je počet roků nebo null “ je podivný mechanismus fungování, očekával bych, že to bude prostě počet roků (tj. žádný rok bude 0).
|
||
Marecek Profil * |
#4 · Zasláno: 5. 4. 2013, 13:42:41
Díky ShiraNai7, ale nefunguje to tak ako Joker píše..
|
||
Camo Profil |
Môžem sa spýtať, prečo je problém tam pričítať tie dva dni?
A aby som aj niečím prispel, tak je tu ešte taká exotická možnosť použiť MySQL. SELECT DATEDIFF('2013-3-1','1999-3-1') AS DiffDate; |
||
ShiraNai7 Profil |
Joker, Marecek:
Funkci jsem upravil. Teď vrací počet skutečných kalendářních roků (nebo 0) v daném rozsahu a počet dnů. Pro rozsah 1. 3. 1999 do 1. 3. 2013 už vrací 14 let a 0 dnů. |
||
Marecek Profil * |
#7 · Zasláno: 5. 4. 2013, 15:53:21
Camo:
„Môžem sa spýtať, prečo je problém tam pričítať tie dva dni?“ nie je to problém, ale nepríde mi to ako systémové riešenie.. skôr ako taká záplata. Vyriešiť tie dva dni viem, skôr išlo o tú prácu s prestupným rokom „A aby som aj niečím prispel, tak je tu ešte taká exotická možnosť použiť MySQL.“ nechcel som to riešiť v db ShiraNai7: „Funkci jsem upravil. Teď vrací počet skutečných kalendářních roků (nebo 0) v daném rozsahu a počet dnů.“ vďaka, vážne si cením snahu, ale nie je to ono, od 01.04.2006 do 14.04.2011 vráti 4 roky a 377 dní, čo sám musíš uznať že je kravina.. Moje aktuálne riešenie je poskladané s funkcie ktorú som našiel tu a nejakých mojich poznatkov, ktoré som vypátral.. function pocetDni($start, $end) { $day = 86400; $sTime = strtotime($start); $eTime = strtotime($end); $pocet = round(($eTime - $sTime) / $day) + 1; if(($pocet /365.25) >= 1) { $roky = floor($dni/365.25); $pocet = $pocet - ($roky * 365.25); } else { $roky = "0"; } return array($roky, $pocet); } Výsledky vyzerajú relatívne uveriteľne ale nie som si tým 100% istý.. |
||
ShiraNai7 Profil |
Marecek:
„od 01.04.2006 do 14.04.2011 vráti 4 roky a 377 dní, čo sám musíš uznať že je kravina..“ Není to kravina, když počítáš jen skutečné kalendářní roky .. například 370 dní od poloviny tohoto roku je sice doba delší než 1 rok, ale celý kalendářní rok za to dobu neuplynul. Funkci jsem upravil, aby v tomto případě připočetla roky podle počet dnů / 365 (je to počet dnů napříč několika roky, v tomto případě nedává smysl brát ohled na přestupné roky). var_dump(pocetDni('2006-04-01', '2011-04-14')); Výsledek: array(2) { [0]=> float(5) [1]=> int(12) } „Výsledky vyzerajú relatívne uveriteľne ale nie som si tým 100% istý..“ To nebuď.. na řádku 5 máš $dni namísto $pocet a nepočítáš s přestupnými roky. Nevím, proč jsi tedy pozitivně reagoval v #4 na Jokerovu poznámku o přestupných rocích a psal „skôr išlo o tú prácu s prestupným rokom“ když teď na ně kašleš taky. Výsledky tvé funkce (líta ti to +- den nebo víc): var_dump(pocetDni('2006-04-01', '2011-04-14')); /* array(2) { [0]=> float(5) [1]=> float(13.75) } */ var_dump(pocetDni('1999-03-01', '2013-03-01')); /* array(2) { [0]=> float(14) [1]=> float(1.5) } */ |
||
Majkl578 Profil |
Proč takové složitosti? Nestačí použít DateTime a diff?
$from = '2011-04-01'; $to = '2012-04-01'; $fromDT = new \DateTime($from); $toDT = new \DateTime($to); $diff = $toDT->diff($fromDT); var_dump($diff->days); // 366 - přestupní rok je zohledněn ----- Aha, až teď jsem si všiml, že je to pro staré PHP (5.2). Pardon. |
||
Joker Profil |
#10 · Zasláno: 5. 4. 2013, 19:13:10
ShiraNai7:
„Není to kravina, když počítáš jen skutečné kalendářní roky .. například 370 dní od poloviny tohoto roku je sice doba delší než 1 rok, ale celý kalendářní rok za to dobu neuplynul.“ To je svým způsobem pravda, ale běžně se takhle délka roku neurčuje. Ale přístup v té opravené verzi by měl být funkční, byť tu implementaci jsem detailně nezkoumal. Marecek: > „Môžem sa spýtať, prečo je problém tam pričítať tie dva dni?“ > nie je to problém, ale nepríde mi to ako systémové riešenie.. skôr ako taká záplata. Proč? Je to nejjednodušší řešení a neměl by s ním být žádný problém. A použít existující funkčnost pro výpočet dnů „mezi“ a potom připočíst ty krajní dny intervalu je určitě systémovější, než celý ten výpočet duplikovat. Majkl578: „Proč takové složitosti? Nestačí použít DateTime a diff?“ To píše hned na začátku, že na to nemá dost vysokou verzi PHP. |
||
Enko Profil * |
#11 · Zasláno: 6. 4. 2013, 02:34:00
Pokud je to ještě aktuální, našel jsem svoje několik let staré řešení. Posílám to komplet včetně použití.
<?php function get_time_difference($start, $end){ $uts['start'] = strtotime($start); $uts['end'] = strtotime($end); if($uts['start'] !== -1 && $uts['end'] !== -1){ if($uts['end'] >= $uts['start']){ $diff = $uts['end'] - $uts['start']; if($days = intval((floor($diff / 86400)))) $diff = $diff % 86400; if($hours = intval((floor($diff / 3600)))) $diff = $diff % 3600; if($minutes = intval((floor($diff / 60)))) $diff = $diff % 60; $diff = intval($diff); return(array('days'=>$days, 'hours'=>$hours, 'minutes'=>$minutes, 'seconds'=>$diff)); } else{ //trigger_error("Konečný datum a čas je starší než počáteční!", E_USER_WARNING); } } else{ //trigger_error("Zjištěno neplatné datum nebo čas!", E_USER_WARNING); } return(false); } //$row["end"] je datum konce a musi byt ulozena v numerickem formatu YYYY-MM-DD-HH-MM-SS $datum = explode("-", $row["end"]); $rok = $datum[0]; $mesic = $datum[1]; $den = $datum[2]; $hodina = $datum[3]; $minuta = $datum[4]; $sekunda = $datum[5]; $arr = get_time_difference("now", "$rok-$mesic-$den $hodina:$minuta:$sekunda"); //echo "Aukce konci "; //echo $den.". ".$mesic.". ".$rok." ".$hodina.":".$minuta.":".$sekunda; if($arr == false){ echo "Prodáno"; } else{ //nastaveni pádu ke dnům if($arr["days"] == "1"){$dny = "den";} elseif($arr["days"] == "2" or $arr["days"] == "3" or $arr["days"] == "4"){$dny = "dny";} else{$dny = "dnů";} //nastavení pádu k hodinám if($arr["hours"] == "1"){$hodin = "hodina";} elseif($arr["hours"] == "2" or $arr["hours"] == "3" or $arr["hours"] == "4"){$hodin = "hodiny";} else{$hodin = "hodin";} //nastavení pádu k minutám if($arr["minutes"] == "1"){$minut = "minuta";} elseif($arr["minutes"] == "2" or $arr["minutes"] == "3" or $arr["minutes"] == "4"){$minut = "minuty";} else{$minut = "minut";} //nastavení pádu k sekundám if($arr["seconds"] == "1"){$sekund = "sekunda";} elseif($arr["seconds"] == "2" or $arr["seconds"] == "3" or $arr["seconds"] == "4"){$sekund = "sekundy";} else{$sekund = "sekund";} //konec bude za if($arr["days"] > 0){ echo $arr["days"]. $dny ; echo " a "; echo $arr["hours"]. $hodin ; } elseif($arr["hours"] > 0){ echo $arr["hours"]. $hodin ; echo " a "; echo $arr["minutes"]. $minut ; } elseif($arr["minutes"] > 0){ echo $arr["minutes"]. $minut ; echo " a "; echo $arr["seconds"]. $sekund ; } else{ echo $arr["seconds"]. $sekund ; } } ?> |
||
Marecek Profil * |
#12 · Zasláno: 6. 4. 2013, 15:17:18
Dík moc, všem hlavne ShiraNai7.
To Enko: skúsim aj toto riešenie, už len tak zo zvedavosti.. dík Joker: > Proč? > Je to nejjednodušší řešení a neměl by s ním být žádný problém. A použít existující funkčnost pro výpočet dnů „mezi“ a potom připočíst ty krajní dny intervalu je určitě systémovější, než celý ten výpočet duplikovat. Nemyslel som niečo duplikovať, ide len o princípe.. nemám rád záplatovanie (ako to robí windows, urobia hotový systém, potom prídu na chybu a záplatujú). Mne osobne to tak príde. V tom vlákne odkiaľ som čerpal je funkcia ktorý načíta všetky dni medzi termínami do pola a následne ich zráta čím rovno povie presný počet dní.. to mi príde skôr ako systémové riešenie ale áno rozumiem čo píšeš.. je to len taký detail, na ktorý sa môže naše názory líšiť.. |
||
Camo Profil |
#13 · Zasláno: 6. 4. 2013, 16:03:08
Marecek:
Pričítať 2 nieje chyba. |
||
Časová prodleva: 12 let
|
0