Zeit Differenz berechnen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 12. November 2008, 14:42

``datetime`` wurde schon vorgeschlagen, PEP8 auch.

Wenn die Parameter feststehen müssen könnte man das so lösen:

Code: Alles auswählen

import datetime

def diff_to_time(weekday, hours):
    hour, minute = divmod(hours, 100)
    now = datetime.datetime.now()
    day_now = now.weekday()
    forward = weekday - day_now
    if forward <= 0:
        forward += 7
    future_day = now + datetime.timedelta(days=forward)
    point_in_time = datetime.datetime(future_day.year, future_day.month,
            future_day.day, hour, minute)
    delta =  point_in_time - now
    return delta.days * 60 * 60 * 24 + delta.seconds

print diff_to_time(0, 1500)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Mittwoch 12. November 2008, 14:47

@cofi: Das wird dadurch nicht unbedingt kürzer und übersichtlicher. Es sei denn, es wäre okay einen Generator für die folgenden Tage zu basteln, der dann maximal 7 mal aktiviert wird. Oder ich habe mich einfach zu dumm angestellt das mit `datetime` zu lösen.

@limepix: Du könntest im Style Guide ein wenig lesen.

Warum ist das eine Methode und keine Funktion?

Statt Indizes würde ich bei `current` die Attribute verwenden. Ist IMHO lesbarer. Also zum Beispiel ``current.tm_wday`` statt ``current[6]``.

Die Argumente würde ich ändern. Beim ersten den Namen in `weekday` oder `next_weekday` und aus dem zweiten Argument würde ich zwei machen: `next_hour` und `next_minutes`.

Irgendwo müsste dann ja trotzdem der Code zum Aufteilen so einer Zahl in Stunden und Minuten erfolgen und den würde ich nicht über den Umweg über Zeichenketten machen. ``next_hour, next_minutes = divmod(next_time, 100)`` wäre einfacher und direkter.

Kann man das ``if``/``else`` am Ende nicht eventuell mit dem Modulo-Operator erschlagen?
BlackJack

Mittwoch 12. November 2008, 14:51

@Leonidas: Wenn der gewünschte Wochentag der heutige ist, die Zeit aber noch in der Zukunft liegt, schlägst Du trotzdem eine Woche drauf. Den Fehler hatte ich bei meinem Versuch auch gemacht. :-)
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Mittwoch 12. November 2008, 15:07

BlackJack hat geschrieben:@Leonidas: Wenn der gewünschte Wochentag der heutige ist, die Zeit aber noch in der Zukunft liegt, schlägst Du trotzdem eine Woche drauf. Den Fehler hatte ich bei meinem Versuch auch gemacht. :-)
Ich weiß. Ich habe da nicht genau verstanden was der OP meinte. Ich denke dass es am schlauesten wäre wenn der Wochentag dem heutigen entspricht zu prüfen ob die Uhrzeit größer oder kleiner der aktuellen Uhrzeit ist und dann ggf eine Woche auzuschlagen. Aber ich wusste nicht genau was der OP da für ein Verhalten haben will (und seinen Code habe ich erst recht nicht nachzuvollziehen versucht).

Also etwa so:

Code: Alles auswählen

import datetime

def diff_to_time(weekday, hours):
    hour, minute = divmod(hours, 100)
    now = datetime.datetime.now()
    day_now = now.weekday()
    if weekday == day_now:
        today_at_time = datetime.datetime(now.year, now.month, now.day,
            hour, minute)
        if now < today_at_time:
            forward = 0
    else:
        forward = weekday - day_now
        if forward < 0:
            forward += 7
    future_day = now + datetime.timedelta(days=forward)
    point_in_time = datetime.datetime(future_day.year, future_day.month,
            future_day.day, hour, minute)
    delta =  point_in_time - now
    return delta.days * 60 * 60 * 24 + delta.seconds

print diff_to_time(2, 1500)
Aber man merkt schon, dass wenn der 1. Parameter nicht so blöd wäre, die Funktion eleganter wäre, weil man dann nicht raten müsste was gemeint ist.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Mittwoch 12. November 2008, 15:13

Ich denke mal die Motivation wird so etwas sein wie "Jeden Dienstag um 15⁰⁰ Uhr kommt der Eiswagen, wie lange muss ich bis dahin noch warten?"

Ich denke der Code mit `datetime` ist nicht wesentlich kürzer und eleganter als es "per Hand" zu machen.
Benutzeravatar
limepix
User
Beiträge: 37
Registriert: Dienstag 11. November 2008, 16:54

Mittwoch 12. November 2008, 15:42

@BlackJack: Danke für die Kritik ... ich druck nen mir mal aus und leg nen mir mal unters kopfkissen ;-) ... werd auf jeden fall mal reinschaun

zum hintergrund: es soll eine art "taskplaner" entstehen - so wie das ding in windows. unserer soll per xml konfigurierbar sein

die xml struktur ist fest vorgegeben und schaut so aus:

Code: Alles auswählen

<?xml version="1.0" encoding="windows-1250"?>
<scheduler>    
  <module>
    <name>blaa</name>
    <active>1</active>
    <exec>C:\foo.py</exec>
    <time>
      <type>interval</type>
      <val>30</val>      
    </time>
  </module>
    
  <module>
    <name>doing</name>
    <active>1</active>
    <exec>C:\doing.py</exec>
    <time> 
        <mon>
           <val>09:20</val>  
           <val>13:18</val>             
        </mon>
        <wed>
           <val>14:30</val>             
        </wed>
    </time>
  </module>
</scheduler>
@BlackJack: es ist teil eine klasse namens scheduler...

so wieder zum allgemeinen...
ich weiss meinen jetzigen zeitpunkt, dazu gehört der wochentag, die stunde und die minute (auf gut deutsch - die uhrzeit) und anhand der xml weiss ich vom nächsten zeitpunkt ebenfalls wochentag, stunde und minute.
beispiel vom modul doing: nächster montag 9:20

meine vorgehensweise ist nun

1. minuten bis ende der aktuellen stunde ermitteln
2. stunden bis ende des aktuellen tages ermitteln
3. tage bis ende der aktuellen woche ermitteln

diese drei werte ergeben die zeit-bis-zum-ende-der-woche.

für unseren zeitpunkt hab ich ja schon alles:
0 tage (montag...)
9 stunden (9:uhr...)
15 minuten(:15 minuten...)

nun ist ja zeit-bis-zum-ende-der-woche + 0,9,15 = zeit bis zu dem zeitpunkt von dem ich bislang immer ausgehe, dass er in der nächsten woche ist.
wenn nun das was ich rausbekommen hab größer ist wie die gesamte anzahl in sek einer woche, weiss ich, dass ich mich quasi einmal selber "überrannt" habe und ziehe einfach eine woche in sekunden von meinem ergebnis ab...

ich hoff des war einigermaßen verständlich :oops:

nochmal @ BlackJack: weil ichs gerade gelesen hab:
mag sein, dass es eleganter geht (deswegen bin ich hier und frag nach ;-) ), aber als übung für unsre azubis hier wie man logisch / händisch an sowas ranzugehen hat, geh ich den weg auch gerne mal zu fuß :-) ... wenn mir nun noch ein spezl hier eine "2-zeilen-mega-schick" lösung präsentieren kann - nur her damit, dann kann ich auch ein "so" & "so nicht" zeigen :-)


vielen dank auf jeden fall für eure mühe und die superschnellen antworten :-)

Edit (BlackJack): Der Highlighter kann zwar nicht viel, aber XML kennt er :-) -> Highlighting von Python auf XML umgestellt.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Mittwoch 12. November 2008, 16:21

limepix hat geschrieben:wenn mir nun noch ein spezl hier eine "2-zeilen-mega-schick" lösung präsentieren kann - nur her damit
Da genügt eine Zeile - wenn sie lang genug ist:

Code: Alles auswählen

from time import localtime
sec_bis_zeitpunkt = lambda tag,zeit:(tag*1440+sum([int(el)*60**(1-k) for k,el in enumerate(zeit.split(":"))])
                    +10080-(localtime()[6]*1440+localtime()[3]*60+localtime()[4]))%10080*60
print sec_bis_zeitpunkt(2,"17:00")
Edit: Zeilenumbruch eingefügt ...
Zuletzt geändert von numerix am Mittwoch 12. November 2008, 20:03, insgesamt 1-mal geändert.
Benutzeravatar
wuf
User
Beiträge: 1483
Registriert: Sonntag 8. Juni 2003, 09:50

Mittwoch 12. November 2008, 16:28

Hallo limepix

Sorry meine peinliche Frage. Warum wird bei deiner Funktion Jahr und Monat nicht brücksichtigt?

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
limepix
User
Beiträge: 37
Registriert: Dienstag 11. November 2008, 16:54

Mittwoch 12. November 2008, 18:02

wieso denn peinliche frage?? ^^

ganz einfach - es muss nicht berücksichtigt werden / wird nicht gebraucht
(kuck dir die xml mal an, da steht nichts von monaten oder jahren drin ;-) ) (wäre aber vllt ne schöne erweiterung die ich mit aufnehmen könnte - danke für den tip ;-) )

das beispiel von zuvor gefällt mir eigentlich am besten:
du weisst, dass jeden mittwoch um 15:00 Uhr der Eismann kommt und möchstest nun wissen, wie lange es bis dahin noch dauert.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Mittwoch 12. November 2008, 18:29

Du meinst etwas ähnliches wie Cron?
Benutzeravatar
wuf
User
Beiträge: 1483
Registriert: Sonntag 8. Juni 2003, 09:50

Mittwoch 12. November 2008, 18:50

Hallo limepix

Danke für die Antwort. Leider spreche ich die Sprache 'xml' nicht. Aber ich glaube deine Aufgabe wäre ideal für 'azubis'. Hast du das Modul 'time' schon einmal genauer angeschaut? Ist eine Fundgrube für realistische Zeitberechnungen.

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Mittwoch 12. November 2008, 19:28

@limepix: Hast du meinen Einzeiler mal ausprobiert?
Oder müssen es für deine "mega-schick"-Lösung unbedingt zwei Zeilen sein?

Das sollte dann nicht das Problem sein: :D

Code: Alles auswählen

sec_bis_zeitpunkt = lambda tag,zeit:(tag*1440+sum([int(el)*60**(1-k) for k,el in enumerate(zeit.split(":"))])
                    +10080-(localtime()[6]*1440+localtime()[3]*60+localtime()[4]))%10080*60
Liefert z.B.:

Code: Alles auswählen

In [4]: sec_bis_datum(3,"20:15")
Out[4]: 89340
BlackJack

Mittwoch 12. November 2008, 19:59

@limepix: Du sagst zwar die XML-Struktur ist fest vorgegeben, aber mit fällt ein deutlicher Mangel an Attributen auf.

Und wenn ich mir die XML ansehe frage ich mich wie da aus einer Uhrzeit der Form '09:20' irgend wann im Programm die ganze Zahl 920 werden kann. Denn in der Form nimmt Deine Funktion das ja anscheinend entgegen. Wenn man so eine Uhrzeit "leichtgewichtig" als eine Einheit im Programm herum reichen will, bietet sich ein Tupel an.

Meine Frage nach der Methode war dadurch motiviert, dass es nur technisch gesehen eine Methode ist. Praktisch wird `self` nicht verwendet und damit könnte man es auch als (Hilfs)Funktion ausserhalb der Klasse platzieren. Falls es thematisch doch zu sehr mit der Klasse verbunden ist, könntest Du eine `staticmethod` daraus machen, dann weiss man dass das eigentlich eine Funktion ist und kann es auch so auf der Klasse aufrufen.

@numerix: Die Funktion kann böse daneben liegen, wenn man sie um Mitternacht herum aufruft, wenn die verschiednenen Aufrufe von `localtime()` nicht alle am gleichen Tag erfolgen. Und Dein Beitrag ist Schuld daran, dass ich jetzt beim lesen der anderen Beiträge einen vertikalen Scrollbalken bemühen muss. Grrr. ;-)
Benutzeravatar
limepix
User
Beiträge: 37
Registriert: Dienstag 11. November 2008, 16:54

Mittwoch 12. November 2008, 20:09

@ str1442: genau! sowas in die richtung - allerdings muss ich das alles händisch machen, für mein ihk projekt... ich hab das gesamte programm schon in c++ geschrieben, sollte es nun nochmal in python "nachschreiben" - so bin zu python gekommen ;-)
ziel des ganzen ist, den "wenigeraufwand" zu c++ zu ermitteln - wenn das für den teil in den die entwicklungrichtung unserer firma geht "große" vorteile bringt, wird python als neue sprache für die gesamte entwicklung / neue sachen herangezogen :-)

@numerix: FREAK! :wink: das schaut ja wild aus... um damit mal anzugeben, werd ichs einfach mal zeigen - das wird die vom hocker haun ;-)

danke nochmal
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Mittwoch 12. November 2008, 20:09

BlackJack hat geschrieben:@numerix: Die Funktion kann böse daneben liegen, wenn man sie um Mitternacht herum aufruft, wenn die verschiednenen Aufrufe von `localtime()` nicht alle am gleichen Tag erfolgen. Und Dein Beitrag ist Schuld daran, dass ich jetzt beim lesen der anderen Beiträge einen vertikalen Scrollbalken bemühen muss. Grrr. ;-)
Hab ich ja auch nur zum Angeben gemacht ... und jetzt geändert.

Ja, das mit Mitternacht ist ein echtes Problem. Ich stell mir das grad vor, wenn man ein paar Millisekunden vor Mitternacht das Programm startet, um nochmal kurz zu checken, wie lange es dauert, bis der Eismann kommt, und dann verpasst man am Ende noch den Eismann, weil das Programm nicht funktioniert hat. :cry:
Antworten