Prüfen ob Tag innerhalb einer Tages-range liegt

Gast #4553310
Hallo

Ich stehe vor der Aufgabe zu prüfen, ob ein bestimmter Tag innerhalb 
einer Datums-range liegt.

Also z.B. der 10. zwischen dem 5. und dem 15. .
Dieser Fall ist recht einfach und wird in meinem Algorithmus derzeit mit
1
if( (day >= date_from.day) && (day <= date_to.day) )
abgearbeitet. Allerdings schlägt diese Abfrage natürlich beim 
Monatswechsel also z.b. date_from.day=31 und date_to.day=1 fehl. Obwohl 
der Tag (31.) innerhalb des Bereichs liegt.
Habt ihr mir eine gute Idee, wie ich diesen Fall handeln kann?

Gruß,
Bean
#4553314
@ Mr Bean (Gast)

>Ich stehe vor der Aufgabe zu prüfen, ob ein bestimmter Tag innerhalb
>einer Datums-range liegt.

Du meinst einen Date-bereich?

>Habt ihr mir eine gute Idee, wie ich diesen Fall handeln kann?

Man muss den Tag in den Tag des Jahres umrechnen, dann hat man einen 
einheitlichen Zahlenbereich. Oder man muss in Einzelprüfungen den Monat 
mit berücksichtigen.
Gast #4553315
hier ein Code-Ausschnitt wie ich hin verwende:
1
int k = Month > 2 ? Year : Year - 1;
2
int f = Year * 365 + (k + 4) / 4 - k / 100 + k / 400 + (Month - 1) * 30 + (Month + Month / 8) / 2 + (Month > 2 ? Day - 2 : Day) - 1;
f ist dann ein einfacher Zähler für Tage der sich auch leicht 
vergleichen lässt.
Gast #4553317
Du nennst selbst das Stichwort: Fall.

Der übliche Weg, den Programmierer dann gehen, ist, sich die 
verschiedenen Fälle zu überlegen. In Deinem Fall (hi hi) gibt es nur 
zwei mögliche Fälle. Du hast sie genannt.

Das ist nicht einfach die Lösung, aber Du kommst selbst darauf, wenn Du 
ein wenig darüber nachdenkst, meine ich.

Allerdings gibt es ein anderes Problem dabei, das Du nicht genannt hast. 
Entweder spielt es in Deinem Fall keine Rolle oder Du hast nicht daran 
gedacht. Die Monate haben verschiedene Länge. Und im Fall des Februars 
hängt die Länge noch von der Jahreszahl ab.
Persönliche Seite #4553321
Normiere Deine Datumsangaben z.B. auf x. Tag im Jahr und vergleiche 
dann.

Wenn jahresübergreifende Daten vorkommen (zwischen 25.12.16 und 3.1.17), 
dann musst Du auf Tag seit einem ausreichend lange in der Vergangenheit 
liegenden Datum normieren, und dann vergleichen.

Für Datumsberechnungen lohnt es sich immer, eine Normierungs- und 
"Entnormierungs"-Funktion zu haben, also einer, die aus einem Datum eine 
Tagesnummer und aus einer Tagesnummer wieder ein Datum erzeugt.

Damit lässt sich auch leicht die Aufgabe "Nenne mir das Datum in 41 
Tagen" lösen.
Gast #4553340
Die Sache mit den Normierungsfunktionen (z.B. auf die Anzahl Tage seit 
dem 1.1.1970 oder so ähnlich) ist natürlich die beste Möglichkeit. Damit 
ist alles berücksichtigt, was normalerweise auftritt.
Gast #4553346
Ok, vielen Dank für eure Antworten.
die mktime() Funktionen aus time.c wollte ich mir egentlich sparen. Da 
diese ja doch etwas Resourcen kosten. Aber habe mir schon fast gedacht, 
dass es am Ende doch darauf raus läuft, wenn man sicher alle Fälle 
berücksichtigen möchte.

Danke

Gruß,
Bean
#4553350
>Die Sache mit den Normierungsfunktionen (z.B. auf die Anzahl Tage seit
>dem 1.1.1970 oder so ähnlich) ist natürlich die beste Möglichkeit. Damit
>ist alles berücksichtigt, was normalerweise auftritt.

Ja bis ein Datum vor dem 1.1.1970 umzurechnen ist.

Gruß J
Gast #4553361
Jonas B. schrieb:
>>Die Sache mit den Normierungsfunktionen (z.B. auf die Anzahl Tage seit
>>dem 1.1.1970 oder so ähnlich) ist natürlich die beste Möglichkeit. Damit
>>ist alles berücksichtigt, was normalerweise auftritt.
>
> Ja bis ein Datum vor dem 1.1.1970 umzurechnen ist.
>
> Gruß J

Das versteht sich, meiner Meinung nach, ja von selbst und ist keiner 
Erwähnung wert.
Gast #4553368
> Das versteht sich, meiner Meinung nach, ja von selbst und ist keiner
> Erwähnung wert.

So selbstverständlich ist das nicht. Wenn's richtig gemacht ist, könnte 
man auch mit negativen Zahlen rechnen.
Gast #4553372
Es ist immer ein Problem, wie tief man bei solchen Fragen und den 
Antworten darauf geht. Bei der obigen Formel ist ihr Geltungsbereich 
nicht angegeben. Was wäre dann mit Daten vor dem 15.10.1582?

Die Behauptung - "bis man dan Daten vor 1970 berechnen muss" - an sich 
ist wertlos, wenn man dann nicht auf das aufgeworfene Problem eingeht.

Der TO hat vermutlich gar nicht die Vorkenntnisse um das einzuschätzen. 
Und bevor er mktime erwähnt hat, wusste man gar nicht, ob sein Problem 
nicht erst einmal nur darin liegt einen Vergleich für - im weitesten 
Sinne - Modulo-Bereiche zu formulieren.

> Wenn man es richtig macht ...

Was ist richtig, was ist falsch? Das hängt von dem Kenntnisstand ab.

Aber wenn ich eine Funktion postuliere, die eine Berechnung für Werte 
seit dem 1.1.1970 berechnet dann ist klar, dass sie nicht 
notwendigerweise für Werte davor gültige Resultate ergibt.

Der Satz fängt darüber hinaus falsch an. Die Voraussetzung war ja 
gerade, dass der Definitionsbereich damit anfängt. Damit ist die 
Funktion ihrer Definition nach "richtig" und es gibt kein "richtiger".

Es ist wirklich ärgerlich, dass hier alles und jedes relativiert wird. 
Ohne Erklärung, völlig unnötig, unvollständig und falsch.
Gast #4553378
Florian schrieb:
> Die Sache mit den Normierungsfunktionen (z.B. auf die Anzahl Tage seit
> dem 1.1.1970 oder so ähnlich) ist natürlich die beste Möglichkeit. Damit
> ist alles berücksichtigt, was normalerweise auftritt.

Wenn er eine 32-bit Variable nimmt, dann wird es ab dem 9. Januar 2038 
3:14:08 Uhr auch Probleme geben.

Was ist so schwer daran das ganze mit einer if Abfrage mit ein paar and 
zu klären:

if (((day   >= date_from.day)   && (day   <= date_to.day  )) &&
    ((month >= date_from.month) && (month <= date_to.month)) &&
    ((year  >= date_from.year)  && (year  <= date_to.year )))
Gast #4553396
Karl schrieb:
> if (((day   >= date_from.day)   && (day   <= date_to.day  )) &&
>     ((month >= date_from.month) && (month <= date_to.month)) &&
>     ((year  >= date_from.year)  && (year  <= date_to.year )))

Dann check mal was bei deinem tollen Konstrukt rauskommt wenn:
Das Datum der 20.4.2016 ist und
date_from der 28.02.2016
date_to der 4.5.2016
#4553408
Sollte eine einfache Prüfung von Anfang und Ende sein. Also (hopefully) 
sowas in der Art:
1
// verify range start
2
if (year < start.year) 
3
  return false ;
4
if (year == start.year) {
5
  if (month < start.month)
6
    return false ;
7
  if (month == start.month) {
8
    if (day < start.day)
9
      return false ;
10
  }
11
}
12
// verify range end
13
if (end.year < year) 
14
  return false ;
15
if (end.year == year) {
16
  if (end.month < month)
17
    return false ;
18
  if (end.month == month) {
19
    if (end.day < day)
20
      return false ;
21
  }
22
}
23
return true ;

Ein normalisiertes integer Format ist allerdings praktischer. Also 
Sekunden seit..., ich nehme gern die Julian Day Number 
(https://en.wikipedia.org/wiki/Julian_day).
Gast #4553409
> Wenn er eine 32-bit Variable nimmt, dann wird es ab dem 9. Januar 2038
> 3:14:08 Uhr auch Probleme geben.

Nicht mit obiger Formel, denn die berücksichtigt nur ganze Tage und hat 
mit 32-Bit kein Problem. Und es sind nur 2 Zeilen
Gast #4553430
Such mal mit dem Stichwort:
"Julianisches Datum" bzw.
"Julian day" für Ausländer.
Dafür gibt es fertige und wahrscheinlich geprüfte Funktionen im Netz.
Moderator Persönliche Seite #4553431
Frank M. schrieb:
> Beide Daten in einen String der Form "YYYYMMDD" umrechnen und beide
> Strings einfach strcmp() übergeben.

Beispiel:
1
  char tim1[9];
2
  char tim2[9];
3
  int  diff;
4

5
  sprintf (tim1, "%04d%02d%02d", start.year, start.month, start.day);
6
  sprintf (tim2, "%04d%02d%02d", end.year, end.month, end.day);
7

8
  diff = strcmp (tim1, tim2);
9

10
  if (diff < 0)
11
  {
12
      // kleiner
13
  }
14
  else if (diff > 0)
15
  {
16
      // größer
17
  }
18
  else
19
  {
20
      // gleich
21
  }


P.S.

Das war falsch:

Return-Werte:

>  -1 Datum1 kleiner Datum2
>   0 Datum1 gleich  Datum2
>   1 Datum1 größer  Datum2

Richtig ist:

  negativ  Datum1 kleiner Datum2
  0        Datum1 gleich  Datum2
  positiv  Datum1 größer  Datum2
#4553450
Ich glaube, Ihr denkt alle viel zu kompliziert!
Wenn die Aufgabe wirklich nur das ist, wie im Eingangspost beschrieben, 
kann man die Datum-Zahlen auch einfach in numerische Variablen schieben 
(Jahr auf die höchstwertigen Bits, Tage auf die niederwertigen) und die 
Zahlen mit einem stinknormalen, numerischen Vergleichsoperator 
verarbeiten.
Gast #4553464
@ Thomas Elger
Bei dem von mir vorgeschlagenen Julianischen Tag kommt eine "lineare" 
Ganzzahl zum Tragen, die sich einfachen Vergleichen unterziehen lässt.
#4553485
Thomas E. schrieb:
> Ich glaube, Ihr denkt alle viel zu kompliziert!

Stimmt! Bei dem Vergleich spielt es ja keine Rolle ob das Skalar 
durchgehend gültige Werte aufweist, oder nicht. Statt Bits würde ich 
aber mit den Wertebereichen (day=0..30,month=0..11) skalieren, also:
1
make_scalar(year,month,day) { return (day-1) + 31 * ( (month-1) + 12 * year ) ; }

Das liest sich einfach und ist damit quasi selbst dokumentierend. Man 
muss lediglich den Fall des Überlaufs ausschließen.
Gast #4553498
@ Thomas Elger
Wenn ich, aus welchen Gründen auch immer, die time-lib nicht einbinden 
möchte, der TO hat seine Zielplattform ja noch nicht verraten, würde ich 
mir die "übliche" Formel einfach mal ansehen.

Wird diese nicht 10000 mal pro Sekunde durchlaufen, so sehe ich auch auf 
schwachbrüstigen µP's kein Problem.

Im Übrigen hast Du ja allen kundgetan, was Du nicht machen würdest. Wie 
wäre es mal mit einem konstruktiven Vorschlag.
Gast #4553518
S.Siebenhaar schrieb:
> Im Übrigen hast Du ja allen kundgetan, was Du nicht machen würdest. Wie
> wäre es mal mit einem konstruktiven Vorschlag.

Dus schreibst um 10:45 gegen seinen Vorschlag von 10:36 und kannst dich 
um 11:13 schon nicht mehr daran erinnern?
Vieleicht mal zum Arzt gehen :-)
Gast #4553525
Also,

vielen Dank allen die sich an der Diskusion beteiligen.
Ich habe eine für mich arbeitende Lösung gefunden. Ich berechne mit 
timestamps mit mktime(). Das ist vielleicht nicht die performanteste, 
aber ich kann mir sicher sein dass alle Fälle abgedeckt sind.
Zumindest solange ich in dem notwendigen Zahlenraum bleibe. Also >1970.

Ich verabschiede mich dann hier aus dem Thread. ;-)

Vielen Dank wie gesagt allen noch einmal. THUMBS_UP

Gruß,
Bean
(Firma: Vescomp) #4553530
Cube_S schrieb:
> hier ein Code-Ausschnitt wie ich hin verwende:
>
1
> int k = Month > 2 ? Year : Year - 1;
2
> int f = Year * 365 + (k + 4) / 4 - k / 100 + k / 400 + (Month - 1) * 30 
3
> + (Month + Month / 8) / 2 + (Month > 2 ? Day - 2 : Day) - 1;
4
>
> f ist dann ein einfacher Zähler für Tage der sich auch leicht
> vergleichen lässt.

 Ja, sowas ähnliches habe ich auch, nur ist es für DayOfWeek, für
 einfaches Vergleichen von 2 Tagen ist es viel zu viel Rechnen.

 Wenn es um die Geschwindigkeit und Resources geht, lässt sich
 sein Problem am schnellsten mit einfachen if-vergleichen lösen.

 Etwa so:
Mikro 7. schrieb:
> Sollte eine einfache Prüfung von Anfang und Ende sein.

 Seine Lösung hat im ungünstigsten Fall 10 einfache Vergleiche, wenn
 jeder Schritt 2us braucht, sind es max. 20us. In Assembler würde man
 dafür weniger als 60Bytes brauchen (geschätzt). Und ein guter Compiler
 sollte auch nicht viel mehr brauchen.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 10 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.