VulCode
Blog

Carbon: round(3600) zaokrągla do pełnej godziny, a nie tylko zeruje sekundy

Liczbowa precyzja w round(), floor() i ceil() oznacza liczbę sekund, ale od 60 w górę nie przenosiła się na minuty, godziny i dni. round(3600) zerował tylko sekundy.

DualFroz - VulCode CEODualFroz - VulCode CEO1 min czytania
Carbon: round(3600) zaokrągla do pełnej godziny, a nie tylko zeruje sekundy - DualFroz - VulCode CEO
Tytuł zmiany w repozytorium
fix: numeric round()/floor()/ceil() precision >= 60 seconds does not carry into minute/hour/day
Scalono
25.09.2026
Opisano tutaj
6.10.2026

Wpis powstał 11 dni po scaleniu zmiany.

Carbon
Technologie:PHPdaty i czas

Co nie działało

Carbon to biblioteka do dat w PHP, z której korzysta między innymi Laravel. Metody round(), floor() i ceil() przyjmują precyzję jako nazwę jednostki ('hour') albo jako liczbę, którą dokumentacja i testy opisują jako liczbę sekund. Dla wartości poniżej 60 wszystko działało, na przykład round(5) zaokrąglał do 5 sekund. Od 60 w górę wynik zostawał zamknięty w polu sekund:

Carbon::parse('2026-01-01 14:21:37')->round(3600)   -> 14:21:00 (zamiast 14:00:00)
Carbon::parse('2026-01-01 14:30:00')->ceil(3600)    -> 14:30:00 (zamiast 15:00:00)

Kod ustawiał dla liczbowej precyzji jednostkę second i zaokrąglał samą wartość sekund, która mieści się w zakresie 0-59. Przy precyzji 3600 wynik zawsze wychodził zero, a minuty i godziny nie były w ogóle ruszane. Ten sam błąd dotyczył zapisu '3600 seconds'.

Co zmieniliśmy

W roundUnit() liczbowa precyzja, która obejmuje całą następną jednostkę, jest przenoszona w górę: 3600 sekund to 60 minut, a 60 minut to godzina. Lista przejść zawiera tylko jednostki o stałej długości, więc precyzja w dniach nigdy nie jest przenoszona na miesiące, bo miesiące mają różną liczbę dni.

Jak to sprawdziliśmy

Nowy test porównuje wyniki liczbowej precyzji z wersją tekstową: round(3600) z round('hour'), round(120) z round('2 minutes'), round(86400) z round('day'), a do tego floor(3600) tuż przed pełną godziną i ceil(3600) w połowie godziny.

Efekt

Zmianę scalono 25 września 2026. Liczbowa precyzja zachowuje się w Carbonie tak samo jak odpowiadająca jej nazwa jednostki.

Rozszerzenie DateTime w PHP do pracy z datami, standard w ekosystemie Laravela.

Język
PHP
Gwiazdki na GitHubie
16 591

Te same wywołania przed zmianą i po niej

Przypadki z wpisu i z testu w pull requeście #3359: co powinno wyjść, co wychodziło przed poprawką i co wychodzi teraz.

WywołaniePowinno daćPrzed zmianąPo zmianieWynik
Wywołanieround(3600)na 2026-01-01 14:21:37
Powinno dać14:00:00
Przed zmianą14:21:00
Po zmianie14:00:00
Zgodne z oczekiwanym
Wywołanieceil(3600)na 2026-01-01 14:30:00, w połowie godziny
Powinno dać15:00:00
Przed zmianą14:30:00
Po zmianie15:00:00
Zgodne z oczekiwanym
Wywołanieround(120)w teście obok wersji tekstowej
Powinno daćround('2 minutes')
Po zmianieround('2 minutes')
Zgodne z oczekiwanym
Wywołanieround(86400)w teście obok wersji tekstowej
Powinno daćround('day')
Po zmianieround('day')
Zgodne z oczekiwanym
Wywołaniefloor(3600)tuż przed pełną godziną
Powinno daćfloor('hour')
Po zmianiefloor('hour')
Zgodne z oczekiwanym

5 z 5 przypadków zgodnych z oczekiwanym

Co zmieniliśmy

W roundUnit() liczbowa precyzja, która obejmuje całą następną jednostkę, jest przenoszona w górę: 3600 sekund to 60 minut, a 60 minut to godzina.

Czego to nie rusza

Lista przejść zawiera tylko jednostki o stałej długości, więc dni nigdy nie są przenoszone na miesiące.

Czego nas to nauczyło

Zaokrąglanie czasu musi przenosić wynik na wyższe jednostki, tak jak dodawanie. Godzina zaokrąglona do pełnej godziny nie może skończyć się na 60 minutach.

Pytania o zmianę #3359

Gdzie jest zmiana, jak ją sprawdziliśmy i kto ją przyjął.