mktime(): Proč nefunguje počítaní dne jako 60*60*24?

Webdesign, HTML, CSS, Flash, PHP, ASP, .NET, JavaScript. Kritika www stránek na Smetišti.

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod Zbynas 9. 9. 2020 11:54

Narazil jsem na problém, vůbec netuším, co je špatně. Cca za dva měsíce od aktuálního data, pokud počítám jako každý další den navíc 60*60*24, tak se to za necelé dva měsíce podělá.

Kód: Vybrat vše
  for (
         $i=mktime(0,0,0,date('j'),date('n'),date('Y'));
         $i<mktime(0,0,0,date('j'),date('n')+60,date('Y'));
         $i+=(60*60*24)
       )
  {
      echo date('j.n.Y H:i',$i)."<br>";
  }


Vím, že mktime bude v roce 2030 obsolete, ale db zatím stojí na tomto, tak proto, alespoň zatím.

Výsledek kódu výše je: (problém začíná 1. 11. - ale nedávno to bylo 28. 10., takže nejde o konkrétní datum, ale spíše za jak dlouho)

Kód: Vybrat vše
9.9.2020 00:00
10.9.2020 00:00
11.9.2020 00:00
12.9.2020 00:00
13.9.2020 00:00
14.9.2020 00:00
15.9.2020 00:00
16.9.2020 00:00
17.9.2020 00:00
18.9.2020 00:00
19.9.2020 00:00
20.9.2020 00:00
21.9.2020 00:00
22.9.2020 00:00
23.9.2020 00:00
24.9.2020 00:00
25.9.2020 00:00
26.9.2020 00:00
27.9.2020 00:00
28.9.2020 00:00
29.9.2020 00:00
30.9.2020 00:00
1.10.2020 00:00
2.10.2020 00:00
3.10.2020 00:00
4.10.2020 00:00
5.10.2020 00:00
6.10.2020 00:00
7.10.2020 00:00
8.10.2020 00:00
9.10.2020 00:00
10.10.2020 00:00
11.10.2020 00:00
12.10.2020 00:00
13.10.2020 00:00
14.10.2020 00:00
15.10.2020 00:00
16.10.2020 00:00
17.10.2020 00:00
18.10.2020 00:00
19.10.2020 00:00
20.10.2020 00:00
21.10.2020 00:00
22.10.2020 00:00
23.10.2020 00:00
24.10.2020 00:00
25.10.2020 00:00
26.10.2020 00:00
27.10.2020 00:00
28.10.2020 00:00
29.10.2020 00:00
30.10.2020 00:00
31.10.2020 00:00
1.11.2020 00:00
1.11.2020 23:00
2.11.2020 23:00
3.11.2020 23:00
4.11.2020 23:00
5.11.2020 23:00
6.11.2020 23:00
7.11.2020 23:00


Opravil jsem to takto:
Kód: Vybrat vše
  for ($i=0;$i<60;$i++)
  {
       $d = mktime(0,0,0,date('j'),date('n')+$i,date('Y'));
       echo date('j.n.Y H:i',$d)."<br>";
  }


Proč tomu tak je? Proč ten první kód nefunguje? Může v tom být změna času, logicky, ale ten je 25. října, nikoliv 1. listopadu. Hm ...
NVidia GTX 1060 6GB, Intel Core i7-2600K @ 3,4 GHz, 16 GB DDR 3
Download 100 Mbps, Upload 100 Mbps, ping 8
VINOTÉKA U FREJKA
FREJK.CZ, FREJK.SK, FREJK.COM
Zbynas
Junior
Uživatelský avatar

Odeslat příspěvekod zivan 9. 9. 2020 13:30

Bude to zmena casu, proc az 1.11. netusim.

mktime() mela drive jeste atribut isDTS:
https://www.php.net/manual/en/function.mktime.php

Ted uz je zruseny, ale zkusil jsem ten tvuj kod vyhodnotit a pokud se pouzije starsi verze PHP a nastavi isDTS = 0, tak to funguje:
http://sandbox.onlinephpfunctions.com/c ... 1bf28eab32
Motorola Edge 20; HP Elitebook 845 G8 (Ryzen 5650U, 32GB RAM, WD SN570 1TB, 14" fullHD IPS) + HP USB-C G5 Essential + 29" LG 29UM65 + 22" Eizo S2202W
zivan
Junior

Odeslat příspěvekod JirkaVejrazka 9. 9. 2020 14:23

Ja PHP neznam, ale evidentne michas dohromady datumy a casy, coz je casta programatorska chyba. Musis se rozhodnout jestli pracujes s kalendarem (dny), nebo casem (hodiny). Dohromady se to moc dobre michat neda, i kdyz k tomu neprogramatorske mysleni dost svadi.
JirkaVejrazka
Mírně pokročilý


Odeslat příspěvekod Zbynas 9. 9. 2020 16:19

Však jsem psal, proč teď nemohu použít novější přístup. Vytahuji data ze staré DB, kde jsou uloženy data v mktime (jako int) a pracuji s nimi. Na změnu struktury DB je brzo kvůli jen formátu dat, ještě 10 let. :) To to do té doby vezmem z gruntu znovu :)
NVidia GTX 1060 6GB, Intel Core i7-2600K @ 3,4 GHz, 16 GB DDR 3
Download 100 Mbps, Upload 100 Mbps, ping 8
VINOTÉKA U FREJKA
FREJK.CZ, FREJK.SK, FREJK.COM
Zbynas
Junior
Uživatelský avatar

Odeslat příspěvekod Just_jo 9. 9. 2020 17:51

Ale php není databáze, takže v čem je problém? Je to jen zápis a vše jde předělat na jiný způsob použití stejných dat.

Nikde jsem neviděl ukázku uložených dat v db, tak těžko poradím.
Just_jo
Junior
Uživatelský avatar

Odeslat příspěvekod JirkaVejrazka 9. 9. 2020 18:52

Presne tak, co ma spolecneho format ulozeni dat v databazi s tim, jak pocitas dalsi dny?
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod Zbynas 10. 9. 2020 09:12

Jak jsem psal, v DB se datum ukládá v mktime do sloupce int.

Vytahuji data z tabulky dovolené.

Kód: Vybrat vše
$d_from = mktime(0,0,0,date(n),date(j),date(Y));
$d_to = mktime(0,0,0,date(n),date(j)+60,date(Y));
... WHERE date_from>='$d_from' and date_to<'$d_to' ...


Jak to chcete předělat, abych nemusel používat mktime?

A když už to takhle vytáhnu, můžu s tím dál pracovat v jiném formátu, ale proč ... to už je celkem jedno.
NVidia GTX 1060 6GB, Intel Core i7-2600K @ 3,4 GHz, 16 GB DDR 3
Download 100 Mbps, Upload 100 Mbps, ping 8
VINOTÉKA U FREJKA
FREJK.CZ, FREJK.SK, FREJK.COM
Zbynas
Junior
Uživatelský avatar

Odeslat příspěvekod JirkaVejrazka 10. 9. 2020 09:51

Nepocitat to jako
Kód: Vybrat vše
date(j)+60
ale spocitat datum nejakym lidskym zpusobem a potom ho prevest na format mktime ? Alespon tak bych to delal v jinem jazyce - ale jak jsem psal, PHP neumim.

EDIT: Neco jako ten treti priklad tady: https://thisinterestsme.com/php-convert-date-unix/
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod Zbynas 10. 9. 2020 10:13

A jsme u toho, zase to pak převedu na mktime ... takže na stránce budu pracovat místo s jedním formátem data, s několika ...

I když do budoucna by to mohlo dávat logiku, prostě se nahradí jen mktime za novější funkce, až se změní DB. Ale to bych spíše vyřešil jinak, vytvořil bych si vlastní funkci mktime a naprogromval bych jí tak, jako kdyby to byla ta pravá :)
NVidia GTX 1060 6GB, Intel Core i7-2600K @ 3,4 GHz, 16 GB DDR 3
Download 100 Mbps, Upload 100 Mbps, ping 8
VINOTÉKA U FREJKA
FREJK.CZ, FREJK.SK, FREJK.COM
Zbynas
Junior
Uživatelský avatar

Odeslat příspěvekod JirkaVejrazka 10. 9. 2020 10:21

Pokud pracujes primarne s mktime(), tak nepracujes s datumy ale s casem, coz je zasadni rozdil.

Ja to vzdavam. Nekdo dalsi?

EDIT: Kdyby ses chtel pobavit, precti si http://www.creativedeletion.com/2015/01 ... zones.html

EDIT2 Nebo jeste lepsi: https://gist.github.com/timvisee/fcda9b ... 06b4b923ca
JirkaVejrazka
Mírně pokročilý

Odeslat příspěvekod Zbynas 10. 9. 2020 10:52

Máš, jo, máš pravdu, uznávám. Ale dokud nedospějeme k tomu, že se vytvoří nová db a překopírují se všechna data, tak to nevyřešíme.
NVidia GTX 1060 6GB, Intel Core i7-2600K @ 3,4 GHz, 16 GB DDR 3
Download 100 Mbps, Upload 100 Mbps, ping 8
VINOTÉKA U FREJKA
FREJK.CZ, FREJK.SK, FREJK.COM
Zbynas
Junior
Uživatelský avatar

Odeslat příspěvekod Just_jo 10. 9. 2020 16:55

No tak začněme trošku popořadě:
1. kde jsi vzal info o obsolete pro mktime?
Je i ve verzi 7.0.0
Od verze 5.1.0 se označuje jako DEPRECATED pokud je použit parametr isDTS

2. pokud se odkazuješ na DB, tak by opravdu bylo vhodné napsat strukturu toho pole v DB.
Je to int? timestamp? varchar?

Existují např. fce strftime, strtotime, které mohou zpříjemnit práci.

Jak je nakládáno s tím seznamem dat? Je potřeba tam mít hodiny a minuty, nebo stačí jen datum bez času?

A teď vsuvka - oprava DB a příprava skriptu pro opravu dat do nové tabulky netrvá tak dlouho jako se šťourat v příšerným kódu.

A dodám, že mi tu celý kód ani obsah a strukturu v DB nevidíme a ani neznáme funkci toho skriptu. Takže bys mohl poslouchat co se ti tu radí namísto hledání výmluv proč to či ono nejde.

JirkaVejrazka: nejsi jediný :-D kvalita dotazů nevalně ustupuje
Just_jo
Junior
Uživatelský avatar

Odeslat příspěvekod Zbynas 11. 9. 2020 09:24

1) na nějakém php validačním webu, už nevím kde. Psali o obselete ve 2030.
2) potřetí říkám, že je to int

- funkce samozřejmě znám, jinde s nimi pracuji, ne tam, kde je datum v db uložené takto ... přijde mi divné to pořád konvertovat do jiných formátů

- je potřeba tam mít i hodiny a minuty
NVidia GTX 1060 6GB, Intel Core i7-2600K @ 3,4 GHz, 16 GB DDR 3
Download 100 Mbps, Upload 100 Mbps, ping 8
VINOTÉKA U FREJKA
FREJK.CZ, FREJK.SK, FREJK.COM
Zbynas
Junior
Uživatelský avatar

Odeslat příspěvekod Just_jo 11. 9. 2020 19:41

Po průzkumu mktime jsem zjistil, že při datetime_zone nastavení na UTC se tento problém nevyskytuje.

Při jiném nastavení ( např. Europe/Prague ) se vyskytuje jakási chyba. Pokud si vyzkoušíš jaký je číselný rozdíl unix timestampu dnů po sobě, tak zjistíš že ne každý den má 60*60*24 sekund. Našel jsem rozdíl mezi 2020-11-1 0:0:0 a 2020-11-2 0:0:0 - rozdíl hodina.

Takže z kódu, který jsi poslal je patrné že hodiny, minuty a sekundy tam nehrají roli ( když máš vždy nastaveno 0:0:0 ).
Takže pro příště používat přičítání dnů. Až budeš přičítat hodiny, pak to taky nedělej přes takovýto přístup.
Jednoduše si vytvoř objekt DATE s datem a přidávej tam časový nebo datumový údaj, jak jsem již zmiňoval v předchozím příspěvku ( tj. strtotime("+1 day", ... ) ).
Just_jo
Junior
Uživatelský avatar


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků