Algorithmus für Zeit zw 2 Zeiten

Gast #1143731
Lesenswert?

Hi,

ich muss eine Messung durchführen, wenn die Zeit (die ich über einem RTC 
geschickt bekomme) zwischen 2 anderen Zeiten liegt.

Also z.b.

Start:
Sekunde, Minute, Stunde, Tag Monat, Jahr

Ende:
Sekunde, Minute, Stunde, Tag Monat, Jahr

Das einzige was mir da einfallen würde wäre, zuerst abzufragen, ob 
aktuelles Jahr zwischen Start und End-Jahr liegt. Wenn ja dann messen.
Wenn nicht, ist aktuelles Jahr = Start-Jahr, dann Frage Monat ab.... Das 
ganze zieht sich dann bis hin zu Sekunden.
Wenn aktuelles Jahr nicht gleich Start-Jahr ist, dann frage ab ob 
aktuelles Jahr gleich End-Jahr ist. Wenn ja, dann Frage Monat ab ob 
kleiner usw. bis Sekunden.

Der Algorithmus herfür wird mindestens 100 Codezeilen lang, gibt es 
dafür nicht irgendwie eine elegantere Lösung. Mir fällt dazu gerade aber 
gar keine andere Variante ein. Jemand eine Idee????
Gast #1143741
Lesenswert?

Bei den Monaten muss natürlich nicht nur geschaut werden ob kleiner oder 
größer, sondern ob Wert dazwischen liegt.

z.b. Startjahr 2000 und Startmonat 8
Endjahr 2000 und Endmonat 10

dann dürfte bei aktueller Zeit: Jahr 2000 und Monat 12 auch keine 
Messung stattfinden, was bedeutet, das der Code wieder extrem viel 
größer wird.

Ist es wirklich für so eine einfache Abfrage nötig, so viel Code zu 
schreiben?!
Gast #1143771
Lesenswert?

Boa danke! Ihr seid meine Rettung.

Das ist wirklich extrem gescheit, einfach alles in Sekunden umwandeln 
und dann brauche ich nur einen Vergleich!

Habs mir ausgerechnet, mit meinen IF abfragen hätte ich ungefähr 400 IF 
Anweisungen gebraucht.

Danke Leute!
#1143776
Lesenswert?

???? wrote:

> Der Algorithmus herfür wird mindestens 100 Codezeilen lang

Also ich komme auf 14 Codezeilen:
1
#include <stdio.h>
2

3

4
struct time {
5
  uint8_t se;
6
  uint8_t mi;
7
  uint8_t ho;
8
  uint8_t da;
9
  uint8_t mo;
10
  uint8_t ye;
11
};
12

13

14
struct time start, end, now;
15

16

17
uint32_t get_sec( struct time t )
18
{
19
  return ((((t.ye * 12UL + t.mo) * 31 + t.da) * 24 + t.ho) * 60
20
         + t.mi) * 60 + t.se;
21
}
22

23

24
uint8_t dazwischen( void )
25
{
26
  uint32_t now_sec = get_sec(now);
27

28
  return now_sec > get_sec(start) && now_sec < get_sec(end);
29
}


Peter


P.S.:
Es reicht, wenn get_sec monoton ist, die Lücken stören also nicht.
Gast #1143778
Lesenswert?

Bilde doch die Differenz aus dem gregorianischer Kalender.

mit (jeweils 1 und 2):
y als Jahr
m als monat
d als tag
1
dTage=(y1-y2)*365 + y1 DIV 4 - y2 DIV 4 - y1 DIV 100 + y2 DIV 100 + y1 DIV 400 - y2 DIV 400 
2
+ (m1*306+5)/10 - (m2*306+5)/10 + (d1-1) - (d2-1);

Damit solltest du die Differenz in Tage erhalten (inklusive 
Schaltjahre).
(keine Gewähr ;) )

Dann noch die Stunden (std), Minuten (min) und Sekunden (sec) 
hinzurechen:
1
dSekunden=dTage*86400 + (std1-std2)*3600 + (min1-min2)*60 + (sec1-sec2)

Das müsste funktionieren...
Gast #1143779
Lesenswert?

>ich muss eine Messung durchführen, wenn die Zeit (die ich über einem RTC
>geschickt bekomme) zwischen 2 anderen Zeiten liegt.

Liefert die RTC BCD Werte?
Dann kannst du die Zeit in z.B. zwei 32 Bit Variablen
schieben. Damit reduzieren sich die Vergleiche erheblich.
Gast #1143786
Lesenswert?

Öhm ich habe noch eine Frage dazu...
Wenn ich das Jahr in Sekunden umrechne, wären das 31 536 000 Sekunden. 
So jetzt gibt es aber Schaltjahre, das heißt ein Schaltjahr hätte 31 622 
400 Sekunden. Muss ich das irgendwie berücksichtigen?
Oder soll ich pro Jahr 31556926 Sekunden nehmen (was der Mittelwert 
wäre: 365 Tage + 5 Stunden + 48 Minuten + 46 Sekunden )
Gast #1143795
Lesenswert?

Also der Source von Peter Dannegger schaut sehr gut aus, ich glaube so 
werde ich es wirklich machen. Großes danke.

Allerdings hast du 31 * Monate geschrieben, damit gehst du davon aus, 
das jeder Monat 31 Tage hat... Geht das so einfach???
#1143807
Lesenswert?

holger wrote:
> Dann kannst du die Zeit in z.B. zwei 32 Bit Variablen
> schieben. Damit reduzieren sich die Vergleiche erheblich.

Stimmt, der Code wird deutlich kürzer:
1
uint32_t get_sec( struct time t )
2
{
3
  return ((((((((((uint32_t)t.ye<<4) + t.mo)<<5) + t.da)<<5) + t.ho)<<6)
4
         + t.mi)<<6) + t.se;
5
}
Es sind dann aber nur 64 Jahre Differenz möglich.


Peter
Gast #1143808
Lesenswert?

...

und wie wandle ich dann die Monate in Sekunden um????

Sollte ich direkt die Jahre in Sekunden umwandeln und dann den Monat mit 
select case einzeln in 12 abfragen in Sekunden umwandeln??? Sorry jungs, 
aber mir fällt dazu wieder keine bessere Idee ein....
#1143814
Lesenswert?

Klaus wrote:
> ... nein

Für die vorliegende Aufgabenstellung: Ja, kann man so machen.
Wichtig ist nur, dass sich eine mit der Zeit aufsteigende Zahlenfolge 
ergibt. Ob da jetzt Lücken drinn sind oder nicht, spielt keine Rolle.
Peters Verfahren stellt sicher, dass für 00:00:01 am 1. März eine 
größere Zahl rauskommt als für den 28.Februar 23:59:59. Mehr braucht es 
auch nicht. Niemand verlangt, dass zwischen beiden Zeitpunkten in 
Zahlenform nur eine Differenz von 2 liegen muss. Größer reicht schon.
Gast #1143820
Lesenswert?

> dann den Monat mit
> select case einzeln in 12 abfragen in Sekunden umwandeln???

Der Februar hat nicht immer gleich viele Tage ;)

Ohne gregorianische Kalender wirst du hin und wieder kräftige Sprünge in 
deiner Zeitdifferenz bekommen.
Gast #1143868
Lesenswert?

@ Peter
>> Dann kannst du die Zeit in z.B. zwei 32 Bit Variablen
>> schieben. Damit reduzieren sich die Vergleiche erheblich.

>Es sind dann aber nur 64 Jahre Differenz möglich.

Ich meinte tatsächlich zwei 32 Bit Variablen pro Uhrzeit.
Wenn die RTC BCD Code liefert einfach alle Werte in ein
eigenes Byte schieben. Also nicht Bits sparen wie du es gemacht hast.
Oder ein long long mit 64 Bit wenn der Compiler das mag.
Das sollte bis 9999 reichen. Danach interessiert es wohl
keinen mehr ;)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren