Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Jak obliczyć wiek po dacie urodzin funkcją PHP?
Forum PHP.pl > Forum > Przedszkole
AmyLokmart
Mam funkcję: date_modify(), date_format(), date_date_set() i substr()

Zbudowałam taki kod:

  1. // Separate parts date for read database
  2. $month->date_date_set = "%m";
  3. $days->date_date_set = "%d";
  4. $year->date_date_set = "%y";
  5. // Start count old
  6. $date = date_create("1974-11-11");
  7. date_modify($date,"-2022 year" . date_date_set('/*%y*/') . " -11 month " . date_date_set('/*%m*/') . "-11 days" . date_date_set('/*%d*/'));
  8. echo "Mam " . substr(date_format($date,"Y"), 3) . " lat.";


Wypisuje co prawda: "Mam 49 lat.", ale po zmianie treści, które zawierają inne dane związane z datą urodzin odczytywane w całości z bazy danych (to znaczy CAŁĄ DATE: 1974-11-11, a nie jej części np: 1974 rok z jednego wiersza, 11 miesiąc z innego wiersza, 11 dzień jeszcze z innego wiersza) - chciałabym, aby działało obliczenie wieku w całości, najlepiej bez ręcznych zmian wywoływanych przez funkcję date_modify() oraz bez stosowania oddzielnych zmiennych dla części składowych daty. Nie podoba mi się też użycie funkcji substr() -> została ona użyta na siłę, by wymóc końcowy wynik niezgrabnego obliczenia: "-0049".

Czy ktoś wie jak to zmodyfikować, aby funkcja z podanej daty urodzin obliczyła wiek osoby, ale w całości?

Dziękuję za sugestie, podpowiedzi, ewentualne rozwiązania smile.gif
trueblue
Nie wiem czy Twój mentor akceptuje krótkie i stosowne rozwiązania, ale:
- w MySQL jest funkcja DATEDIFF, wystarczy dodać dzielenie przez 365 i rzutować wynik na integer (w MySQL lub PHP),
- w PHP mamy https://www.php.net/manual/en/datetime.diff.php
AmyLokmart
"trueblue", a możesz napisać mi jak by wyglądał taki kod SQL dla mojej bazy danych?

Datę urodzin mam w tabeli: birthdate (wiersze: id, date)

database
-> birthdate
->->id(1)
->->date(1974-11-11)

A może coś trzeba w bazie ustawić? Na razie się tego uczę i umiem tylko zrobić takie podstawowe rzeczy: utworzyć bazę, tabelę, wiersz, aktualizować wiersze, kasować wiersze i zmieniać kodowanie.

Uznałam, że jak już od dłuższego czasu tworzę w php to znajdę proste rozwiązanie i nie będę musiała grzebać w innych rzeczach.


Po zastosowaniu kodu z dokumentacji PHP

  1. $origin = new DateTime('1974-11-11');
  2. $target = new DateTime('2022-04-27');
  3. $interval = $origin->diff($target);
  4. echo $interval->format('%R%a days');


Wypisało wynik:

  1. +17334 days


A chciałabym, aby wypisało wynik

  1. Mam 49 lat.


Czy podany przykład posiada jakiś brak? Może podany zestaw funkcji oblicza datę łącząc wszystkie dni nie uwzględniając separacji tego wyniku, no i te "diff" mi się nie podoba. Coś tu jest nie tak, takie mam wrażenie sad.gif
Salvation
A jak masz tą datę zapisaną w bazie danych? Rozumiem, że chcesz pętlą przelecieć po danych stamtą?

Skoro już poszłaś w backend, to muszę Cię zmartwić, ale znajomość komunikacji z bazą danych jak i samych zapytań SQL to must-have backend developera wink.gif
Do tego dochodzą jeszcze inne rzeczy: m.in. protokól HTTP czy całe security.
AmyLokmart
Data urodzin w bazie danych zapisana jest za pomocą metody: varchar, choć wcześniej miałam ustawione na metodę: datetime (jednak, kiedy miałam tak wcześniej ustawione to baza danych przesyłała po odczycie "napakowaną datę" to znaczy 00 00 00 2022-11-11 14:00:00:00 - zbijałam ciąg funkcjami php i w pewnym momencie uznałam, że to za bardzo komplikuje mi obliczenia i zabiera więcej pamięci dla bazy danych, a ja chcę zapisać 2 miliony dat urodzin, które mam na razie w pliku. Teraz testuje to dla jednej daty, aby móc zapisać resztę z przekonaniem, że obliczanie wieku działa mi poprawnie.

Podstawowe rzeczy związane z bazą danych i php, oraz połączeniem tego umiem zrobić. Nie umiem zrobić takich rzeczy,które rzadko są stosowane. Dopiero wtedy interesujemy się rzadko stosowanymi rzeczami, kiedy nam są potrzebne. A przecież lepiej nauczyć się później niż w ogóle prawda? smile.gif
phpuser88
  1. $date = "1974-11-11";
  2. $dzis = date("Y-m-d");
  3. $wiek = $dzis - $date;
  4. echo $wiek; //48
gino
date w bazie zapisuje się się pomocą typu DATE, żadne varchar, text i inne wynalazki
Salvation
Cytat(AmyLokmart @ 27.04.2022, 20:37:43 ) *
(...) wcześniej miałam ustawione na metodę: datetime (jednak, kiedy miałam tak wcześniej ustawione to baza danych przesyłała po odczycie "napakowaną datę" to znaczy 00 00 00 2022-11-11 14:00:00:00 - zbijałam ciąg funkcjami php (...)

Data właśnie powinna mieć typ pola jako datetime, bo masz tam więcej przydatnych informacji (np. timezone). Wtedy odczyt z bazy i wrzucenie jej choćby do obiektu \DateTime() to chwila, i masz większość operacji z datą z głowy, bo obiekt dostarcza własne metody. Teraz masz takie kwiatki i zagwozdki biggrin.gif

Wracając do tematu. Skoro datę masz jako zwykły string, to rozbij ją sobie regexem po stronie PHP lub zapytaniem w SQL na rok, miesiąc i dzień, a później zerknij tutaj: https://www.php.net/manual/en/class.datetimeimmutable.php wink.gif

Powodzenia! I czekamy na update z progressu.
nospor
Cytat
Data urodzin w bazie danych zapisana jest za pomocą metody: varchar, choć wcześniej miałam ustawione na metodę: datetime (jednak, kiedy miałam tak wcześniej ustawione to baza danych przesyłała po odczycie "napakowaną datę" to znaczy 00 00 00 2022-11-11 14:00:00:00 - zbijałam ciąg funkcjami php i w pewnym momencie uznałam, że to za bardzo komplikuje mi obliczenia

To nie mozliwe ze datetime zwracalo ci jakies 00 00 00 na poczatku. Zwyczajnie zrobilas jakis blad
Poza tym skoro to urodziny czyli data to nie zadne datetime tylko date

Cytat
zabiera więcej pamięci dla bazy danych, a ja chcę zapisać 2 miliony dat urodzin, które mam na razie w pliku.

Kolejna bzdura. No po co wymyslac takie rzeczy nie znajac sie w ogole w temacie?
Pole typu DATE zajmuje tylko 3 bajty, podczas gdy VARCHAR do zapisania daty zajmie ci 10 bajtow czyli ponad 3 razy wiecej. Wiec jakim cudem stosujac VARCHAR oszczedzasz pamiec?


Cytat
Nie umiem zrobić takich rzeczy,które rzadko są stosowane. Dopiero wtedy interesujemy się rzadko stosowanymi rzeczami, kiedy nam są potrzebne. A przecież lepiej nauczyć się później niż w ogóle prawda? smile.gif

I kolejny blad, gdyz operacje na datach sa dosc czesto stosowane wink.gif

Cytat
Wracając do tematu. Skoro datę masz jako zwykły string, to rozbij ją sobie regexem po stronie PHP lub zapytaniem w SQL na rok, miesiąc i dzień, a później zerknij tutaj: https://www.php.net/manual/en/class.datetimeimmutable.php wink.gif

Salvation no miejze litosc. Po grzyba tam jakis regexp a juz tymbardziej skoro i tak potem proponbujesz obiekt DATETIME ktory spokoknie wezmien 2022-11-11 bez zadnego regexpa
Poza tym rozwiazania juz podano na samym poczatku
trueblue
Cytat(AmyLokmart @ 27.04.2022, 20:21:24 ) *
"trueblue", a możesz napisać mi jak by wyglądał taki kod SQL dla mojej bazy danych?

Po zastosowaniu kodu z dokumentacji PHP

  1. $origin = new DateTime('1974-11-11');
  2. $target = new DateTime('2022-04-27');
  3. $interval = $origin->diff($target);
  4. echo $interval->format('%R%a days');


Wypisało wynik:

  1. +17334 days


A chciałabym, aby wypisało wynik

  1. Mam 49 lat.


Czy podany przykład posiada jakiś brak? Może podany zestaw funkcji oblicza datę łącząc wszystkie dni nie uwzględniając separacji tego wyniku, no i te "diff" mi się nie podoba. Coś tu jest nie tak, takie mam wrażenie sad.gif


  1. SELECT DATEDIFF(CURDATE(),'1974-11-11')/365

Rzutowanie w MySQL wykonuje się poprzez CAST.

  1. $origin = new DateTime('1974-11-11');
  2. $target = new DateTime('2022-04-27');
  3. $interval = $origin->diff($target);
  4. echo $interval->format('%y lat');

W linku, który podałem można dotrzeć do dokumentacji, którą warto czytać: https://www.php.net/manual/en/dateinterval.format.php
Salvation
Fakt, za dużo pracy na dzisiaj ewidentnie... Aczkolwiek regex też się przydaje w pracy, więc akurat do nauki tongue.gif
nospor
Cytat(Salvation @ 27.04.2022, 20:35:17 ) *
Fakt, za dużo pracy na dzisiaj ewidentnie... Aczkolwiek regex też się przydaje w pracy, więc akurat do nauki tongue.gif

No ale nie mieszaj w glowie osobie, ktora ledwo ogarnia podstawy wink.gif
AmyLokmart
Dziękuję chłopaki za podpowiedzi i sugestie. smile.gif

Odnośnie ustawień w bazie danych co do metod: date i datetime - Nie potrzebuję zapisywać daty urodzin w formatach obsługiwanych po przez te metody, ponieważ założenie skryptu ma działać w string'u. Właśnie to odkryłam w mojej aplikacji. Jeśli data zapisana będzie za pomocą date lub datetime wówczas nie będę mogła wykonać innych funkcji w aplikacji i przyłączyć dodatkowych informacji do zmiennych. Samo date lub datetime, kiedy wykonuje osobno to działa bez zarzutu smile.gif Dlatego postanowiłam zmienić na varchar. Skoro varchar zabiera więcej pamięci zapisując mniej niż date i datetime to chyba jestem głupia z logicznego myślenia. Pomijając to zastanowiłam się nad skryptem php i napisałam tak:

  1. // Actual date
  2. $date_2 = date_create(date('Y-m-d'));
  3. // Read Parser Date from string
  4. $date_1 = date_create(str_replace('-->', '', trim(ltrim(rtrim(strstr(strstr(str_replace('<div class="hit__name">', '<!--', str_replace('</div></div>', '-->', str_replace('<div class="hit__details hit__details--knowForFilm">', '<!--', str_replace('<span class="hit__personBirthDate" data-birthdate="', '', str_replace('"></span>', '', chop($actors_base[1]['date'])))))), '<!--<div', true), '-->', false), ' '), ' '), ' ')));
  5. $diff = date_diff($date_1, $date_2);
  6. // Separate Year to OLD
  7. $summary_separate = $diff->format("%a")/365+1;
  8. print "Wiek: " . strstr($summary_separate, '.', true) . " lat<br />";


W zmiennej $date_1 występuje:

  1. date_create(str_replace('-->', '', trim(ltrim(rtrim(strstr(strstr(str_replace('<div class="hit__name">', '<!--', str_replace('</div></div>', '-->', str_replace('<div class="hit__details hit__details--knowForFilm">', '<!--', str_replace('<span class="hit__personBirthDate" data-birthdate="', '', str_replace('"></span>', '', chop($actors_base[1]['date'])))))), '<!--<div', true), '-->', false), ' '), ' '), ' ')));


Powyższa funkcja odczytuje dane string'u po przez zmienną $actors_base[1]['date'], z którego usuwane są wybrane fragmenty kodu HTML. Zamiast tego można wstawić: date_create('1974-11-11');

Poniżej mój kod php:

  1. // Actual date
  2. $date_2 = date_create(date('Y-m-d'));
  3. // Read Parser Date from string
  4. $date_1 = date_create('1974-11-11');
  5. $diff = date_diff($date_1, $date_2);
  6. // Separate Year to OLD
  7. $summary_separate = $diff->format("%a")/365+1;
  8. print "Wiek: " . strstr($summary_separate, '.', true) . " lat.<br />";


Działa tak jak chciałam i do tego jak zmieniam kontent to także działa i liczy wiek bez błędów smile.gif
Działania na bazie z DIFF-coś tam sobie odpuszczę.

Pozdrawiam.
gino
O kurde (to do kodu)....
Sorki, ale jeżeli: "Odnośnie ustawień w bazie danych co do metod: date i datetime - Nie potrzebuję zapisywać daty urodzin w formatach obsługiwanych po przez te metody, ponieważ założenie skryptu ma działać w string'u" - to proponuję zmienić nauczyciela.
trueblue
Nie zaskoczyłaś mnie.
nospor
Cytat
Jeśli data zapisana będzie za pomocą date lub datetime wówczas nie będę mogła wykonać innych funkcji w aplikacji i przyłączyć dodatkowych informacji do zmiennych

No wlasnie o to chodzi ze bedziesz mogla

Cytat
e to chyba jestem głupia z logicznego myślenia

W tym wypadku nie chodzi o logiczne myslenie a o znajomosc jak dane typy sa przechowywane wewnetrznie przez baze.

Z jednej strony piszesz ze chcesz oszczedzac pamiec a potem i tak robisz to bez sensu 3 razy gorzej.

To wyglada mniej wiecej tak:

"Nie znam sie na tym co robie, ale wiem lepiej"

No to powodzenia zycze na dalszej drodze uprzykrzania sobie samej zycia programistycznego smile.gif
AmyLokmart
Dzięki chłopaki za Wasze wypowiedzi i pomoc. Przed wpisywaniem tematu na tym forum szukam informacji w internecie na innych stronach i pytam się też osób, które znam osobiście, a też programują. Nie zawsze czytam dokumentację, chyba, że naprawdę mi nie idzie i się wkurzam. Aplikacja, która mi pomaga w tworzeniu posiada dokumentację, w której pisze zupełnie co innego niż to co piszecie na forum, więc postanowiłam założyć temat dotyczący obliczania wieku po zadanej dacie urodzin. Koncepcja była prosta: aktualny czas odjąć czas urodzin podzielić przez 365 dni i dodać 1 równa się wynik. Z tym, że aplikacja posiada mechanizm filtrujący informację z bazy danych sprawdzający w jakich typach zostały te informacje zapisane. Jeśli typy te to: date, datetime wówczas aplikacja wypisuje kod błędu: 00 00 00 + wynik daty i blokuje wykonywanie niektórych funkcji. W zamyśle "blokuje wykonanie, niektórych funkcji" nie chodzi, o funkcje, które wykonuje serwer tylko ta aplikacja. Próbowałam w kodzie aplikacji to zmienić tak, aby odczytywało date lub datetime bez błędów i wówczas cała aplikacja świrowała, więc poprawki zmieniłam tak jak były. W komunikacie błędu ciągle było pokazane: "Złe użycie typów date, datetime dla zadanej daty" - zmieniłam te typy na "varchar" i zaczeło działać prawidłowo. Po zmianach typów mogę wykonywać funkcje, które wcześniej były zablokowane. W dokumentacji znalazłam kilka wyjaśnień tego problemu. Jednym z nich jest kwestia bezpieczeństwa, kiedy to użytkownik nie może korzystać z funkcji aplikacji i zapisywać danych lub je odczytywać w momencie złamania hasła. Są też pewne czynności, które trzeba zrobić po zalogowaniu się do aplikacji, aby system upewnił się, że to ty. Kolejne wyjaśnienie to takie, że zapisywane dane w typach date, datetime zajmują więcej miejsca niż w "varchar" z prostej przyczyny. Kiedy jest baza danych ustawiona na zapisanie danych typami date i datetime wówczas aplikacja zapisuje za każdym razem dodatkowe informacje w innych komórkach, które są niepotrzebne np: tytuły, wynik metod md5, sha, base64 dla zakodowanej części daty, język, autor itd. Ręcznie kasowałam te dane, ale one za każdym razem się tam pojawiały, gdy przełodowywałam aplikację. Usunęłam wszystkie wiersze z bazy danych, w których zapisywane były dane i aplikacja przestała działać. Kiedy typy: date i datetime zostały zmienione na varchar wówczas aplikacja datę zapisuje do tego typu, a pozostałych informacji nie. Dziwne jest to, że kiedy zaznaczam dodatkowe informacje, a w zasadzie odznaczam, aby nie były zapisywane to przy typach: date i datetime i tak je zapisze. Ogólnie dałabym sobie z tym spokój i po prostu stworzyła bazę danych z tabelą, w której byłaby komórka z typem: date lub datetime, napisałabym kod php, który łączy się z bazą, odczytuje datę, a potem ją liczy i wypisuje na stronie internetowej, ale ta aplikacja mi się podoba, bo ma wiele fajnych funkcji łącznie z generowaniem kodu. Dzięki niej zrobiłam wiele fajnych skryptów i rozwiązań, nawet takich co tu na forum uważane były za niemożliwe choćby automatyczne zapisywanie 2 milionów pozycji z zabezpieczonej bazy danych nie znając hasła i adresów seo do swojej bazy danych - udało mi się to zrobić i jestem z tego dumna.

Kochany "nespor" dzięki za uszczypliwość i za to, że tak wierzysz w pomaganie innym jednocześnie deprymując działanie osoby proszącej,o jakiąś pomoc lub podpowiedź, nie wiedząc jakie są szczegóły.
To tak jakby zapytać się człowieka, który skończył studia informatyczne - co to jest WiFi? Oczywiście studenciak, który zjadł wszystkie rozumy odpowie na to pytanie źle. A co zrobią ludzie np: moderatorzy forum? Pierwsze co sprawdzą w internecie co to jest, a potem napiszą w temacie zajebistą definicję. Jednak samemu to niczego od siebie nie napiszą.

Właśnie przeważnie (choć nie zawsze oczywiście) tak jest na tym forum: większość ludzi wysyła do dokumentacji, kopiuje i wkleja gotowy nie swój skrypt, ale naprawdę pomóc i wyjaśnić to już nie ma komu.

Jest mi przykro, ale wbrew temu co piszecie na tym forum ja się nie załamie i dalej będę tworzyła w PHP, bo mi się ten język podoba. Jedyne co jeszcze zrobię to podciągnę się ze SQL-u i bazy danych.

Pozdrawiam Serdecznie Tych co Szczerze pomagają na tym forum i nie stosują sarkazmu. Buziaki :*
nospor
Cytat
Kochany "nespor" dzięki za uszczypliwość i za to, że tak wierzysz w pomaganie innym jednocześnie deprymując działanie osoby proszącej,o jakiąś pomoc lub podpowiedź, nie wiedząc jakie są szczegóły.
To tak jakby zapytać się człowieka, który skończył studia informatyczne - co to jest WiFi? Oczywiście studenciak, który zjadł wszystkie rozumy odpowie na to pytanie źle. A co zrobią ludzie np: moderatorzy forum? Pierwsze co sprawdzą w internecie co to jest, a potem napiszą w temacie zajebistą definicję. Jednak samemu to niczego od siebie nie napiszą.

Slodkie... No to podsumujmy:
piszesz ze uzywasz VARCHAR bo masz bardzo duzo dat i VARCHAR zajmuje mniej miejsca niz DATE. Ja ci wyjasniem ze jestes w bledzie, ze VARCHAR na zapisanie daty potrzebuje 3 razy wiecej miejsca niz DATE. Ty w odpowiedzi, ze wg twojej logiki to jest zle. No to ja ci wyjasniam ze nie o logike tu chodzi tylko o fakty. i tak, dodaje zgryzliwie ze sie nie znasz ale i tak wiesz lepiej. Moze wiec zamiast szukac drzazgi w moim oku, to poszukaj belki w swoim wink.gif

Cytat
Pozdrawiam Serdecznie Tych co Szczerze pomagają na tym forum i nie stosują sarkazmu. Buziaki :*

A ja pozdrawiam tych ktorzy faktycznie przychodza na forum czegos sie dowiedziec a nie trwac w swojej blednej "logice". Buziaczki i usciski. Make love not war etc etc
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.