Datum +x Tage - timedelta eingeben & Wochentag Berechnung

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.
Antworten
Justifiez
User
Beiträge: 13
Registriert: Montag 26. Mai 2014, 19:48

Liebe Leute,

ich hab zwei Probleme, die allerdings nicht schwerwiegend sind und würde euch bitten mir zu helfen. Ich selbst bin Python-Neuling.

Mein erstes Problem ist bei einem Programm, bei dem auf ein Datum eine bestimmte Anzahl von Tagen draufaddiert werden soll bzw. eine bestimmte Anzahl von Tagen abgezogen werden soll.

Code: Alles auswählen

import datetime
import time
from datetime import datetime
from datetime import timedelta
from time import mktime

datum = input('Datum: ')
timedelta(input('Abstand: '))
datum1 = time.strptime(datum, '%Y-%m-%d')
datum2 = (datetime.fromtimestamp(mktime(datum1)) - timedelta)
print(datum2.strftime('%Y-%m-%d'))
Ich würde mein "timedelta" gerne selbst bestimmen, also mir aussuchen können, wieviele Tage ich addiere oder subtrahiere. Das heißt ich würde sie gerne selbst eingeben. Habt ihr eine Idee, wie das funktionieren kann?
Ich wüsste, wie es funktioniert, wenn ich im Code den Abstand verändere. Das würde dann so aussehen:

Code: Alles auswählen

import datetime
import time
from datetime import datetime
from datetime import timedelta
from time import mktime

datum = input('Datum: ')
datum1 = time.strptime(datum, '%Y-%m-%d')
datum2 = (datetime.fromtimestamp(mktime(datum1)) - timedelta(1000))
print(datum2.strftime('%Y-%m-%d'))
Ok, und mein zweites Problem betrifft ein anderes Programm, bei dem ich herausfinden will, welches Datum welchen Wochentag hatte. Ich habe das auch schon fertig, allerdings auch noch ne zweite Variante bei der ich nicht weiterkomme:

Code: Alles auswählen

jahr = input('Jahr: ')
monat = input ('Monat: ')
tag = input ('Tag: ')

j = int(jahr) % 100
c = int(jahr) / 100

if int(monat) == 5: int(k) == 0 #hier fehlen noch einige Befehle, die im Prinzip genauso aussehen

d = int(tag) + k + j + j / 4 - 2 * (c % 4)

wochentag = d % 7

if wochentag == 0:
    print ("Sonntag")
elif wochentag == 1:
    print ("Montag")
elif wochentag == 2:
    print ("Dienstag")
elif wochentag == 3:
    print ("Mittwoch")
elif wochentag == 4:
    print ("Donnerstag")
elif wochentag == 5:
    print ("Freitag")
elif wochentag == 6:
    print ("Samstag")
else:
    print ("Fehler")
Wenn ich das Programm ausführe, kommt als Fehler, das mein "k" nicht definiert wurde. Wie kann ich das denn machen?
Das "k" soll Werte zwischen 0 und 5 annehmen und beschreibt die Monate.
Die Formel mit dem "d" am Anfang ist irgendwie von KREUZFELDT, falls euch das was sagt.

Ich weiß, dass es für diese Funktion einen Zweizeiler gibt, der aber direkt in der Python-IDLE eingeben wird. Das will ich eigentlich nicht.


Ich hoffe, dass das jetzt nicht zuviel war. Wenn ja, splitte ich das nochmal in zwei Beiträge.

Ich würde mich über eine Antwort sehr freuen. Danke schonmal im Voraus :)

Grüßle
Arv
Malta
User
Beiträge: 83
Registriert: Samstag 8. Januar 2011, 23:51

Hallo,

du musst timedelta einer Variable zuweisen und mit %A wird der Wochenname angezeigt. Was mich ein wenig wundert ist das der Wochentag in Englisch angezeigt wird, und nach Umstellung auf DE in Deutsch. Komisch dabei ist das es davor schon auf DE war.

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import datetime
import locale

loc = locale.getlocale()
print (loc)

datum = input('Datum: ')
td = datetime.timedelta(int(input('Abstand: ')))
datum1 = time.strptime(datum, '%Y-%m-%d')
datum2 = (datetime.datetime.fromtimestamp(time.mktime(datum1)) - td)
print(datum2.strftime('%Y-%m-%d'))
  
print(datum2.strftime('Der Wochentag ist %A'))
locale.setlocale(locale.LC_ALL, ('de_DE', 'UTF-8'))
print(datum2.strftime('Der Wochentag ist %A'))
$ ./test_timedelta.py
('de_DE', 'UTF-8')
Datum: 2014-5-4
Abstand: 77
2014-02-16
Der Wochentag ist Sunday
Der Wochentag ist Sonntag
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@Justifiez
Zu Deinem 1. Problem:
Dein Importe überschreiben sich gegenseitig. Warum nicht einfach ``import datetime``? Damit hast Du alle datumsrelevanten Vorgänge an `datetime` gebunden was den Vorteil hat, dass innerhalb des Codes auf einen Blick erkennbar ist, woher eine Funktion/Klasse stammt. Es ist jetzt nicht falsch, nach einem ``from datetime import datetime, timedelta`` direkt auf `datetime` und `timedelta` zuzugreifen. Ich persönlich bevorzuge es allerdings, ein Modul komplett zu importieren und dann über den Punktoperator auf dessen Objekte zuzugreifen.
Das `time` Modul ist für Dein Problem nicht nötig.
Wenn Du, so wie Du es bereits mit `datum` machst, den `timedelta` Wert an einen Namen bindest, kannst Du das dann auch benutzen. Dein ``timedelta(input('Abstand: '))`` erstellt ein `timedelta`-Exemplar und lässt es im Nirvana stehen, da kein Name definiert wird, über den ich darauf zugreifen kann. Also in seiner einfachsten Form würde ich es so machen:

Code: Alles auswählen

import datetime

def convert_datetime(datestring):
    return datetime.datetime.strptime(datestring, '%Y-%m-%d')

def add_days():
    date = input('Datum (yyyy-mm-dd): ')
    delta = input('Abstand in Tagen: ')
    return convert_datetime(date) + datetime.timedelta(days=int(delta))

Code: Alles auswählen

>>> date_delta.add_days()
Datum (yyyy-mm-dd): 2014-5-27
Abstand in Tagen: 5
datetime.datetime(2014, 6, 1, 0, 0)
Zu Deinem 2. Problem:
Auch das lässt sich sehr einfach mit Boardmitteln erledigen. Sowohl `datetime.date` als auch `datetime.datetime` Exemplare verfügen über eine `weekday()`-Methode, die Dir die Nummer des Werktages zurückgibt. Dabei ist 0 der 1. Werktag (i. d. R. Montag) und 6 der letzte Werktag.
Könnte demnach so aussehen:

Code: Alles auswählen

def get_weekday():
    weekdays = ('Montag', 'Dienstag', 'Mittwoch',
                'Donnerstag', 'Freitag', 'Samstag', 'Sonntag')
    date = input('Datum (yyyy-mm-dd): ')
    return weekdays[convert_datetime(date).weekday()]

Code: Alles auswählen

>>> date_delta.get_weekday()
Datum (yyyy-mm-dd): 2014-5-27
'Dienstag'
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Justifiez
User
Beiträge: 13
Registriert: Montag 26. Mai 2014, 19:48

Vielen Dank mututella und Malta!
Sorry, dass ich mich so spät melde, ich war den ganzen Tag unterwegs und bin erst jetzt dazu gekommen, mir das mal anzuschauen.

mututella, ich komme mit deinem Quellcode nicht ganz klar. Bzw. mit dem Ausführen des Quellcodes.
Wenn ich die Codes ausführe, müsste ich ja in der Python IDLE die Daten (Datum bzw. Datum & Abstand) eingeben können. Kann ich aber nicht.
Es wird mir auch nicht ausgegeben.
Hat das was mit dem "return"-Befehl zu tun? Der unterscheidet sich ja von dem "print"-Befehl.
Die Antwort ist wahrscheinlich total offensichtlich, aber ich habe keinen Plan wie.

Grüßle
Arv
BlackJack

@Justifiez: Wenn Du keine Funktionen kennst, solltest Du am besten mal ein Grundlagentutorial durcharbeiten. In der Python-Dokumentation befindet sich eines und für absolute Programmieranfänger wird oft Learn Python The Hard Way empfohlen (nicht vom Namen irritieren lassen).
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@Justifiez
Mein Beispielcode enthält 3 Funktionen, die jede für sich eine bestimmte Aufgabe übernimmt. Wenn Du diese Funktionen innerhalb Deiner IDLE in die Shell tippst, hast Du zwar die Funktionen erstellt, musst sie aber natürlich auch ausführen. Gib einmal in der Shell folgendes ein:

Code: Alles auswählen

>>> import datetime
>>> def convert_datetime(datestring):
    return datetime.datetime.strptime(datestring, '%Y-%m-%d')
Damit hast Du das `datetime` Modul importiert und die Funktion `convert_datetime()`, die auf dieses Modul zugreift, angelegt. Im Namensraum Deiner Shell befindet sich nun der Name 'datetime', der auf das Modul mit allen seinen Klassen und Funktionen verweist und der Name 'convert_datetime', der auf die Funktion verweist. Wie gesagt, eine Funktion beginnt erst zu arbeiten, wenn sie aufgerufen wird:

Code: Alles auswählen

>>> convert_datetime('2014-5-28')
datetime.datetime(2014, 5, 28, 0, 0)
Nun macht es natürlich wenig Sinn, alle Funktionen, die man verwendet, jedes mal in die Shell tippen zu müssen. Deshalb würde ich die 3 Funktionen in einem Modul (.py-Datei) zusammenfassen. Lege dazu eine neue Datei an und tippe dort meinen Beispielcode ein. Danach speicherst Du diese z. B. als ``date_utils.py`` ab. Nun importierst Du Dein gerade erstelltes Modul `date_utils` und führst eine Funktion daraus aus:

Code: Alles auswählen

>>> import date_utils
>>> date_utils.add_days()
Datum (yyyy-mm-dd): 2014-5-28
Abstand in Tagen: 4
datetime.datetime(2014, 6, 1, 0, 0)
Noch eine Anmerkung: Wenn Du ein bereits importiertes Modul veränderst, z. B. eine Funktion hinzufügst oder innerhalb einer Funktion etwas umschreibst, musst Du die Shell neu starten und das Modul erneut importieren. Das liegt daran, dass Python ein Modul lediglich einmal importiert. Ein erneuter Import überschreibt nicht das bereits importierte, sondern wird ignoriert.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@mutetella: Einmal importierte Module kann man mittels `reload(modulname)` erneut laden und dadurch ihre aktualisierte Version nutzen.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@snafu
Aber nicht unter Python 3 das Justifiez offensichtlich verwendet...

mutetella


EDIT: Ok, `imp.reload()` unter Python 3, allerdings halte ich zumindest innerhalb der IDLE einen Neustart der Shell für sinniger, da `reload()` leider nicht rekursiv neu lädt...
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Justifiez
User
Beiträge: 13
Registriert: Montag 26. Mai 2014, 19:48

Hey,

vielen Dank nochmal für die hilfreichen Antworten! Ich habe vor allem verstanden, wie das mit dem importieren der Module funktioniert.
Ich habe das ganze mal weitergeführt, bin aber wieder hängen geblieben. Vlt hat ja jemand Lust, mir da noch weiterzuhelfen. Wäre echt top :)

Ich habe jetzt also mit den date_utils von mututella weitergearbeitet und dem noch zwei weitere Funktionen hinzugefügt:

Code: Alles auswählen

def date_difference():
    date1 = input('Datum1(yyyy-mm-dd): ')
    date2 = input('Datum2(yyyy-mm-dd): ')
    return date1 - date2

def comparison():
    date1 = input('Tag1(yyyy-mm-dd): ')
    date2 = input('Tag2(yyyy-mm-dd): ')
    return ((print('Tag 1 ist vor Tag 2')) + date1 < date2)
Wenn ich allerdings comparison() ausführe kommt das bei raus:

Code: Alles auswählen

>>> import date_utils
>>> date_utils.comparison()
Tag1(yyyy-mm-dd): 2014-5-26
Tag2(yyyy-mm-dd): 2014-5-27
Tag 1 ist vor Tag 2
Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    date_utils.comparison()
  File "/Users/Arv/Desktop/Python Programme/date_utils.py", line 25, in comparison
    return ((print('Tag 1 ist vor Tag 2')) + date1 < date2)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'
Und wenn ich date_difference() ausführe, passiert das:

Code: Alles auswählen

>>> date_utils.date_difference()
Datum1(yyyy-mm-dd): 2014-5-26
Datum2(yyyy-mm-dd): 2014-6-1
Traceback (most recent call last):
  File "<pyshell#12>", line 1, in <module>
    date_utils.date_difference()
  File "/Users/Arv/Desktop/Python Programme/date_utils.py", line 20, in date_difference
    return date1 - date2
TypeError: unsupported operand type(s) for -: 'str' and 'str'
Hat jemand einen Plan, was daran falsch ist und würde mir helfen wollen?

Liebe Grüße
Arv
BlackJack

@Justifiez: Die Meldungen sind doch eigentlich recht deutlich: Du kannst Zeichenketten nicht voneinander abziehen, was soll denn 'Hallo' - 'Welt' auch für ein Ergebnis haben!?

Und man kann `None` mit ``+`` benutzen. Dazu solltest Du Dir mal die Teilergebnisse von den Teilausdrücken in der `comparison()`-Funktion in der letzten Zeile klar machen. Notfalls mal einzeln auswerten lassen und ausgeben lassen, sowohl Typ als auch Wert.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Spielst du gerade "Python-Syntax raten"?

Was soll das da darstellen?
Justifiez hat geschrieben:

Code: Alles auswählen

    return ((print('Tag 1 ist vor Tag 2')) + date1 < date2)
Du nimmst den Rückgabewert von print (welcher immer None ist) und versuchst den mit einem String zu verketten um dann das Ergebnis mit einem weiteren String zu vergleichen. Das Ergebnis dieses Vergleichs möchtest du dann zurückgeben.

Deine Codebeispiele scheitern schon daran, dass du aus den Strings erst echte Datumswerte erzeugen musst, aber das da ist einfach nur völlig verkorkst.
Justifiez
User
Beiträge: 13
Registriert: Montag 26. Mai 2014, 19:48

Ich wollte eigentlich in der Ausgabe dafür sorgen, dass nicht einfach die Meldung "True" oder "False" erscheint, sondern eine Aussage macht wie:
"Tag 1 liegt vor Tag 2: True"
Lasse ich diesen print-Befehl weg, funktioniert es ja.

Code: Alles auswählen

def comparison():
    date1 = input('Tag1(yyyy-mm-dd): ')
    date2 = input('Tag2(yyyy-mm-dd): ')
    return (date1 < date2)
Ausgabe:

Code: Alles auswählen

>>> import date_utils
>>> date_utils.comparison()
Tag1(yyyy-mm-dd): 2014-5-27
Tag2(yyyy-mm-dd): 2014-5-28
True
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Justifiez: Was hältst du hiervon:

Code: Alles auswählen

>>> import date_utils
>>> date_utils.comparison()
Tag1(yyyy-mm-dd): 2014-13-32
Tag2(yyyy-mm-dd): hallo
True
Ich schlage vor, du schaust dir mutetellas Beitrag nochmal etwas genauer an.
In specifications, Murphy's Law supersedes Ohm's.
Justifiez
User
Beiträge: 13
Registriert: Montag 26. Mai 2014, 19:48

Oha, ok. Hab das jetzt nochmal überarbeitet und meinen Kopf rauchen lassen, und bin bis hierher gekommen:

Code: Alles auswählen

def date_difference():
    date1 = input('Jüngeres Datum (yyyy-mm-dd): ')
    date2 = input('Älteres Datum (yyyy-mm-dd): ')
    return convert_datetime(date1) - convert_datetime(date2)

def comparison():
    date1 = input('Tag1(yyyy-mm-dd): ')
    date2 = input('Tag2(yyyy-mm-dd): ')
    abstand = (convert_datetime(date1) - convert_datetime(date2))
    if abstand < datetime.timedelta(0):
        print ('Tag 1 ist älter als Tag 2.')
    elif abstand > datetime.timedelta(0):
        print ('Tag 1 ist jünger als Tag 2.')
    elif abstand == datetime.timedelta(0):
        print ('Same')
Es funktioniert alles. Bei Angaben wie "Hallo" oder Ähnlichen meckert Python auch rum. Also passt das.
Danke für eure Hilfe! Besonders an mutetella, durch dich habe ich den Funktionenkram verstanden.

Grüßle
Arved
BlackJack

@Justifiez: Das mit dem `abstand` ist unnötig kompliziert. Und wenn man im letzten Zweig einen Test hat der unnötig ist weil alle vorhergehenden Tests diesen einen Fall übrig lassen, dann kann man den Test auch weglassen und ``else`` verwenden.
Justifiez
User
Beiträge: 13
Registriert: Montag 26. Mai 2014, 19:48

Das das mit dem Abstand sinnlos war, wusste ich eigentlich schon.
Die Sache mit dem else habe ich verrafft. Danke.
Also so:

Code: Alles auswählen

def comparison():
    date1 = input('Tag1(yyyy-mm-dd): ')
    date2 = input('Tag2(yyyy-mm-dd): ')
    if (convert_datetime(date1) - convert_datetime(date2)) < datetime.timedelta(0):
        print ('Tag 1 ist älter als Tag 2.')
    elif (convert_datetime(date1) - convert_datetime(date2)) > datetime.timedelta(0):
        print ('Tag 1 ist jünger als Tag 2.')
    else: 
        print ('Same')
Grüßle
Arv
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast das mit dem Abstand genau verschlimmbessert:

Code: Alles auswählen

def comparison():
    date1 = convert_datetime(input('Tag1(yyyy-mm-dd): '))
    date2 = convert_datetime(input('Tag2(yyyy-mm-dd): '))
    if date1 < date2:
        print ('Tag 1 ist älter als Tag 2.')
    elif date1 > date2:
        print ('Tag 1 ist jünger als Tag 2.')
    else:
        print ('Same')
Justifiez
User
Beiträge: 13
Registriert: Montag 26. Mai 2014, 19:48

Ok. Danke! :)
Antworten