Avatar billede ej147 Nybegynder
23. februar 2014 - 21:27 Der 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
Avatar billede arne_v Ekspert
23. februar 2014 - 21:35 #1
Du kan faktisk ikke udregne alder udfra 2 aarstal du er noedt til ogsaa at kende datoer. Men goer du det, saa kan det beregnes.

For dataoer foerend 1901 er du vist noedt til at bruge DateTime klassen.
Avatar billede nemlig Professor
23. februar 2014 - 21:38 #2
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.
Avatar billede nemlig Professor
23. februar 2014 - 21:40 #3
Hov - havde ikke set Arnes indlæg.
Avatar billede ej147 Nybegynder
23. februar 2014 - 21:46 #4
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
Avatar billede nemlig Professor
23. februar 2014 - 22:03 #5
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.
Avatar billede nemlig Professor
23. februar 2014 - 22:16 #6
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.

Skriv lige det format, du gemmer i?
Avatar billede repox Seniormester
23. februar 2014 - 22:18 #7
#5
Som arne_v var inde på, så i stedet for at finde på sine egne funktioner så brug DateTime klassen - det er trods alt formålet med den.
Avatar billede nemlig Professor
23. februar 2014 - 22:27 #8
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>

?>
Avatar billede repox Seniormester
23. februar 2014 - 23:03 #9
#8
Det virker godt nok noget voldsomt for noget så simpelt som det OP efterspørger.

$birthdate = new \DateTime("1879-03-14");
$deathdate = new \DateTime("1955-04-18");

echo $birthdate->diff($deathdate)->format("%y år");


Det handler om KISS
Avatar billede ej147 Nybegynder
23. februar 2014 - 23:27 #10
Citat:
"Skriv lige det format, du gemmer i? "

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
Avatar billede repox Seniormester
23. februar 2014 - 23:35 #11
Prøv at skrive
date_default_timezone_set ('UTC');

lige før min kode.
Avatar billede ej147 Nybegynder
23. februar 2014 - 23:43 #12
Tak.
Har lige prøvet men desværre....

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
Avatar billede ej147 Nybegynder
23. februar 2014 - 23:46 #13
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...
Avatar billede ej147 Nybegynder
24. februar 2014 - 14:24 #14
repox - nemlig:

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.

Må jeg foreslå I begge sender et svar?

mvh Erik
Avatar billede nemlig Professor
24. februar 2014 - 14:29 #15
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. :)
Avatar billede ej147 Nybegynder
24. februar 2014 - 14:37 #16
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 :-)

Så må jeg håbe de andre 2 svarer :-)

mvh Erik
Avatar billede repox Seniormester
24. februar 2014 - 16:54 #17
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'.
Avatar billede ej147 Nybegynder
24. februar 2014 - 17:00 #18
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
Avatar billede ej147 Nybegynder
24. februar 2014 - 17:02 #19
Nu undrer jeg mig???
Fik ikke mulighed for at skære point over, gad vide hvorfor?
Nå shit, men de er afgivet :-)
Avatar billede repox Seniormester
24. februar 2014 - 17:54 #20
Jeg har fordelt pointente for dig.
Avatar billede ej147 Nybegynder
24. februar 2014 - 20:06 #21
Fornemt - tak.
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester