Discussion:
Tage zwischen 2 Daten berechnen?
(zu alt für eine Antwort)
Sascha Retter
2004-09-04 10:33:08 UTC
Permalink
Hi!

Ich muss die Anzahl der Tage zwischen 2 Daten berechnen. Genauer gesagt
die Anzahl der Tage zwischen einem Datum das in einer MySql-DB steht und
dem heutigen Datum. Weiß einer ob Java bzw. MySql schon über Methoden
verfügen oder ob man eine Methode selber schreiben muss.

Sascha
Michael Borgwardt
2004-09-04 10:51:26 UTC
Permalink
Post by Sascha Retter
Ich muss die Anzahl der Tage zwischen 2 Daten berechnen. Genauer gesagt
die Anzahl der Tage zwischen einem Datum das in einer MySql-DB steht und
dem heutigen Datum. Weiß einer ob Java bzw. MySql schon über Methoden
verfügen oder ob man eine Methode selber schreiben muss.
Ja, Mysql und auch Java verfügen schon über Methoden.
Marian Aldenhövel
2004-09-04 10:54:42 UTC
Permalink
Hallo,
Post by Sascha Retter
Weiß einer ob Java bzw. MySql schon über Methoden
verfügen oder ob man eine Methode selber schreiben muss.
MySQL hat DATEDIFF() und andere nützliche Funktionen:

http://dev.mysql.com/doc/mysql/en/Date_and_time_functions.html

Java hat die Klasse Calendar.

Um die Differenz zu bestimmen kannst Du entweder die Differenz der
beiden Ergebnisse von getTime() durch die Anzahl der Millisekunden an
einem Tag (1000*60*60*24 oder so) teilen. Oder Du bestimmst die
Differenz der einzelnen Felder (Jahr, Monat, Tag) und rechnest
ziemlich herum.

Die erste Methode liefert unerwartete Ergebnisse falls die Datumswerte
auch Zeitanteile haben, die will man also vorher zum Beispiel auf
00:00:00.0000 normalisieren. Die zweite ist nicht-trivial zu
implementieren.

Ob es eine direkte fertige Methode gibt, weiß ich nicht. Aber ich bin
nur ein Ei.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn.
Fon +49 228 624013, Fax +49 228 624031.
http://www.marian-aldenhoevel.de
"When firing areas are active all air traffic is strongly
requested to avoid them"
Michael Borgwardt
2004-09-04 11:26:02 UTC
Permalink
Post by Marian Aldenhövel
Um die Differenz zu bestimmen kannst Du entweder die Differenz der
beiden Ergebnisse von getTime() durch die Anzahl der Millisekunden an
einem Tag (1000*60*60*24 oder so) teilen.
*Ganz* schlechte Idee.
Post by Marian Aldenhövel
Oder Du bestimmst die
Differenz der einzelnen Felder (Jahr, Monat, Tag) und rechnest
ziemlich herum.
Die erste Methode liefert unerwartete Ergebnisse falls die Datumswerte
auch Zeitanteile haben,
Oder wenn einem die Sommer/Winterzeit oder ein Schaltjahr dazwischen kommt.
Würde ich mich nicht drauf verlassen wollen.
Post by Marian Aldenhövel
Die zweite ist nicht-trivial zu implementieren.
Weswegen die Jungs von Sun das nettweise in die Standard-API mit
aufgenommen haben, eben gerade in der von Dir genannten Calendar-Klasse.
Marian Aldenhövel
2004-09-04 11:40:10 UTC
Permalink
Hallo,
Post by Michael Borgwardt
Weswegen die Jungs von Sun das nettweise in die Standard-API mit
aufgenommen haben, eben gerade in der von Dir genannten Calendar-Klasse.
Ich hätte mich nicht mit der Augen-zu-und-durch-Methode in die Gruppe
getraut, wenn ich nicht vorher nochmal in die API geschaut hätte und
nichts gefunden hätte.

Wie heißt die Calendar-Methode die dieses leistet?
Post by Michael Borgwardt
Post by Marian Aldenhövel
Die erste Methode liefert unerwartete Ergebnisse falls die
Datumswerte auch Zeitanteile haben,
Oder wenn einem die Sommer/Winterzeit oder ein Schaltjahr dazwischen kommt.
Auf Anhieb fällt mir kein Beispiel ein, in dem man damit falsch läge.
Jedenfalls nicht, wenn man wie empfohlen den Zeitanteil streicht bevor
man subtrahiert.

getTime() liefert doch "vergangene Zeit seit X", hat also mit Kalendern
nichts mehr zu tun. Damit ist die Differenz von Time-Werten immer die
Anzahl der dazwischen tatsächlich vergangenen Millisekunden. Teilt man
das bekommt man die Anzahl der tatsächlich vergangenen Tage.

Oder übersehe ich da was?

Allenfalls Schalt_sekunden_ könnten die Stetigkeit von getTime()
betreffen, aber das würde mein Ergebnis doch nicht beeinflussen.

Bei der Methode die die Differenz auf den einzelnen Feldern berechnet
muss man natürlich Schaltjahre und ganze allgemein die unterschiedlichen
Anzahlen von Tagen pro Monat berücksichtigen. Das macht diese Methode
eben viel komplizierter als die Millisekunden-Methode.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn.
Fon +49 228 624013, Fax +49 228 624031.
http://www.marian-aldenhoevel.de
"When firing areas are active all air traffic is strongly
requested to avoid them"
Dirk Michael
2004-09-04 12:49:36 UTC
Permalink
Hallo,
Post by Marian Aldenhövel
Wie heißt die Calendar-Methode die dieses leistet?
Ich glaube, java.util.Calendar#add(int field, int amount) ist gemeint.

MfG
Dirk Michael
Marian Aldenhövel
2004-09-04 13:07:36 UTC
Permalink
Hallo,
Post by Dirk Michael
Ich glaube, java.util.Calendar#add(int field, int amount) ist gemeint.
Das hilft aber doch nicht.

Es sei denn, man würde eine while-kleiner-addiere-einen-Tag-und-
zähle-mit-Schleife akzeptieren. Das empfände ich aber dann doch als
ziemlich Bäh und nicht als ernstzunehmende Alternative.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn.
Fon +49 228 624013, Fax +49 228 624031.
http://www.marian-aldenhoevel.de
"When firing areas are active all air traffic is strongly
requested to avoid them"
Michael Borgwardt
2004-09-04 22:10:03 UTC
Permalink
Post by Marian Aldenhövel
Post by Michael Borgwardt
Weswegen die Jungs von Sun das nettweise in die Standard-API mit
aufgenommen haben, eben gerade in der von Dir genannten Calendar-Klasse.
Ich hätte mich nicht mit der Augen-zu-und-durch-Methode in die Gruppe
getraut, wenn ich nicht vorher nochmal in die API geschaut hätte und
nichts gefunden hätte.
Wie heißt die Calendar-Methode die dieses leistet?
Sorry, hab' mich geirrt, die gibt's wirklich nicht.
Post by Marian Aldenhövel
Post by Michael Borgwardt
Oder wenn einem die Sommer/Winterzeit oder ein Schaltjahr dazwischen kommt.
Auf Anhieb fällt mir kein Beispiel ein, in dem man damit falsch läge.
Jedenfalls nicht, wenn man wie empfohlen den Zeitanteil streicht bevor
man subtrahiert.
getTime() liefert doch "vergangene Zeit seit X", hat also mit Kalendern
nichts mehr zu tun. Damit ist die Differenz von Time-Werten immer die
Anzahl der dazwischen tatsächlich vergangenen Millisekunden. Teilt man
das bekommt man die Anzahl der tatsächlich vergangenen Tage.
Die Tage haben dann aber doch wieder was mit Kalendern zu tun, jedenfalls
würde man doch allgemein erwarten, daß das Ergebnis sich auch so am
Kalender ablesen läßt.
Post by Marian Aldenhövel
Oder übersehe ich da was?
Beim Wechsel zwischen Sommer- und Winterzeit gibt es je einen Tag,
der 23 bzw. 25 Stunden lang ist. Deswegen gibt's Probleme wenn die
Zeitspanne davon nur einen (bzw. einen ungerade Anzahl) umfaßt.

Siehe auch Abschnitt 9, Frage 37 im FAQ:
http://www.faqs.org/faqs/computer-lang/java/programmers/faq/
mit mehreren Lösungsansätzen.
Patrick Roemer
2004-09-04 11:47:44 UTC
Permalink
Post by Sascha Retter
Ich muss die Anzahl der Tage zwischen 2 Daten berechnen. Genauer gesagt
die Anzahl der Tage zwischen einem Datum das in einer MySql-DB steht und
dem heutigen Datum. Weiß einer ob Java bzw. MySql schon über Methoden
verfügen oder ob man eine Methode selber schreiben muss.
Schau mal, ob der Thread (und die darin referenzierte Klasse) weiterhilft:

http://groups.google.com/groups?threadm=bl28vn%245l9%241%40newsreader2.netcologne.de

Viele Gruesse,
Patrick
Stefan Ram
2004-09-04 16:22:02 UTC
Permalink
Post by Sascha Retter
Ich muss die Anzahl der Tage zwischen 2 Daten berechnen.
Genauer gesagt die Anzahl der Tage zwischen einem Datum das in
einer MySql-DB steht und dem heutigen Datum. Weiß einer ob Java
bzw. MySql schon über Methoden verfügen oder ob man eine
Methode selber schreiben muss.
Mit

new de.dclj.ram.type.gregorian.YearMonth( y, m ).toDays() +( d - 1 )

erhält man zu einem gregorianischen Tripel y-m-d
(Jahr-Monat-Tag) eine Tageszahl, die den Abstand zum Tag
(-1)-12-31 angibt. Durch Ermittlung der Differenz zweier
solcher Tageszahlen sollte man dann die Differenz zweier Daten
in Tagen erhalten können.

Die URIs des Quellcodes der benötigten Klassen sind:

http://www.purl.org/stefan_ram/java/de/dclj/ram/type/gregorian/YearMonth.java
http://www.purl.org/stefan_ram/java/de/dclj/ram/type/gregorian/Year.java

Bei den negativen Jahreszahlen erhalten ich wohl andere
Ergebnisse als die Testdaten aus der folgenden Quelle (nach
"TestFixedDates" und "TestDates[Gregorian]" suchen).

http://www.math.nus.edu.sg/aslaksen/calendar/Calendrica.m

Es scheint mir so, als hätte man dort ein Jahr 0 angenommen,
während ich dachte, beim Gregorianischen Kalendar folge auf
das Jahr -1 das Jahr 1. Andererseits scheint diese Quelle von
Spezialisten zu stammen, so daß ich mir nun nicht sicher bin,
ob meine Methode für negative Jahre richtig ist.
Frank Buss
2004-09-04 18:51:55 UTC
Permalink
Post by Stefan Ram
Bei den negativen Jahreszahlen erhalten ich wohl andere
Ergebnisse als die Testdaten aus der folgenden Quelle (nach
"TestFixedDates" und "TestDates[Gregorian]" suchen).
http://www.math.nus.edu.sg/aslaksen/calendar/Calendrica.m
Es scheint mir so, als hätte man dort ein Jahr 0 angenommen,
während ich dachte, beim Gregorianischen Kalendar folge auf
das Jahr -1 das Jahr 1. Andererseits scheint diese Quelle von
Spezialisten zu stammen, so daß ich mir nun nicht sicher bin,
ob meine Methode für negative Jahre richtig ist.
es gibt zwei verschiedene gregorianische Kalender: der "Proleptic
Gregorian Calendar", in dem es das Jahr 0 nicht gibt und der
"Astronomical Gregorian Calendar", in dem das Jahr 0 als Schaltjahr
existiert:

http://en.wikipedia.org/wiki/Proleptic_Gregorian_Calendar

java.util.GregorianCalendar implementiert den Proleptic Gregorian
Calendar, inklusiv der Lücke zwischen dem 4. und 15. Oktober 1582.

Genau genommen dürfte man übrigens keine negativen Zahlen verwenden, da
die zum Zeitpunkt der Einführung des gregorianischen Kalenders im Jahre
1582 (wobei allerdings viele Länder erst später diesen Kalender
übernahmen) noch nicht üblich waren:

http://kr.cs.ait.ac.th/~radok/math/mat1/mat112.htm

Die Zahl 0 gab es allerdings schon 1202 in Europa:

http://www.bbc.co.uk/radio4/science/5numbers1.shtml
--
Frank Buß, ***@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Stefan Ram
2004-09-04 20:59:17 UTC
Permalink
Post by Frank Buss
java.util.GregorianCalendar implementiert den Proleptic Gregorian
Calendar, inklusiv der Lücke zwischen dem 4. und 15. Oktober 1582.
Es ist nicht ganz eindeutig, ob diese Lücke Teil des
(vorausgenommenen) gregorianischen Kalenders ist - jedenfalls,
wenn ich den Ausführungen von Sun folge:

"Before the Gregorian cutover, GregorianCalendar implements
the Julian calendar."

Damit implementiert GreogorianCalendar also eher den "zivilen
Mischkalender" (oder wie man ihn jetzt nennen soll), der bis
zum 4. Oktober 1582/jul der julianische und danach der
gregorianische war. Die Lücke ist Teil dieses Mischkalenders.
Post by Frank Buss
Genau genommen dürfte man übrigens keine negativen Zahlen
verwenden, da die zum Zeitpunkt der Einführung des
gregorianischen Kalenders im Jahre 1582 (wobei allerdings viele
Länder erst später diesen Kalender übernahmen) noch nicht
Man kann "-1" als Darstellung von "1 vor Christus" (dem Jahr,
welches "1 nach Christus" direkt vorangeht) ansehen. (Was
natürlich nicht ganz stimmig ist, denn vor "1 nach Christus"
käme ja nach unserer heutigen Auffassung "0 vor Christus".)
Mit dem Auslassen der 0 verwendet man ja ohnehin nicht mehr
die Menge Z der ganzen Zahlen mit den üblichen Strukturen.

Moral: Also, welche Entscheidungen man hinsichtlich solch
einer Kalenderklasse auch immer trifft - man sollte sie in der
Gebrauchsanweisung der Klasse erklären. (Das fehlt bei
meinen Klassen bisher noch.)
Frank Buss
2004-09-05 09:25:41 UTC
Permalink
Post by Stefan Ram
Es ist nicht ganz eindeutig, ob diese Lücke Teil des
(vorausgenommenen) gregorianischen Kalenders ist - jedenfalls,
"Before the Gregorian cutover, GregorianCalendar implements
the Julian calendar."
Zumindest ist eindeutig, daß die Klasse diese Lücke behandelt:

This implementation handles a single discontinuity, which corresponds
by default to the date the Gregorian calendar was instituted (October
15, 1582 in some countries, later in others). The cutover date may be
changed by the caller by calling setGregorianChange()

Man kann also sogar setzen, wann die Lücke war. Außerdem beeinflusst
dieses Datum das Verhalten der Schaltjahrberechung, da beim Julianischen
Kalender nur alle 4 Jahre ein Schaltjahr ist.
Post by Stefan Ram
Man kann "-1" als Darstellung von "1 vor Christus" (dem Jahr,
welches "1 nach Christus" direkt vorangeht) ansehen. (Was
natürlich nicht ganz stimmig ist, denn vor "1 nach Christus"
käme ja nach unserer heutigen Auffassung "0 vor Christus".)
Mit dem Auslassen der 0 verwendet man ja ohnehin nicht mehr
die Menge Z der ganzen Zahlen mit den üblichen Strukturen.
ja, so habe ich es auch in meiner Klasse festgelegt. Hier eine
abgespeckte Version, die nur die Differenz zwischen zwei Daten berechnet:

import java.util.*;

public class DayDiff {
public static int getDays(int year, int month, int date) {
long millisPerDay = 24 * 60 * 60 * 1000;
GregorianCalendar c =
new GregorianCalendar(TimeZone.getTimeZone("UTC"));
c.clear();
if (year < 0) {
c.set(Calendar.ERA, GregorianCalendar.BC);
year = -year;
}
c.set(year, month - 1, date);
return (int) (c.getTimeInMillis() / millisPerDay);
}

public static int diff(
int y1, int m1, int d1,
int y2, int m2, int d2)
{
return getDays(y1, m1, d1) - getDays(y2, m2, d2);
}

public static void main(String args[]) {
assert diff(-1, 1, 1, -2, 1, 1) == 365;
assert diff( 1, 1, 1, -1, 1, 1) == 366;
assert diff( 1, 1, 1, 0, 1, 1) == 366;
assert diff( 2, 1, 1, 1, 1, 1) == 365;
assert diff(1582, 10, 4, 1582, 10, 3) == 1;
assert diff(1582, 10, 15, 1582, 10, 4) == 1;
assert diff(1582, 10, 16, 1582, 10, 14) == -8;
assert diff(1582, 10, 16, 1582, 10, 15) == 1;
}
}

Genaugenommen müsste man bei der Jahreszahl 0 eine Exepction werfen.
Ebenso bei Daten zwischen dem 4.10.1582 und 15.10.1582, da es diese Daten
nicht gab und es sonst zu merkwürdigen Effekten kommt, z.B. daß
16.10.1582 - 14.10.1582 = -8 ergibt. Was übrigens auch ein Grund für die
spätere Einführung mancherorts war, da den Leuten ja 10 Tage ihres Lebens
gestohlen wurde :-)

http://www.geocities.com/CapitolHill/Lobby/2554/kal5.htm (Abschnitt "Die
Ausbreitung des Gregorianischen Kalenders")

In dBase (Clipper-Dialekt) konnte man übrigens einfach sowas schreiben:

. ? date() - { 1.1.2004 }
248

Schön, daß Java einem das Leben so leicht macht :-)
--
Frank Buß, ***@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Marcus Woletz
2004-09-04 16:48:10 UTC
Permalink
Hallo Sascha,
Post by Sascha Retter
Hi!
Ich muss die Anzahl der Tage zwischen 2 Daten berechnen. Genauer gesagt
die Anzahl der Tage zwischen einem Datum das in einer MySql-DB steht und
dem heutigen Datum. Weiß einer ob Java bzw. MySql schon über Methoden
verfügen oder ob man eine Methode selber schreiben muss.
Sascha
also ich würde einfach folgendes berechnen:

int diffSecs = Calendar2.getTime() - Calendar1.getTime();
int diffDays = diffSecs / 86400; // 24h * 3600s/h

diffDays kann man natürlich auch durch mathematisches Runden
(also nicht nur abschneiden des Dezimalanteils) berechnen,
was evtl. Ungenauigkeiten vermeiden würde.

ciao
Marcus
Stefan Ram
2004-09-04 17:32:34 UTC
Permalink
Post by Marcus Woletz
int diffSecs = Calendar2.getTime() - Calendar1.getTime();
Hier ist mal ein Quellcode. Bei dem letzten Versuch mit
1995-01-01 sollte sich wohl eine Differenz von 3082 Tagen
ergeben (laut Frank Buss
[http://www.frank-buss.de/tmp/DayDateTest.java], Excel und
meiner Implementation), da ergibt die Methode diff1 aber 3081
Tage. Davor stehen zwei Versuche mit einer Differenz von 0
Tagen und von einem Tag, bei denen alle Ergebnisse
übereinstimmen.

public class YearMonthTrial
{

static int diff0
( final int y, final int m, final int d,
final int y_, final int m_, final int d_ )
{ return
( new de.dclj.ram.type.gregorian.YearMonth
( y, m ).toDays() +( d - 1 )) -
( new de.dclj.ram.type.gregorian.YearMonth
( y_, m_ ).toDays() +( d_ - 1 )); }

static int diff1
( final int y, final int m, final int d,
final int y_, final int m_, final int d_ )
{ java.util.GregorianCalendar calendar2 =
new java.util.GregorianCalendar( y, m, d );
java.util.GregorianCalendar calendar1 =
new java.util.GregorianCalendar( y_, m_, d_);
long diffSecs =
calendar2.getTimeInMillis() / 1000L -
calendar1.getTimeInMillis() / 1000L;
double diffDays = ( double )diffSecs /
( double )( 24 * 60 * 60 );
int result =( int )( diffDays + 0.5 );
return result; }

public static void main( final String[] args )
{
java.lang.System.out.println( 0 );
java.lang.System.out.println( diff0( 2003, 6, 10, 2003, 6, 10 ));
java.lang.System.out.println( diff1( 2003, 6, 10, 2003, 6, 10 ));
java.lang.System.out.println();

java.lang.System.out.println( 1 );
java.lang.System.out.println( diff0( 2003, 6, 11, 2003, 6, 10 ));
java.lang.System.out.println( diff1( 2003, 6, 11, 2003, 6, 10 ));
java.lang.System.out.println();

java.lang.System.out.println( 3082 );
java.lang.System.out.println( diff0( 2003, 6, 10, 1995, 1, 1 ));
java.lang.System.out.println( diff1( 2003, 6, 10, 1995, 1, 1 ));
java.lang.System.out.println(); }}

Ausgabe:

0
0
0

1
1
1

3082
3082
3081
Frank Buss
2004-09-04 17:49:13 UTC
Permalink
Post by Stefan Ram
Hier ist mal ein Quellcode. Bei dem letzten Versuch mit
1995-01-01 sollte sich wohl eine Differenz von 3082 Tagen
ergeben (laut Frank Buss
[http://www.frank-buss.de/tmp/DayDateTest.java], Excel und
meiner Implementation), da ergibt die Methode diff1 aber 3081
Tage.
ja, das liegt an der nicht bedachten Sommer-/Winterzeit bei diff1, was
deine Klasse, Excel und meine DayDate-Klasse nicht verwirrt.
--
Frank Buß, ***@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Bernd Eckenfels
2004-09-04 17:51:36 UTC
Permalink
Post by Stefan Ram
Hier ist mal ein Quellcode.
es tut mir physisch und psychisch weh, ist das denn notwendig?

Gruss
Bernd
--
eckes privat - http://www.eckes.org/
Project Freefire - http://www.freefire.org/
Tarlika Elisabeth Schmitz
2004-09-06 08:15:24 UTC
Permalink
Hallo Sascha,
Post by Sascha Retter
Ich muss die Anzahl der Tage zwischen 2 Daten berechnen. Genauer gesagt
Das Joda Time API (http://joda-time.sourceforge.net) hat alles, was Du
brauchst; vor allem die Differenz Berechnung ist einfach gemacht.
--
Regards/Gruß,

Tarlika Elisabeth Schmitz
Thorsten G.
2004-09-06 09:27:50 UTC
Permalink
Als gute Quelle für Kalender-Arithmetik kann ich nur
IBMs OSS-Site empfehlen:
http://oss.software.ibm.com/icu4j
http://oss.software.ibm.com/icu4j/doc/

Allerdings sind Kalender-Funktionen nur ein Bruchteil der
dort angebotenen API zum Thema Internationalisierung.
Post by Sascha Retter
Hi!
Ich muss die Anzahl der Tage zwischen 2 Daten berechnen. Genauer gesagt
die Anzahl der Tage zwischen einem Datum das in einer MySql-DB steht und
dem heutigen Datum. Weiß einer ob Java bzw. MySql schon über Methoden
verfügen oder ob man eine Methode selber schreiben muss.
Sascha
Loading...