Két dátum közti különbség megállapítása PHP-vel

Két dátum közti különbség megállapítása PHP-vel
2021-03-17T13:08:40+01:00
2021-05-20T23:40:12+02:00
2022-10-15T21:25:32+02:00
*deleted_23419333
Sziasztok!

Két dátum közti különbségre lennék kíváncsi az alábbiak szerint:

// percek 1 perce ... 59 perce // órák 1 órája ... 23 órája // napok 1 napja ... 364 napja // évek 1 éve ... x éve

PHP fájl:

$start_date = new DateTime ( $row [ 'check' ], new DateTimeZone ( "UTC" ) ); // 2021-03-17 11:30:00 $since_start = $start_date -> diff ( new DateTime ( "now", new DateTimeZone ( "UTC" ) ) ); // 2021-03-17 13:00:00 $m = $since_start -> i;

A $m kiírja a perceket, tehát működik, viszont a fenti példánál csak 30 percet ír ki, 90 perc helyett.
Mutasd a teljes hozzászólást!
Hali!

A $m kiírja a perceket, tehát működik, viszont a fenti példánál csak 30 percet ír ki, 90 perc helyett.

Azért, mert a DateInterval osztályú objektum (amit a DateTime osztály diff() metódusa ad eredményül) i tulajdonsága nem a különbséget adja vissza percben, hanem a különbség perc értékét. A példádban a két időpont különbsége nem 90 perc, hanem 1 óra és 30 perc (azaz, a h tulajdonság értéke 1 lesz, az i pedig 30).

Mit szeretnél pontosan? Ha két időpont közti különbséget intelligensen, szövegesen megjeleníteni, akkor nézz rá a csatolt függvényre, eléggé jól paraméterezhető (nézd meg a kommentet). Néhány példa:
$diff = dateTimeDiffText('2020-04-14 23:45:10', '2021-03-17 23:57:00', 'UTC'); // Eredmény: '11 hónapja' $diff = dateTimeDiffText(new \DateTime('2021-03-17 10:45:10'), new \DateTime('2021-03-17 23:57:00')); // Eredmény: '13 órája' $diff = dateTimeDiffText('2021-03-18 02:45:10', '2021-03-17 23:57:00', new \DateTimeZone('Europe/Budapest')); // Eredmény: '3 óra múlva' $diff = dateTimeDiffText(new \DateTime('2021-02-10 23:45:10'), new \DateTime('2021-03-17 23:57:00'), null, 'h'); // Eredmény: '840 órája' $diff = dateTimeDiffText('2025-02-16 21:49:10', '2021-03-17 23:57:00', null, 'full'); // Eredmény: '3 év, 10 hónap, 30 nap múlva' $diff = dateTimeDiffText('2025-02-16 21:49:10', '2021-03-17 23:57:00', null, 'full', '', 1); // Eredmény: '3 év, 10 hónap, 29 nap múlva' $diff = dateTimeDiffText('2025-02-16 21:49:10', '2021-03-17 23:57:00', null, 'full', 'h'); // Eredmény: '3 év, 10 hónap, 29 nap és 22 óra múlva' $diff = dateTimeDiffText(new \DateTime('2019-01-10 21:49:10'), '2021-03-17 23:57:00', null, 'full'); // Eredmény: '2 éve, 2 hónapja és 7 napja' $diff = dateTimeDiffText(new \DateTime('2019-01-10 21:49:10'), '2021-03-17 23:57:00', null, 'full', 's'); // Eredmény: '2 éve, 2 hónapja, 7 napja, 2 órája, 7 perce és 50 másodperce' $diff = dateTimeDiffText('2021-03-17 23:57:00', '2021-03-17 23:57:00'); // Eredmény: 'most' $diff = dateTimeDiffText(); // Eredmény: 'most'
Mutasd a teljes hozzászólást!
Csatolt állomány

  • Próbáld így:

    $m = $since_start -> h * 60 + $since_start -> i;
    Mutasd a teljes hozzászólást!
  • Rossz időzónát használsz.
    UTC ami angliai, míg nálunk + 1 óra van.
    Ezért a "now" UTC zóna szerint 1 órával kevesebb.
    Mutasd a teljes hozzászólást!
  • Hali!

    A $m kiírja a perceket, tehát működik, viszont a fenti példánál csak 30 percet ír ki, 90 perc helyett.

    Azért, mert a DateInterval osztályú objektum (amit a DateTime osztály diff() metódusa ad eredményül) i tulajdonsága nem a különbséget adja vissza percben, hanem a különbség perc értékét. A példádban a két időpont különbsége nem 90 perc, hanem 1 óra és 30 perc (azaz, a h tulajdonság értéke 1 lesz, az i pedig 30).

    Mit szeretnél pontosan? Ha két időpont közti különbséget intelligensen, szövegesen megjeleníteni, akkor nézz rá a csatolt függvényre, eléggé jól paraméterezhető (nézd meg a kommentet). Néhány példa:
    $diff = dateTimeDiffText('2020-04-14 23:45:10', '2021-03-17 23:57:00', 'UTC'); // Eredmény: '11 hónapja' $diff = dateTimeDiffText(new \DateTime('2021-03-17 10:45:10'), new \DateTime('2021-03-17 23:57:00')); // Eredmény: '13 órája' $diff = dateTimeDiffText('2021-03-18 02:45:10', '2021-03-17 23:57:00', new \DateTimeZone('Europe/Budapest')); // Eredmény: '3 óra múlva' $diff = dateTimeDiffText(new \DateTime('2021-02-10 23:45:10'), new \DateTime('2021-03-17 23:57:00'), null, 'h'); // Eredmény: '840 órája' $diff = dateTimeDiffText('2025-02-16 21:49:10', '2021-03-17 23:57:00', null, 'full'); // Eredmény: '3 év, 10 hónap, 30 nap múlva' $diff = dateTimeDiffText('2025-02-16 21:49:10', '2021-03-17 23:57:00', null, 'full', '', 1); // Eredmény: '3 év, 10 hónap, 29 nap múlva' $diff = dateTimeDiffText('2025-02-16 21:49:10', '2021-03-17 23:57:00', null, 'full', 'h'); // Eredmény: '3 év, 10 hónap, 29 nap és 22 óra múlva' $diff = dateTimeDiffText(new \DateTime('2019-01-10 21:49:10'), '2021-03-17 23:57:00', null, 'full'); // Eredmény: '2 éve, 2 hónapja és 7 napja' $diff = dateTimeDiffText(new \DateTime('2019-01-10 21:49:10'), '2021-03-17 23:57:00', null, 'full', 's'); // Eredmény: '2 éve, 2 hónapja, 7 napja, 2 órája, 7 perce és 50 másodperce' $diff = dateTimeDiffText('2021-03-17 23:57:00', '2021-03-17 23:57:00'); // Eredmény: 'most' $diff = dateTimeDiffText(); // Eredmény: 'most'
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • Hali!

    Rossz időzónát használsz.

    Csak annyi fontos, hogy a két időpont ugyanabba az időzónába essen, azon kívül lényegtelen az időzóna. Tök mindegy, hogy a '2021-03-17 11:30:00' és '2021-03-17 13:00:00' időpontok UTC, budapesti esetleg washingtoni időzónában vannak, a különbségük mindig 1 óra és 30 perc lesz.

    Mutasd a teljes hozzászólást!
  • Bár Tibor nem erre célzott, de nem teljesen mindegy, hogy melyik időzónát használod, mert más időzónákban máskor van a DST váltás (már ha van). Egyik időzónában lehet +-60 perc különbség ugyanazon két "dátum" között másik időzónához képest. (Azért írom idézőjelben, mert itt a zóna nélküli részre kell gondolni.)
    Mutasd a teljes hozzászólást!
  • Igen, arra akart célozni, hogy ő nem "UTC" zónában van, hanem "Europe/Budapest".
    Így a "now" UTC -ben nem ő órájának idejét, hanem Londoni időt veszi alapul.
    Ha a diff értéke két dátum, akkor mindegy milyen időzónát adunk meg, ha ugyan abba rögzítették.
    Én a default időzóna beállítását és használatát javaslom, nem sűrű van szükség különböző időzónákkal történő számolgatásra.

    <?php date_default_timezone_set('Europe/Budapest'); $start_date = new DateTime ("2021-03-18 07:00" ); $since_start = $start_date -> diff ( new DateTime ( "now") ); print_r($since_start); ?>
    Mutasd a teljes hozzászólást!
  • Hali!

    Igen, arra akart célozni, hogy ő nem "UTC" zónában van, hanem "Europe/Budapest".
    Így a "now" UTC -ben nem ő órájának idejét, hanem Londoni időt veszi alapul.

    A kérdező problémájának szempontjából ennek mennyi relevanciája van? Mindkét DateTime osztályú objektumot UTC időzónával példányosított. Ráadásul, még ha igazad is lenne, akkor sem tartalmazná a DateInterval osztályú objektum ($since_start) i tulajdonsága a 90-et, lévén, hogy „nem arra való”.

    Én a default időzóna beállítását és használatát javaslom, nem sűrű van szükség különböző időzónákkal történő számolgatásra.

    Nem is számol különböző időzónákkal.

    Mutasd a teljes hozzászólást!
  • Komolyan nem érted amit írtam!?
    Nem mindegy milyen időzónát add meg, mert ha eltér a $row [ 'check' ] készítésétől,
    akkor a NOW elfog csúszni 1 órát, és ha még jó is a dátum, de a megfigyelőként
    a NOW -ra a helyi időt nézi, megint elfog csúszni, mert UTC -nél -1 óra van,
    a mi európai időzónánkhoz képest.
    Ezért érdemes beállítani a helyi - használt default időzónát és azzal számolni.
    Akkor nincs, számolás - megfigyelési probléma, ez már is kizárható.

    Az i tulajdonságban tényleg nem lesz 90 mivel az a percet jelöli.
    y » év, m » hónap, d » nap, h » óra, i » perc, s » másodperc
    Vagy is 90 helyet h: 1 és i: 30, ezért is írtam mintában print_r() -t hogy vissza kapja minden értéket.

    Ha esetleg a percet akarja megkapni akkor a két dátumot time számmá konvertálja, kivonja egymásból, majd elosztja, és megkapja a percet.

    $time1 = strtotime("2021-03-18 09:00"); $time2 = strtotime("now"); $diff = floor(abs($time1-$time2)/60); print($diff);
    Mutasd a teljes hozzászólást!
  • Hali!

    Komolyan nem érted amit írtam!?

    Én tökéletesen értem – de úgy tűnik, hogy te nem érted azt, amit én írtam.

    Nem mindegy milyen időzónát add meg, mert ha eltér a $row [ 'check' ] készítésétől, akkor a NOW elfog csúszni 1 órát, és ha még jó is a dátum, de a megfigyelőként a NOW -ra a helyi időt nézi, megint elfog csúszni, mert UTC -nél -1 óra van, a mi európai időzónánkhoz képest.

    Szerintem, te valamit nagyon keversz (különösen, a nyitó hozzászólásban felvázolt probléma és példakód ismeretében):
    1. Nézd már meg – figyelmesen – a példakód első két sorát, különösen azoknak a végét (a kommenteket). Ott jelezte a kérdező, hogy azok az értékek vannak.
    2. Nézd már meg – figyelmesen – a példakód első két sorát, különösen a DateTime-példányosítások második paraméterét. Ott láthatod, hogy mindkét DateTime-objektumot UTC időzónával példányosította. Tehát, a $row['check'] értéke 2021-03-17 11:30:00 (tök mindegy, hogy miként/honnan jött – és akkor még nem is néztük, hogy MySQL/MariaDB esetén TIMESTAMP vagy DATETIME mező a forrás), a 'now' (fontos: nem keverendő a MySQL NOW() függvényével, mert ez a DateTime konstruktorának paramétere, sima sztring) hatására meg 2021-03-17 13:00:00 időpont lesz a második DateTime-példány „értéke”, mindkettő UTC időzónával.

    Adott két időpont (2021-03-17 11:30:00 és 2021-03-07 13:00:00), mindkettő ugyanazon időzónában (UTC). Akkor ismét kérdezem: miért fontos ez az egész időzónás keverésed, ha két konkrét, ugyanazon időzónában található időpont közötti különbséget szeretne megállapítani?

    Ezért érdemes beállítani a helyi - használt default időzónát és azzal számolni.

    Ez így is van (és minden, valamirevaló szerveren be is van megfelelően állítva) – de itt lényegtelen (lásd fentebb).

    Akkor nincs, számolás - megfigyelési probléma, ez már is kizárható.

    Mint ahogy' itt sincs számolási/megfigyelési probléma, már az időzónák tekintetében (lásd fentebb).

    Vagy is 90 helyet h: 1 és i: 30, ezért is írtam mintában print_r() -t hogy vissza kapja minden értéket.

    Valószínűsítem, hogy a kérdező tisztában van a DateInterval-osztályú objektum tulajdonságaival (már azoknak létezésével), így a print_r() használata legfeljebb megerősíti abban, hogy milyen tagváltozói vannak az osztálynak/objektumnak. Azt is valószínűsítem, hogy inkább a tulajdonságok értelmezésével lehet gond, ebben viszont a print_r() sem segít sokat. De OK, legalább látja.

    Ha esetleg a percet akarja megkapni akkor a két dátumot time számmá konvertálja, kivonja egymásból, majd elosztja, és megkapja a percet.

    Egyrészt, mi a fenének konvertálgasson, mikor DateInterval-osztállyal (illetőleg, a DateTime-osztály diff() metódusának használatával) egyszerűbb számolni: végigmegy a különbségeken egységenként, és az adott egységek értékeinek a kívánt egységhez szükséges váltószámával képzett szorzatait összegzi. Másrészt, szintén valószínűsítem, hogy nem ennyire egyszerű különbség-képzést szeretne (már csak a „Két dátum közti különbségre lennék kíváncsi az alábbiak szerint…” nyitó hozzászólás-kezdetre alapozva – de majd biztosan pontosítja). Harmadrészt, mennyivel jobb (vagy másabb) a te strtotime()-os megadásod (időzóna nélkül), mint a DateTime-példányosítások (ugyanazon időzóna megadásával)?

    Mutasd a teljes hozzászólást!
  • "mindkettő ugyanazon időzónában" igen, de ugyan az a megfigyelési pont is?
    lehet mindkettő ott ugyan abban, ha nem ugyan az a megfigyelési pont.
    A code UTC időzóna alapján számol, de a kérdést ki író Europe/Budapest időzónából figyeli.
    Tehát a NOW nem 13 óra hanem 12 óra, hiába van az ő óráján 13 óra.
    Mutasd a teljes hozzászólást!
    Csatolt állomány
  • Hali!

    igen, de ugyan az a megfigyelési pont is?
    lehet mindkettő ott ugyan abban, ha nem ugyan az a megfigyelési pont.

    Mi az a „megfigyelési pont”, mit értesz alatta?

    De OK, mondj példát arra, hogy két DateTime-osztályú objektumot létrehozva ugyanazzal az időzónával (UTC), az egyiknek megadott időpont-sztring legyen 2021-03-17 11:30: 00, a másiknak megadott időpont-sztring legyen 2021-03-17 13:00:00 (csak azért ne now, mert akkor értelemszerűen mindig az aktuális értéket veszi – de itt lényegtelen, mivel az időzóna ugyanaz), majd a két időpont különbségét véve, mikor fog mást eredményezni bármilyen szerveren futtatva. Tehát, legyen a következő kód:
    $timeStr1 = '2021-03-17 11:30:00'; $timeStr2 = '2021-03-17 13:00:00'; $tz = 'UTC'; $dt1 = new \DateTime($timeStr1, new \DateTimeZone($tz)); $dt2 = new \DateTime($timeStr2, new \DateTimeZone($tz)); $diff = $dt1->diff($dt2); print_r($diff);
    Ennek az eredménye mikor nem a következő lesz:
    DateInterval Object ( [y] => 0 [m] => 0 [d] => 0 [h] => 1 [i] => 30 [s] => 0 [f] => 0 [weekday] => 0 [weekday_behavior] => 0 [first_last_day_of] => 0 [invert] => 0 [days] => 0 [special_type] => 0 [special_amount] => 0 [have_weekday_relative] => 0 [have_special_relative] => 0 )
    Szóval, mikor függ ez a „megfigyelési pont”-tól (bármit is érts alatta)?

    Mutasd a teljes hozzászólást!
  • közben csatoltam mellé képet, nézd meg.
    Ő Europe/Budapest időzónából kéri hogy UTC NOW, ami hozzá képest -1 óra.
    Mutasd a teljes hozzászólást!
  • Hali!

    A code UTC időzóna alapján számol, de a kérdést ki író Europe/Budapest időzónából figyeli.
    Tehát a NOW nem 13 óra hanem 12 óra, hiába van az ő óráján 13 óra.

    Remélhetőleg, a DateTime-objektum értékét vizsgálta, és nem szemrevételezéssel feltételezett valamit.

    Ettől függetlenül, lényegtelen, hogy hol, milyen szerveren fut a kód, milyen „időzónából figyeli”, mivel a DateTime-objektumok létrehozásánál megadta ugyanazt az időzónát is, így semmilyen időzóna-keveredés nem lesz a két DateTime-objektum közti különbség diff() metódussal történő meghatározásánál. Függetlenül az értékektől (tehát, hogy egyik időpont egy konkrét időpont, míg a másik now) és a szerveren beállított időzónától.

    Mutasd a teljes hozzászólást!
  • Hali!

    közben csatoltam mellé képet, nézd meg.

    Láttam. Mondom, remélhetőleg értéket vizsgált – bár az, hogy a DateInterval-objektum i tagváltozója nem azt mutatja, amit elvár, ettől teljesen független (nem az időzóna a probléma).

    Ő Europe/Budapest időzónából kéri hogy UTC NOW, ami hozzá képest -1 óra.

    Ami teljesen irreleváns a probléma szempontjából. Ha a $row['check'] értéke 2021-03-17 11:30:00, a szkript futtatása pedig 2021-03-17 13:00:00 UTC-kor történik, tök mindegy, hogy milyen időzóna van a szerveren beállítva, milyen időzónából kéri/nézi, mindig ugyanazt az eredményt fogja kapni.

    Mutasd a teljes hozzászólást!
  • "Remélhetőleg, a DateTime-objektum értékét vizsgálta, és nem szemrevételezéssel feltételezett valamit."
    Pedig pont ezt mondom, ami a kérdés kiírásának ideje és az UTC NOW -ra mőgé írt feltételezett időpont, elég közeli értéke, ami a kérdés kiírásának hozzávetőleges megkezdés időpontja.
    Mutasd a teljes hozzászólást!
  • Fentbenn írták már a DateTime objektummal a megoldást, de ajánlom a megoldásra inkább a Carbon package-et. A problémádat könnyen megoldhatod vele, meg a PHP DateTime bizonyos bug-jai ki vannak javítva benne. Csak egy példa, hogy ha február 28-hoz adsz egy hónapot, akkor március 31-re mutat ami jó, de ha március 31-ből kiakarsz vonni egy hónapot, akkor a visszatérési érték nem február 28 lesz, hanem március 2-a. Ez pl. a Carbon-ban ki van javítva. 

    Persze ez csak egy lehetőség, feleslegesen ne méretezd túl, ha nem indokolja a projekt! :)
    Mutasd a teljes hozzászólást!
  • Köszönöm mindenkinek a hozzászólást és elnézést a késői reakciómért.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd