# Altersberechnung - Extended!



## Eagle3386 (31. März 2005)

Hallo! 

Ich bin etwas, nun ja, "Statistik-vernarrt" und möchte die *exakte* Zeit, die seit meinem Geburtstag vergangen ist, anzeigen - und zwar in Jahren, Monaten, Wochen, Tagen, Stunden, Minuten und Sekunden.

Dazu hab ich mir 'n recht primitives Code-Snippet geschrieben:


```
$age_days = explode('.', ((time() - mktime(13, 0, 0, 3, 3, 1986)) / 86400));
$age_ours = explode('.', ($age_days[1] * 0.0000000024));
$age_mins = explode('.', ($age_ours[1] * 0.0000000060));
$age_secs = explode('.', ($age_mins[1] * 0.0000000060));
```

Das Problem ist jetzt, dass dieses Snippet nur die Tage, Stunden, Minuten und Sekunden ausrechnen kann, da ich bei der Angabe in Jahren ein Problem habe: das Schaltjahr, von dem es bekanntlich einige seit 1986 gab. 

Nun würd' ich gern wissen, wie ich's realisieren kann, dass es die *exakte* Anzahl an Jahren, Monaten, Wochen, Tagen, Stunden, Minuten und Sekunden angibt und dabei Schaltjahre berücksichtigt werden.

Außerdem soll das Ganze *unabhängig* vom *nix-Datumslimit sein, sprich soll es egal sein, ob jemand 1965 geboren ist oder eben 1986. 


Danke für eure Mühe im Voraus! 

LG, Martin...


----------



## olly1882 (31. März 2005)

Ich hatte schon mal etwas gelesen, was für dich passend sein dürfte. Du nimmst di aktuelle Zeit als UNIX Timestamp und ziehst deinen geburtstag davon ab. Die übrigen Sekunden lässt du dir im gewünschten Format anzeigen. Ich suche mal eben, ob ich den Thread finde.

EDIT: Habs gefunden hier


----------



## Eagle3386 (31. März 2005)

Danke, aber genau das macht mein Snippet doch schon! - Ich krieg' ja die Differenz zwischen dem 03. 03. 1986 um 13:00 Uhr und der aktuellen Zeit als Rückgabewert in Sekunden.

Ich will bei der Umrechnung dieser Sekundenanzahl jedoch nicht nur durch 84600 rechnen, um die Tage rauszukriegen, sondern auch die Jahre, Monate und Wochen - und hierbei hab ich das Problem, das ich nicht durch 365 teilen kann, weil's auch Schaltjahre gibt und deshalb geht das nicht so einfach.

Ich such' nun 'Hilfe dafür, dass ich das *absolut exakt* ermitteln kann - inklusive "Vor-1970-Kompatibilität"!


----------



## Matthias Reitinger (31. März 2005)

"Absolut exakt" und eine Angabe in den ungenauen Einheiten Jahr und Monat? Ehh... widerspricht sich das nicht ein wenig?   Wie definierst du "ein Monat"? Sind das 30 Tage? Oder die Zeit vom n-ten Tag des einen Monats zum n-ten Tag des nächsten Monats? Wenn du in dem Fall deine Zeitdifferenz in Monate umwandelst, verlierst du Information - und dann war's das mit der absoluten Exaktheit...


----------



## Eagle3386 (31. März 2005)

Matthias Reitinger hat gesagt.:
			
		

> "Absolut exakt" und eine Angabe in den ungenauen Einheiten Jahr und Monat? Ehh... widerspricht sich das nicht ein wenig?


 
 Seine "Lebenszeit" von Geburt an in Sekunden anzugeben find' ich sehr exakt! 
 Denn dieses "absolut exakt" bezieht sich darauf, dass ich eben nicht nur mein Alter in Jahren haben will, sondern in Jahren, Monaten, Wochen, Tagen, Stunden, Minuten und Sekunden. - Das ist für 'ne Lebenszeit-Angabe schon SEHR exakt, IMHO zumindest... 




			
				Matthias Reitinger hat gesagt.:
			
		

> Wie definierst du "ein Monat"? Sind das 30 Tage? Oder die Zeit vom n-ten Tag des einen Monats zum n-ten Tag des nächsten Monats? Wenn du in dem Fall deine Zeitdifferenz in Monate umwandelst, verlierst du Information - und dann war's das mit der absoluten Exaktheit...


 
 Nein, ich verliere KEINE Information, weil ich mich (glaube ich zumindest) anscheinend etwas falsch ausgedrückt habe.
 Ich will im Prinzip mit dem Snippet erreichen, dass angezeigt wird, viele Jahre ich schon lebe (zurzeit 19 ), dann die Monate, Wochen, Tage, Stunden und Minuten, die übrig sind.

 Wir haben heute den 31. März, also bin ich 19 Jahre, 0 Monate, 4 Wochen, 0 Tage, 6 Stunden und (jetzt gerade) 17 Minuten und paar Sekunden alt.

 Verstehst du jetzt, wie ich's meine? - Ich nehme den Differenzwert, rechne ihn in Jahre um, wandle den Restwert (bin ja 19,xxx Jahre alt ) in die nächst kleinere Einheit um, gebe diese aus und nehme davon wieder den Rest und wandle den wiederum in die nächst kleinere Einheit um - das mach ich runter bis zu den Sekunden, die runde ich dann auf, weil in Zehntel-Sekunden brauche ich's nun auch wieder nicht wissen!  

 Nur kann ich momentan nur die Tage ausrechnen, nicht aber die Jahre und Wochen, weil's Schaltjahre gibt und sich damit auch die Anzahl an Wochen verschiebt - genau hierfür bräuchte ich nun bisschen helfe, wenn die mir jemand geben kann...


----------



## Matthias Reitinger (31. März 2005)

FreedomCall hat gesagt.:
			
		

> Seine "Lebenszeit" von Geburt an in Sekunden anzugeben find' ich sehr exakt!


Da widersprichst du dir jetzt aber...



> Denn dieses "absolut exakt" bezieht sich darauf, dass ich eben nicht nur mein Alter in Jahren haben will, sondern in Jahren, Monaten, Wochen, Tagen, Stunden, Minuten und Sekunden. - Das ist für 'ne Lebenszeit-Angabe schon SEHR exakt, IMHO zumindest...


Wie gesagt: Ein Jahr und ein Monat sind keine exakten Angaben.



> Nein, ich verliere KEINE Information, weil ich mich (glaube ich zumindest) anscheinend etwas falsch ausgedrückt habe.


Doch, du verlierst Information. Wenn ich jetzt sage, XY ist exakt 30 Tage alt, dann weißt du (sekunden)genau, wie lange das ist. Sage ich allerdings, XY ist ein Monat alt, wie lange lebt XY dann schon? 31 Tage? Oder 30? Oder vielleicht doch 28? Oder etwa gar 29?



> Ich will im Prinzip mit dem Snippet erreichen, dass angezeigt wird, viele Jahre ich schon lebe (zurzeit 19 ), dann die Monate, Wochen, Tage, Stunden und Minuten, die übrig sind.


Und du hast leider immer noch nicht genau erklärt, was du unter der Zeiteinheit "ein Monat" verstehst. Das ist aber eben der springende Punkt.


----------



## Eagle3386 (1. April 2005)

Matthias Reitinger hat gesagt.:
			
		

> Da widersprichst du dir jetzt aber...
> 
> Wie gesagt: Ein Jahr und ein Monat sind keine exakten Angaben.
> 
> ...


 
 So, dann wollen wir das alles mal nachholen!  

 Okay, okay, ich verliere Informationen, wenn ich Monate angebe, allerdings nicht in jedem Fall:

 Ein Monat ist sicherlich eine recht ungenaue Angabe - nichtsdestotrotz ist dieser Wert unter bestimmten Bedingungen sehr wohl genau, nämlich wenn ich festlege, dass ein Monat für den Zeitraum vom 03. des Vormonats bis zum 03. des aktuellen Monats anzusehen ist.
 Sicherlich kann man jetzt sagen, dass das immer noch ungenau ist, weil es Monate mit 28, teilweise 29, 30 sowie 31 Tagen gibt, Doch ergibt sich im arithmetischen Mittel ein Wert, den man als recht exakt ansehen kann.


 Ich persönlich möchte halt von "groß nach klein" in der Angabe meiner Lebenszeit gehen, sprich: am 03. März 2005, um exakt 13:00:00 sind genau 19 Jahre seit dem 03. März 1986, 13:00:00 vergangen.
 Allerdings sind (bald) wiederum Wochen, Tage, Stunden, Minuten und Sekunden seit dem 03. März 2005, 13:00:00 vergangen und diesen Rest möchte ich nun erst in Wochen angeben, dann die restlichen Tage, da heute der Freitag, 01. April ist und somit noch 6 Tage fehlen (der 03. März 2005 war 'n Donnerstag ), bevor eine weitere volle Woche seit dem 03. März 2005 vergangen ist.
 Weiterhin ist es jetzt 01:26, also sind ein paar Wochen und Tage rum, aber auch schon wieder eine Stunde und 26 Minuten!


 Und genau so soll dann die Ausgabe sein - immer der Rest soll in die nächst kleinere Einheit umgewandelt werden, runter bis zur Sekunde, die wird "großzügig" gerundet...


----------



## ManicMarble (1. April 2005)

Exakt hin oder her, so bekommst Du was Du willst:

```
$geburtsjahr = 1986;
$geburtsmonat = 3;
$geburtstag = 3;
$geburtsstunde = 13;
$geburtsminute = 0;
$geburtssekunde = 0;

$alter = mktime(
	date('G') - $geburtsstunde,
	date('i') - $geburtsminute,
	date('s') - $geburtssekunde,
	date('n') - $geburtsmonat,
	date('d') - $geburtstag,
	date('Y'),
	-1
);

echo 'Alter am '.date('d.m.Y').' um '.date('H:i:s').' Uhr: <br>';
echo date('Y') - date($geburtsjahr) - (date('Y') - date('Y', $alter)) . ' Jahre, ';
echo date('n', $alter) . ' Monate, ';
echo date('d', $alter) . ' Tage, ';
echo date('G', $alter) . ' Stunden, ';
echo date('i', $alter) . ' Minuten, ';
echo date('s', $alter) . ' Sekunden.';
```
Das mit dem Jahr muss man so komisch machen, weil man ja mit mktime() eine UNIX-Timestamp erzeugt und für UNIX gab's vor 1970 nix. Und die Monate sind jetzt keine gemittelten "Statistikmonate" mit 30.4375 Tagen, sondern einfach die Anzahl vollständiger Monate, egal wie lang diese sind.
Die Ausgabe wird zugegebenermaßen in manchen Fällen (so wie in Deinem) etwas seltsam, Du bist demnach eben nicht 19 Jahre sondern 18 Jahre und 12 Monate. Das kann man aber mit etwas mehr Feinarbeit im Code noch ausbügeln.
Probier lieber mal ein paar Konstellationen durch, bin mir nämlich nicht sicher, ob ich das bis zu Ende logisch durchdacht habe. Ist jedenfalls ne lustige kleine Übung - das Alter in Sekunden mit date('U') - mktime(4, 30, 25, 10, 15, 1967, -1) berechnen kann ja jeder. Aber einen doofen Computer dazu zu bringen wie ein Mensch zu denken...

_Martin_


----------



## Eagle3386 (1. April 2005)

ManicMarble hat gesagt.:
			
		

> Exakt hin oder her, so bekommst Du was Du willst:
> 
> ```
> $geburtsjahr = 1986;
> ...


  Moin, Namensvetter!  

 Also erstmal danke für dein Snippet! 
 Nichtsdestotrotz gibt's da paar Dinge, die ich nicht verstehe und wo ich auf bessere (erweiterte ) Beschreibungen bzw. Erklärungen von dir hoffe:

 1. Warum berechnest du die Jahre so, wie du's eben machst - so wie du das machst, komme ich beim Nachrechnen (mit einem Geburtsdatum VOR 1970, z. B. 1963) auf 0, denn du rechnest ja dann bei den Jahren 2005 - 1963 - (2005 - 1963) 

 2. Hab ich dein Snippet versucht und es kommt nicht nur bei meinem Geburtsdatum 'ne komische Zahl raus, sondern auch beim Geburtsdatum meiner Mum, die ist am 20. 07. 1963 um xx:xx geboren und da meint dein Code, sie sei 41 Jahre und 8 Monate - richtig wären 9 Monate.
 Deshalb vermute ich generell einen Fehler in der Umrechnung der Monate, weil mit meinem Geburtsdatum kommen ja 18 Jahre und 12 Monate raus - das wiederum müsste aber PHP als 19 Jahre begreifen.

 3. Als Minuten-Angabe wird mir gerade eben "04 Minuten" ausgegeben, was ja am date('n') format liegt - aber wie kann ich die 0 wegkürzen ohne beispielsweise aus "10 Minuten" dann "0 Minuten" zu machen?

 [EDIT]
 4. Wieso machst du bei mktime eigentlich beim Geburtsjahr nur date('Y') und nicht date('Y') - $geburtsjahr? - Ich weiß, es kommt dann 'n falscher Wert, aber wieso
 [/EDIT]


 Ich weiß, viele Fragen, aber hey, nur wer fragt wird schlau und deshalb danke ich schon mal allen für ihre Mühe...


----------



## ManicMarble (1. April 2005)

Also wie gesagt, ich habe das nicht wirklich zu Ende gedacht, war nur so ein Ansatz.

Die komischen Zeitangaben im Ergebnis kommen daher, dass mktime() eigentlich einen Zeit_punk_ (Timestamp) zurückliefert und eben keine Zeit_spanne_ (Timeslice). Sprich: Das Ergebnis ist eigentlich ein Datum mit Uhrzeit - in Deinem Beispiel (Ergebnis "18 Jahre, 12 Monate, 29 Tage, 0 Stunden, 13 Minuten, 13 Sekunden") ist das der 29.12. des Jahres 18 (n.Chr.), 00:13:13 Uhr.

Das mit dem Jahr kann man so also nicht berechnen, da ja 18 n.Chr. deutlich vor dem 1.1.1970 liegt .
Deshalb habe ich das Jahr außen vor gelassen und berechne das später extra.

Da bei der mktime()-Berechnung (also $alter) theoretisch auch das Vorjahr rauskommen kann (3.3.2005 minus 3 Monate = 3.12.2004) muss in diesen Fällen diese Differenz noch bei der Jahres-Berechnung berücksichtigt werden. Deshalb
date('Y') - $geburtsjahr - (date('Y') - date('Y', $alter))
enspricht im o.g. Beispiel
2005 - 1986 - (2005 - 2004) = 2005 - 1986 - 1 = 18

Wenn Du den Ansatz mal zu Ende denken willst, muss Dir klar sein, wie mktime() arbeitet. Bei dem Alter Deiner Mutter sähe das in Etwa so aus:
$alter = mktime(13 - 0, 44 - 0, 20 - 0, 4 - 7, 1 - 20, 2005, -1);
entspricht
$alter = mktime(13, 44, 20, -3, -19, 2005, -1);
mktime() ist angeblich so schlau, aus den negativen Zahlen wieder ein korrektes Datum zu machen. Funktioniert für Timestamps AFAIK eigentlich wunderbar, wenn man's aber als Timeslice missbraucht, bin ich mir nicht mehr so sicher. Ist dann wohl doch so, dass das nicht richtig klappt...   

Tja, dann muss es halt doch irgendwie anders gehen. Vielleicht tüftel ich mal noch ein bischen dran rum, jetzt muss ich aber erst mal wieder das machen, wofür ich hier bezahlt werde...

Viel Spaß noch
_Martin_


----------



## Eagle3386 (1. April 2005)

ManicMarble hat gesagt.:
			
		

> Also wie gesagt, ich habe das nicht wirklich zu Ende gedacht, war nur so ein Ansatz.
> 
> Die komischen Zeitangaben im Ergebnis kommen daher, dass mktime() eigentlich einen Zeit_punk_ (Timestamp) zurückliefert und eben keine Zeit_spanne_ (Timeslice). Sprich: Das Ergebnis ist eigentlich ein Datum mit Uhrzeit - in Deinem Beispiel (Ergebnis "18 Jahre, 12 Monate, 29 Tage, 0 Stunden, 13 Minuten, 13 Sekunden") ist das der 29.12. des Jahres 18 (n.Chr.), 00:13:13 Uhr.
> 
> ...


 
 Also jetzt gibt's bei mir wirklich den Overkill - SYSTEM OVERLOADED, DEADLOCK REGISTERED!  

 Okay, ich versuch das wirklich in mein Hirn reinzukriegen und obwohl ich mich schon als "anfangenden Fortgeschrittenen" bezüglich meiner PHP-Fähigkeiten betrachte, blick ich grad GAR NIX bei deinen Erklärungen.

 Nun kann ich dich wohl kaum dazu überreden, es mir so zu erklären, dass auch mein dummes Hirn es begreift, doch mehr als den Unterschied zwischen Zeitspanne (was ich brauche) und Zeitpunkt (was mktime mir liefert) peil ich einfach nicht.

 Deine Berechnung ist irgendwie zu hoch für mich, oder ich bin einfach zu blöd dafür... 
 Weil ich blick nicht ganz, was du im Jahr 18 u. Z. willst, wenn ich in 1986 bzw. 1963 bzw. 2005 bin... 

 Ich hoffe, du kannst es mir so erklären, dass auch ein Doofy wie ich das gepeilt kriegt...  

 BtW: Was für 'ne Tätigkeit bei tutorials.de wird bitte bezahlt


----------



## ManicMarble (1. April 2005)

Wer sagt denn, dass ich bei Tutorials mein Geld verdiene?
Wollte nur andeuten, dass ich eigentlich was arbeiten müsste, anstatt hier im Forum Spaß zu haben...
Da ich aber nun durch meine unqualifizierten Ergüsse einen aufstrebenden Jung-Coder völlig verwirrt habe, stehe ich wohl in der Pflicht, das wieder hinzubiegen. Gruß an meinen Chef: Tut mir leid, das hier ist wichtig! 

Also, ich versuch's nochmal mit einer Erklärung:

Die Funktion mktime() liefert einen Unix-Timestamp, also die Anzahl der verstrichenen Sekunden seit dem 1.1.1970. Jetzt gerade eben hatten wir den Unix-Timestamp 1112364125, also 1 Milliarde 112 Millionen 364 Tausend und 125 Sekunden.

Mein Lösungsansatz basierte darauf, mit dem Unix-Timestamp eine Zeitspanne darzustellen. Theoretisch müsste das auch möglich sein, aber nur, wenn man eine Zeitspanne darstellen will, die mindestens 1970 und maximal 2036 (oder so) Jahre umfasst. Da nur wenige Lebewesen so alt werden, eignet sich dieser Lösungsansatz nicht zur Altersberechnung.
Ich habe dann versucht, das zu umgehen, indem ich die Berechnung der Jahre separat veranstaltet habe. War aber wohl zu kurz gedacht - der Unix-Timestamp eignet sich nicht für Timeslice-Berechnungen - was Du ja bewiesen hast.

(Die Sache mit dem "Jahr 18 n.Chr." war mein verunglückter Versuch, dies zu verdeutlichen: Als Ergebnis der Berechnung käme eine Zeit_spanne_ mit irgendwas über 18 Jahren raus, als Zeit_punkt_ dargestellt also irgend ein Datum im Jahr 18 und das ist als Unix-Timestamp nicht darstellbar).

Vergiss also diesen Lösungsansatz. So geht es nicht - zumindest nicht so einfach.

Die Problematik steckt in der menschlichen Denkweise (und ich meine damit Menschen, nicht Programmierer ). Was genau meint jemand, wenn er sagt: "Ich bin 37 Jahre, 6 Monate und 16 Tage alt."? Matthias hat natürlich recht: Das ist nicht exakt. Exakt ist es erst, wenn derjenige dazusagt, _welche _ 6 Monate. Sagt er aber nicht, er ist ja kein Computer. Das macht die Sache ja so interessant.
Also: Was _exakt_ meint der Mensch im allgemeinen Sprachgebrauch mit "6 Monate"? Ich würde sagen, er meint "6 Monats_wechsel_.

Das nächste Problem wären die Tage:
Nehmen wir an, jemand hat am 2. Oktober Geburtstag und heute wäre der der 27. April. Von Oktober bis April sind es 6 Monatswechsel. Also ist der Mensch x Jahre und 6 Monate alt.
Jetzt die Tage: Vom 2. Oktober bis Monatsende sind es 29 Tage. Vom 1. bis zum 27. April sind es 26 Tage (der 27. April selbst zählt nicht, der ist noch nicht vollständig). 29+26=55. Der Mensch ist also x Jahre, 6 Monate und 55 Tage alt. Hm. Also doch 7 Monate? Ja, ok. Dann müssen wir bei den 55 Tagen aber einen Monat abziehen. Bloß welchen? Den März (31 Tage)? Oder den November (30 Tage)? Oder einen Mittelwert (30.5 Tage)? Puh! So kommen wir IMHO nicht weiter.

Also: Völlig anderer Ansatz.
Berechne zunächst das Alter in Sekunden. Dann teile durch (365.25*24*60*60), das ist die durchschnittliche Anzahl Tage pro Jahr (nicht ganz exakt, eigentlich 365.241, aber das lassen wir jetzt mal gut sein) in Sekunden. Abgerundet auf eine ganze Zahl ist das das Alter in Jahren.
Den Rest teilst Du durch (30.44*24*60*60), die durchschnittliche Anzahl Tage pro Monat in Sekunden, das sind die Monate. Wiederum der Rest wird geteilt durch (24*60*60), das sind die Tage, den Rest durch 3600 (die Stunden), Rest durch 60 (Minuten) und das was bleibt sind die Sekunden. Das müsste bei allen Menschen unter 35 funktionieren und zumindest "mathematisch" annähernd exakt sein.
Bei Deiner Mutter (und bei mir) klappt das nicht, wir wurden vor Unix geboren. Für die "Generation X" muss man also das Alter in Sekunden "von Hand" ausrechnen. Ich mache das mal der Einfachkeit halber nur näherungsweise:

```
$geburtsjahr = 1963;
$geburtsmonat = 7;
$geburtstag = 20;
$geburtsstunde = 13;
$geburtsminute = 0;
$geburtssekunde = 0;

if ($geburtsjahr < 1970) {
	$sekundenVor1970 = (1970 - $geburtsjahr) * 365.25 * 24 * 60 *60;
	$alterInSek = date('U') - mktime($geburtsstunde, $geburtsminute, $geburtssekunde, $geburtsmonat, $geburtstag, 1970, -1);
	$alterInSek += $sekundenVor1970;
} else {
	$alterInSek = date('U') - mktime($geburtsstunde, $geburtsminute, $geburtssekunde, $geburtsmonat, $geburtstag, $geburtsjahr, -1);
}

$alterjahre = floor($alterInSek / (365.25*24*60*60));
$rest = $alterInSek % (365.25*24*60*60);

$altermonate = floor($rest / (30.44*24*60*60));
$rest = $rest % (30.44*24*60*60);

$altertage = floor($rest / (24*60*60));
$rest = $rest % (24*60*60);

$alterstunden = floor($rest / (60*60));
$rest = $rest % (60*60);

$alterminuten = floor($rest / 60);

$altersekunden = $rest % 60;

echo 'Alter am '.date('d.m.Y').' um '.date('H:i:s').' Uhr: <br>';
echo $alterInSek . ' Sekunden<br>';
echo "$alterjahre Jahre, $altermonate Monate, $altertage Tage, $alterstunden Stunden, $alterminuten Minuten, $altersekunden Sekunden.";
```
Nach menschlicher Denkweise ist das Ergebnis allerdings nicht befriedigend. Also eigentlich wieder nix. Das Ganze wird also schwieriger als man so auf den ersten Blick meinen würde.   

Ich hoffe, ich habe Dich jetzt nicht erst recht und endgültig verwirrt. Du siehts ja auch, dass es kein spezifisches PHP-Problem ist, sondern ein ganz allgemein programmiertechnisches (wenn nicht gar ein philosophisches ). Aber netter Denksport...

_Martin_


----------



## Eagle3386 (2. April 2005)

ManicMarble hat gesagt.:
			
		

> Wer sagt denn, dass ich bei Tutorials mein Geld verdiene?
> Wollte nur andeuten, dass ich eigentlich was arbeiten müsste, anstatt hier im Forum Spaß zu haben...
> Da ich aber nun durch meine unqualifizierten Ergüsse einen aufstrebenden Jung-Coder völlig verwirrt habe, stehe ich wohl in der Pflicht, das wieder hinzubiegen. Gruß an meinen Chef: Tut mir leid, das hier ist wichtig!
> 
> ...


 
 Zuerst einmal möchte ich mich entschuldigen, weil die Antwort ja doch recht spät kommt - allerdings war die Badewanne (und der mütterliche Druck  ) stärker und dann kam "Genial Daneben" und ... - Ach, ich hab's einfach verrissen, sorry!

 Aufstrebender Jung-Coder? Ich? - Nein, nein, das bin ich doch nicht!  
 (Wenn's glatt geht und ich das Assessment-Center nächsten Samstag bestehe, bin ich ab Oktober Berufsakademie-Student für Software-Entwicklung, aber Jung-Coder? Aufstrebend? - Nene, das ist 'n Missverständnis!   )

 Okay, jetzt versteh ich (glaub ich zumindest so halbwegs ) dein "Beispiel" mit der "18 u. Z."-Angabe...  

 Warum du nun Monatswechsel als Monatsangabe verwenden willst, blick ich nicht so ganz - aber ich denke mal, es ist das gleiche wie ich es eigentlich wollte: bei mir war 1 Monat = Zeit zwischen dem 03. des Vormonats und dem 03. des aktuellen Monats.

 Deinen Denkansatz ("Jetzt die Tage: Vom 2. Oktober bis Monatsende sind es 29 Tage.") geht mir völlig ab - wozu brauchst du die Anzahl der Tage vom 02. Oktober bis zum Ende vom Monat Oktober - Und vor allem: diese 29 Tage liegen doch NACH dem gewünschten Tag (02. Oktober, wenn ich dein Beispiel richtig verstehe...), aber du addierst die 29 Tage zu den 26 Tagen vom Rest-April hinzu

 Und zu deinem völlig neuen Ansatz: warum machst du's da nur nährungsweise und nicht auch exakt? Wär' das zuviel Aufwand? - Ich will dich ja nicht unnötig stressen, schließlich ist das hier alles völlig voluntär von dir geleistet und dafür dank ich dir auch SEHR! 


 Martin...


----------



## meilon (2. April 2005)

öööhm, erklärt mich für dumm, aber wieso nutzt du nicht [phpf]gmdate[/phpf], um die gewünschten Werte anzugeben?

mfg


----------



## Eagle3386 (2. April 2005)

meilon hat gesagt.:
			
		

> öööhm, erklärt mich für dumm, aber wieso nutzt du nicht [phpf]gmdate[/phpf], um die gewünschten Werte anzugeben?
> 
> mfg


 Wenn du mir jetzt noch sagst, warum ich bzw. mein Namensvetter ( ) diese Funktion nutzen sollten, wär' ich sehr dankbar!


----------



## meilon (2. April 2005)

Hmm, sry 

Hab ebend selber Versucht ein Script mit gmdate() zu schreiben. Ist nix geworden ;D

Einfach ignorieren


----------



## Matthias Reitinger (2. April 2005)

Na gut, dann will ich doch auch mal...   

```
<?

//
// monthdays
// * Gibt Anzahl der Tage eines bestimmten Monats zurück
//
function monthdays($month, $year)
{
	// evtl. Überträge ausgleichen
	if ($month > 12) {
		$month -= 12;
		$year++;
	}
	if ($month < 1) {
		$month += 12;
		$year--;
	}

	switch ($month) {
		case 1: case 3: case 5: case 7: case 8: case 10: case 12:
			return 31;
		case 4: case 6: case 9: case 11:
			return 30;
		case 2:
			// Schaltjahrbestimmung
			if (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0) {
				return 29;
			} else {
				return 28;
			}
	}

	return -1; // Fehler!
}

//
// timediff
// * Berechnet Differenz zwischen zwei Zeitpunkten
//
function timediff($t1, $t2)
{
	$diff = array();

	$keys = array_keys($t1);

	// Einfache Differenz bilden
	foreach ($keys as $key) {
		$diff[$key] = $t2[$key] - $t1[$key];
	}

	// Negative Differenzen ausgleichen
	while ($diff['M'] < 0 || $diff['D'] < 0
		|| $diff['h'] < 0 || $diff['m'] < 0 || $diff['s'] < 0) {

		if ($diff['M'] < 0) {	// Übertrag der Monate
			$diff['Y']--;
			$diff['M'] += 12;
		}
		
		if ($diff['D'] < 0) {	// Übertrag der Tage
			$diff['M']--;
			$diff['D'] += monthdays($t2['M']-1, $t2['Y']);
		}
		
		if ($diff['h'] < 0) {	// Übertrag der Stunden
			$diff['D']--;
			$diff['h'] += 24;
		}

		if ($diff['m'] < 0) {	// Übertrag der Minuten
			$diff['h']--;
			$diff['m'] += 60;
		}

		if ($diff['s'] < 0) {	// Übertrag der Sekunden
			$diff['m']--;
			$diff['s'] += 60;
		}

		if ($diff['D'] >= 7) {	// Berechnung der Wochen
			$diff['w'] = floor($diff['D'] / 7);
			$diff['D'] %= 7;
		} else {
			$diff['w'] = 0;
		}
	}

	return $diff;

}

// Y: Jahr, M: Monat, D: Tag
// h: Stunde, m: Minute, s: Sekunde

$geb = array(
	'Y' => 1985, 'M' => 8, 'D' => 10,
	'h' => 15, 'm' => 30, 's' => 0
);

$now = array(
	'Y' => date('Y'), 'M' => date('n'), 'D' => date('j'),
	'h' => date('G'), 'm' => date('i'), 's' => date('s')
);

$age = timediff($geb, $now);

print_r($age);

?>
```
Scheint eigentlich zu funktionieren. Hab jetzt leider nicht genügend Zeit, ein paar Testläufe zu machen oder eine lange Erklärung zu texten... kann ich ja bei Bedarf nachholen


----------



## Eagle3386 (3. April 2005)

Ich bin irgendwie sauer - hab den ganzen Tag gewartet, eine Benachrichtigungs-Mail zu kriegen und nix kam. Dann denk ich mir grad nochmal, ich könnt' doch auch so mal gucken und rums - ihr habt fleißig für mich gerackert!

 Das find ich nicht gut, wenn ich hier ausgegrenzt werde!   

 Zu dem Code: ATM bin ich zu müde, aber morgen werd' ich's testen...


----------



## Matthias Reitinger (3. April 2005)

Mir ist grad was aufgefallen - den if-else-Block, der mit "Berechnung der Wochen" kommentiert ist, sollte man aus der while-Schleife rausziehen (dahinter setzen).


----------



## Eagle3386 (3. April 2005)

Moin! 

 So, hab's getestet, es  1a! *YEEEEEEEEEEEEHAAAAAAAAAAAAAAAW* 

 Könntest du nun so frei sein und mir den Quellcode bisschen genauer erklären?


----------



## Matthias Reitinger (3. April 2005)

Ok, im Prinzip ist es eigentlich ganz einfach   

Und zwar gehe ich genau so vor wie beim schritlichen Subtrahieren. Wenn man da bspw. an einer Stelle eine "9" stehen hat und darüber eine "4", dann sagt man ja: "9 auf 14 [4+10] sind 5, also 5 an, 1 gemerkt". Das ganze muss man jetzt auf Zeiten übertragen, und mit den einzelnen Zeitkomponenten rechnen wie mit einzelnen Ziffern.

Beispiel:

```
22:10 (hh:mm)
- 20:45
   1
-------
  01:25

Sprich:
 * 45 auf 70 [10+60!] sind 25 => 25 (Minuten) an, 1 (Stunde) gemerkt
 * 21 [20+1] auf 22 sind 1, 1 (Stunde) an
```

So verfährt man dann auch mit den anderen Zeitkomponenten. Beim Abziehen der Tage muss man allerdings aufpassen, was man dazurechnet. Nach ein bisschen Überlegen kommt man darauf, dass man immer die Anzahl der Tage des jeweiligen Vormats hinzuzählen muss.

Das ist im Prinzip genau das, was der Code macht.

Für die Berechnung der Wochen wird einfach die Anzahl der Tage in der Differenz durch 7 geteilt und abgerundet. Der Rest aus dieser Division entspricht dann der Anzahl der restlichen Tage.

Ich hoffe, das war so weit verständlich.


----------



## ManicMarble (3. April 2005)

n'Abend FreedomCall,
sorry, das Wetter am Wochenende war einfach zu schön für Computerspiele 
Aber Matthias hat ja professionell - und einiges erfolgreicher - übernommmen.

Ciao,
_Martin_


----------



## Eagle3386 (3. April 2005)

'n Abend, Herr Namensvetter!  

 Ach hast du's gut - ich darf zurzeit nicht in die Sonne, zumindest nicht mit dem Gesicht und nicht mal für 5 Minuten! 
 Okay, ich könnte diese komische Creme auf meine Fratze ( ) schmieren, dann dürfte ich in die Sonne, aber auch nicht sehr lange... 
 Wie dem auch sei, so ist das halt, wenn man gegen "mittelschwere Rest-Akne" kämpft - aber hey, ich hab den Kampf gegen die schwerste Form der Akne gewonnen (obwohl sie bei mir NICHT überall, sondern nur im Gesicht war, was SEHR ungewöhnlich ist), also gewinne ich auch diesen Kampf...  
 (Oh man, ich laber dich hier mit privatem Zeugs zu!  Sorry! )


 Wie dem auch sei, weiter zum Problem:

 Matthias: Im PRINZIP sind alle Probleme leicht lösbar - in der Realität bedürfen sie aber manchmal einer völlig abstrusen und verwirrenden Lösung...  

 Zu deinem Beispiel: das Grundprinzip hab ich soweit verstanden, dein Beispiel hingegen nicht! 
 Ich meine, die Rechnung "22:10 - 20:45" ergibt 01:25, das weiß ich (durch nachrechnen  ) auch.
 Nichtsdestotrotz peil' ich nicht ganz, warum du "45 auf 70" rechnest und nicht "45 auf 100" (BtW: bei uns heißt das nicht "auf", sondern "bis" - aber das ist ja egal, ich versteh' ja, was du meinst  ).


 Der Rest ist dann soweit einleuchtend - bis auf diesen Passus:



> Beim Abziehen der Tage muss man allerdings aufpassen, was man dazurechnet. Nach ein bisschen Überlegen kommt man darauf, dass man immer die Anzahl der Tage des jeweiligen Vormats hinzuzählen muss.


 
 Warum willst du die Anzahl der Tage des Vormonats hinzuzählen?
 Und wie stellst du dabei sicher, dass korrekt gerechnet wird (manche Monate haben 30, manche 31, andere 28, teilweise 29)


 Viele Fragen - insofern hoffe ich auf viele Antworten!  

 GN8, Martin!


----------



## Matthias Reitinger (5. April 2005)

Zuerst mal sorry für die späte Antwort - aber die Schule droht hier so kurz vor dem Abi tatsächlich nochmal etwas stressig zu werden 



			
				FreedomCall hat gesagt.:
			
		

> Zu deinem Beispiel: das Grundprinzip hab ich soweit verstanden, dein Beispiel hingegen nicht!
> Ich meine, die Rechnung "22:10 - 20:45" ergibt 01:25, das weiß ich (durch nachrechnen  ) auch.
> Nichtsdestotrotz peil' ich nicht ganz, warum du "45 auf 70" rechnest und nicht "45 auf 100" (BtW: bei uns heißt das nicht "auf", sondern "bis" - aber das ist ja egal, ich versteh' ja, was du meinst  ).


Gegenfrage: Wieso sollte man "45 auf 100" rechnen? Beim schriftlichen Subtrahieren von Zahlen rechnest du ja bspw. als ersten Schritt auch nicht "5 auf 10", wenn du 262 - 15 ausrechnest, sondern "5 auf 12". Dieses 12 ergibt sich einfach dadurch, dass man die "2" nimmt, die Minuenden steht, und die nächsthöhere Stelle dieser Zahl mit einer "1" besetzt. Also wird aus "2" eine "12".

Analog verhält es sich bei den Zeiten. Ich nehme die 10 Minuten vom Minuenden und besetze die nächsthöhere Stelle (die Stunden) mit einer "1" und erhalte somit 1 Stunde + 10 Minuten. Und das sind natürlich 60 Minuten + 10 Minuten = 70 Minuten.

Würde man jetzt beispielsweise mit Tagen und Stunden rechnen, und sagen wir mal... 7d 6h - 3d 17h rechnen, dann würde das so aussehen:

```
7d  6h
- 3d 17h
  1d
--------
  3d 13h
```
Sprich: 17h auf 6h -> geht nicht, also Übertrag: 17h auf 1d 6h -> 17h auf 24h+6h -> 17h auf 30h = 13h. 13h an, 1d gemerkt. Und dann 4d auf 7d = 3d. 3d an.

Alles klar? 



> Der Rest ist dann soweit einleuchtend - bis auf diesen Passus:
> 
> Warum willst du die Anzahl der Tage des Vormonats hinzuzählen?
> Und wie stellst du dabei sicher, dass korrekt gerechnet wird (manche Monate haben 30, manche 31, andere 28, teilweise 29)


Mit den Monaten war es etwas kniffliger. Aber auch hier geht es darum, bei der Berechnung mit Tagen und Monaten die nächsthöhere Stelle mit "1" zu besetzen. Aber wie rechnet man jetzt 1 Monat in Tage um? Am besten mach ich wieder ein Beispiel, vielleicht wird's dann einleuchtend...

Nehmen wir mal an, wir befinden uns auf dem Planeten "Gnarz", auf dem die Monate ziemlich kurz sind. Die ersten vier Monate eines Gnarz-Jahres (Foo, Bar, Fork und Dork) sind 4, 3, 5 und 4 Tage lang. Zwibbeldrop, ein Bewohner von Gnarz, wurde nun am 3. Foo geboren. Momentan haben wir den 2. Dork, und Zwibbeldrop will jetzt wissen, wie alt er heute ist.

```
Foo      Bar     Fork     Dork
 _______  _______  _______  _______
|_______||___.___||___.___||___.___|
|_______||___.___||___.___||___H___|
|___Z___||___o___||___o___||_______|
|___.___|         |___.___||_______|
                  |___.___|
   4d       3d        5d      4d
```
"Z" kennzeichnet den Geburtstag unseren Gnarzmännchens und "H" den momentanen Gnarztag. Die Punkte bezeichnen den zu berechnenden Zeitraum. Wir wollen also folgendes berechnen:

```
4m 2d
- 1m 3d
-------
```
Also Schema F angewandt und gedacht: *3d auf 1m 2d* sind...? Hm. Was wollen wir da eigentlich in diesem Schritt berechnen? Ach ja, die Tage der Zeitdifferenz. Aber da ist es doch vollkommen egal, in welchem Monat Zwibbeldrop Geburtstag hatte - so lange der Tag des Monats gleich bleibt (der 3.), kann er auch am 3. Bar oder am 3. Fork (die "o" im Kalender) gehabt haben. Wenn wir seinen Geburtstag in Monatsschritten verschieben, ändert sich am Alter von Zwibbeldrop nur der Monatsanteil. Prima. Aber bringt uns das? Wir können nun die Berechnung der Tagesdifferenz vereinfachen, indem wir den Geburtstag auf den 3. Fork legen - also auf den Monat, der vor dem Dork kommt. (In den Dork selber können wir ihn natürlich nicht verlegen, denn sonst wäre unser kleiner Kamerad ja noch überhaupt nicht geboren.)

Aber wie berechnen wir jetzt die Tage zwischen dem dem 3. Fork und dem 2. Dork? Zeichnen wir den Kalender von Fork und Dork doch mal etwas anders:

```
_______
|___.___| <- 1. Fork
|___.___|
|___o___|
|___.___|
|___.___|
 _______
|___.___| <- 1. Dork
|___x___|
|_______|
|_______|
```
Jetzt sollte man es schon fast auf den ersten Blick erkennen: Wenn wir die entsprechenden Tage vom 1. Fork aus zählen, dann ist der 3. Fork auf Position 3. Der 2. Dork liegt auf Position 5 + 2 (5 Tage vom Fork + 2. Tag vom Dork). Und die Differenz daraus... 3 auf 7... Moment, das kommt uns doch bekannt vor! Genau, das ist doch *3d auf 1m 2d*, nur dass wir 1m durch 5d ersetzt haben. Und diese 5d sind - genau, die Länge des Vormonats in Tagen. Flugs ausgerechnet ergibt das 4d. Der Rest der Rechnung gestaltet sich einfach: 4d an, 1m gemerkt:

```
4m 2d
- 1m 3d
  1m
-------
  2m 4d
```

Hurra, fertig! Zwibbeldrop ist also 2 Monate und 4 Tage alt.

Das ganze verläuft absolut analog für Erdenjahre und Monate. Und die Länge der Monate ermittle ich in meinem Code mit der schönen Funktion monthdays (die steht ganz am Anfang ), die ich so aufrufe: $diff['D'] += monthdays($t2['M']-1, $t2['Y']); Warum, sollte nun hoffentlich klar sein 


So, und jetzt muss ich los nach Gnarz. Mit 2 Monaten und 4 Tagen ist man dort nämlich volljährig, was immer mit einem rauschenden Fest gefeiert wird. Und da ich Zwibbeldrop recht gut kenne...  ;-)


----------



## Matthias Reitinger (4. Mai 2005)

Und siehe da, ein knapper Monat zog ins Land, doch nichts geschah... hab ich dich jetzt vollkommen verschreckt mit meinem Beispiel? Würde mich zumindest über ein Lebenszeichen freuen, nicht dass ich mir die hübsche Geschichte von Zwibbeldrop ganz umsonst ausgedacht hab


----------



## Eagle3386 (4. Mai 2005)

Matthias Reitinger hat gesagt.:
			
		

> Und siehe da, ein knapper Monat zog ins Land, doch nichts geschah... hab ich dich jetzt vollkommen verschreckt mit meinem Beispiel? Würde mich zumindest über ein Lebenszeichen freuen, nicht dass ich mir die hübsche Geschichte von Zwibbeldrop ganz umsonst ausgedacht hab


 
 Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah
 Ich bin nicht würdig - Oh Meister, kannst du mir vergeben :-(

 Schlicht und ergreifend die Lehrer(innen) sind schuld: 5 Klausuren in 3 Tagen + Prüfungs-(Vorbereitungs-)-Stress und meine leichte Vergesslichkeit sind die Gründe für mein Versagen!  

 Wie dem auch sei: ab dieser Stelle hat sich mein Hirn ausgeklinkt:


> Am besten mach ich wieder ein Beispiel, vielleicht wird's dann einleuchtend...


 
 Deshalb wär' eine Erklärung dieser Stelle (und des ganzen Rests) SEEEEEEEEEEHR hilfreich!


----------



## Matthias Reitinger (5. Mai 2005)

Es sei dir verziehen, ich stecke ja auch grade voll im Prüfungsstress  

Aber ich weiß leider nicht, wie ich dir das mit dem Übertrag der Tage auf Monate noch anders erklären soll. Entweder du beißt dich durch mein Beispiel durch (ich find es eigentlich sehr anschaulich... zeichne dir vielleicht einfach mal selber einen Kalender auf und versuch es nachzuvollziehen), oder du erklärst, an welcher Stelle genau das Verständnis den Bach runter geht.

Derweil viel Glück und Erfolg bei deinen Prüfungen


----------

