23. februar 2014 - 21:27Der er
18 kommentarer og 3 løsninger
Beregne alder i PHP problem
Kan det her i det hele taget lade sig gøre og evt. hvordan? Jeg spørger, fordi jeg flere steder på nettet har læst, at hvis datoen er fra før 1970, er det et problem og i min anedatabase er der jo flere datoer f.eks fra 1770 og fremad.
Men jeg har følgende 2 dato felter i min tabel, hvor fødselsdato og dødsdato bliver angivet:
birt_date og deat_date
Begge felter er oprettet i MySql som varchar 255. Det jeg ønsker ud fra de 2 felter (hvis det altså kan lade sig gøre) er at få fat i alderen, f.eks hvis en person er født 1770 og død 1825 - så er alderen på personen 55 år.
Jeg ved godt, der findes utallige script i php på nettet omkring emnet, men de beskriver ikke hvordan og hvorledes man beregner alder udfra 2 felter, derimod hvordan man beregner alt andet omkring datoer.
Det vil derfor glæde mig, hvis der er nogen af jer, der kan komme frem med en løsning på, hvordan jeg får fat i alderen, selv kender jeg ikke løsningen. mvh Erik
Hvad nu hvis, personen er født d. 1.12.1770 og døde 1.3.1825, så er personen jo kun 54 år. Skal du også have den, måske væsentlige detalje med?
I øvrigt vil jeg anbefale ikke at anvende "varchar" i MySql, men derimod "date". Så kan Mysql også regne på datoerne, herunder sortere og lave udtræk med betingelser.
Efter at have gennemlæst utallige script eksempler havde jeg godt nok en fornemmelse af, at det ville blive et problem eller umuligt. P.t lader jeg det ligge - men tusind tak for jeres svar - og send venligst et svar begge 2. mvh Erik
Jeg mener da ikke, at det behøver at være så svært. Hvis der ikke er nogen færdig funktion, der kan håndtere det (det ved jeg ikke), så kan du bare selv lave en.
1. Jeg vil gemme datoen i MySql med "date" i formatet yyyy-mmm-dd 2. Så vil jeg lave en PHP-funktion, der først kigger på årstallene og trækker dem fra hinanden. 3. Derefter skal vi have styr på, om dødsdagen i dødsåret ligger før fødselsdagen i fødselsåret. Hvis ja, skal der trækkes 1 år fra.
OK, leger lige lidt med det, og kan godt se, der er nogle udfordringer.
I hvilket format skriver du datoerne i MySql? Hvis du fx angiver en dato som "22.12.1770" - altså med et fast format med 2 tegn for dato, 2 tegn for måned og 4 tegn for år, så vil jeg nok mene, at det er forholdvis enkelt at lave en funktion til beregning af alderen.
I forlængelse af Arnes forslag med DateTime klassen, så er dette kopieret fra php.net:
<?php class Blar_DateTime extends DateTime {
/** * Return Date in ISO8601 format * * @return String */ public function __toString() { return $this->format('Y-m-d H:i'); }
/** * Return difference between $this and $now * * @param Datetime|String $now * @return DateInterval */ public function diff($now = 'NOW') { if(!($now instanceOf DateTime)) { $now = new DateTime($now); } return parent::diff($now); }
/** * Return Age in Years * * @param Datetime|String $now * @return Integer */ public function getAge($now = 'NOW') { return $this->diff($now)->format('%y'); } }
$birthday = new Blar_DateTime('1879-03-14');
echo '<p>Albert Einstein was on 2010-10-10 ', $birthday->getAge('2010-10-10'), ' years old.</p>'; // Result: <p>Albert Einstein was on 2010-10-10 131 years old.</p>
Når feltet er valgt til at være varchar 255 skyldes det, at data importeres via en gedcom parser til MySql. Og disse data kommer fra et slægtsprogram hvor dato'er ikke altid er præcise. F.eks kan der ud for en fødselsdato stå født ca. 1855 eller dødsdato kan måske bare skrives som et enkelt årstal f.eks 1827. Altså ingen eksagt dato - derfor varchar. Så det vil sige, at det faktisk er umuligt at lave feltet om til date i MySql - som foreslået - selvom det er det mest logiske.
#9 Har lige testet den mulige løsning, men desværre. Fejlen er :
Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): Failed to parse time string (deat_date) at position 0 (d): The timezone could not be found in the database' in C:\xampp\htdocs\include-9\indhold\slaegt\test.html:37 Stack trace: #0 C:\xampp\htdocs\include-9\indhold\slaegt\test.html(37): DateTime->__construct('deat_date') #1 C:\xampp\htdocs\include-9\index.php(96): include('C:\xampp\htdocs...') #2 {main} thrown in C:\xampp\htdocs\include-9\indhold\slaegt\test.html on line 37
Fejl: Fatal error: Uncaught exception 'Exception' with message 'DateTime::__construct(): Failed to parse time string (deat_date) at position 0 (d): The timezone could not be found in the database' in C:\xampp\htdocs\include-9\indhold\slaegt\test.html:37 Stack trace: #0 C:\xampp\htdocs\include-9\indhold\slaegt\test.html(37): DateTime->__construct('deat_date') #1 C:\xampp\htdocs\include-9\index.php(96): include('C:\xampp\htdocs...') #2 {main} thrown in C:\xampp\htdocs\include-9\indhold\slaegt\test.html on line 37
Jeg har lige lavet en seriøs brøler - beklager. Dit forslag i #9 virker perfekt.
Men siden jeg skrev det ikke virkede, var det fordi jeg havde indsat mine 2 felter i stedet for dine datoer - derfor fejlede det. Jeg har jo ikke eksakte datoer blot mine feltnavne...
Jeg fulgte forslaget fra nemlig og lavede mit dato felt om i Mysql, men da data blev hentet fra min gedcom fil var alle datoer nulstillet - så det duede ikke. Jeg tænker, det skyldes, at i min gedcom fil er datoer angivet f.eks 24 februar 1885 og når data så bliver hentet ind i et 'date' felt, der er 00.00.0000 ja, så bliver de nulstillet. Men det var værd at prøve.
Og det lille script skrevet af repox blev testet og virker fint, det var bare mig, der havde sovet i timen.
Jeg skal ikke have point - mit bidrag var ikke så godt. Arne_V kom faktisk med løsningen og repox var mere detaljeret. Så jeg foreslår, at arne_v og repox deler. :)
Det vil jeg nu ikke give dig ret i, for ideen var faktisk ganske god og brugbar. Og det var lykkedes hvis bare mit datofelt i gedcom filen havde været sat anderledes. Problemet med det er bare, at det felt kan jeg ikke ændre på. Men dit svar er selvfølgelig godtaget :-)
Du burde konvertere dit dato felt til et date felt og så validere inputtet.
Hvis du er sikker på de forskellige variationer at datoerne, bør du kunne lave en eller en kombination af flere funktioner der skrev nogle datoformater du kan bruge i databasen.
F.eks. fra dine egne eksempler, ville du strippe alt der ikke er relevant for dit datofelt:
"Født ca. 1857" => $ date = substr($streng, -4)."-01-01"; Så gem det i databasen sammen med et nyt felt (kald det 'estimeret'). Og så har du et ordentligt format og en måde i databasen at sige at 'det er cirka deromkring'.
repox: Tak for forslaget, jeg arbejder videre med sagen. Prøvede tidligere at udføre en ALTER i MySql for at ændre dato format, men det gav også kun 0000.00.00, så måske bliver det din løsning. Skærer point over i tilfælde af at arne sender et svar - håber det er ok? mvh Erik
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.