Seite 1 von 1

Wieder mal die Frage: "Geht's besser?"

Verfasst: Dienstag 28. August 2012, 16:55
von mutetella
Hallo,

nachfolgender Code generiert datetime-objecte. Hier ein paar Beispiele:

Code: Alles auswählen

In [263]: parse.generate_date('2012.9.16')
Out[263]: datetime.datetime(2012, 9, 16, 0, 0)

In [264]: parse.generate_date('10-3')
Out[264]: datetime.datetime(2012, 10, 3, 0, 0)

In [265]: parse.generate_date('30')
Out[265]: datetime.datetime(2012, 8, 30, 0, 0)

Code: Alles auswählen

import re
import datetime

FORMAT = 'ymd'
CHANGE_SHORT_YEAR = True

def generate_date(date_args, formatstring=None):
    '''generate_date(date_args[, formatdate_args]) -> datetime-object
    
    Extract potential date digits from 'date_args' and return
    a valid datetime-object or raise a ValueError.

    'date_args' must be a date_args with 1, 2 or 3 digit(s) seperated
    by any char. These digit(s) represents year, month and day 
    in order of the given 'formatdate_args' or by 'parse.FORMAT' 
    by default.

    If one or more digit(s) are not given it will be replaced
    with the equivalent of the current day.
    Note that 2 digits are always interpreted as day with month,
    1 digit always as day.

    'formatdate_args' specified the order in which the date digits
    are contained in 'date_args'.

    If 'parse.CHANGE_SHORT_YEAR' is True, a year-number larger
    then 100 will be interpreted as a 21 century year, e. g. 
    the year 13 will be returned as year 2013.'''

    if formatstring is None:
        formatstring = FORMAT
    date_args = re.findall('\d+', date_args)
    arg_count = len(date_args)
    year, month, day = datetime.datetime.now().timetuple()[0:3]
    if arg_count == 3:
        # positions of year, month, date
        y_idx, m_idx, d_idx = formatcode_positions(formatstring, 'ymd')
        year = int(date_args[y_idx])
        if CHANGE_SHORT_YEAR and year < 100:
            year += 2000
        month = int(date_args[m_idx])
        day = int(date_args[d_idx])
    elif arg_count == 2:
        # positions of month and date if no year is given
        m_idx, d_idx = formatcode_positions(formatstring, 'md')
        month = int(date_args[m_idx])
        day = int(date_args[d_idx])
    else:
        day = int(date_args[0])
    try:
        return datetime.datetime(year, month, day)
    except ValueError:
        raise ValueError('{0}(y), {1}(m), {2}(d) seems not to be '
                         'a valid date.'.format(year, month, day))
        

def formatcode_positions(formatstring, formatcodes):
    formatcodes = formatcodes.upper()
    _ = [f.upper() for f in re.findall('[{0}]'.format(formatcodes),
                                       formatstring, re.I)]
    return [_.index(code) for code in formatcodes]

Was mich allerdings nicht so ganz glücklich macht ist diese 'arg_count'-Sache. Ich stelle mir da eher sowas wie ein template vor, das mit default-Werten gefüllt ist und je nach übergebenen year-, month- und day-Werten bestückt wird.
Die Hürde, über die ich nicht komme ist die veränderliche Reihenfolge der Werte.

Wäre für jegliche Inspiration sehr dankbar!

mutetella

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Dienstag 28. August 2012, 17:14
von deets
Reaktion der ersten Sekund: _ verwendet man fuer Bezeichner, die man *nicht* benoetigt. Das solltest du also aendern.

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Dienstag 28. August 2012, 21:50
von mutetella
@deets:
Ich verwende den _ immer gern für so Sachen, für die es sich nicht lohnt, einen vernünftigen Namen zu finden... Manchmal kommt es mir so vor, als würde mich die Suche nach gescheiten Namen mehr Zeit als der Code selbst kosten... :(

Was meinst Du mit "nicht benötigt"? Ist nicht das so ein Fall? Ein Bezeichner für eine Liste, die man ja eigentlich nicht benötigt. Oder wieviel mehr kann man etwas nicht benötigen (ernst gemeinte Frage!)?

mutetella

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Dienstag 28. August 2012, 22:11
von EyDu
mutetella hat geschrieben:Ich verwende den _ immer gern für so Sachen, für die es sich nicht lohnt, einen vernünftigen Namen zu finden... Manchmal kommt es mir so vor, als würde mich die Suche nach gescheiten Namen mehr Zeit als der Code selbst kosten... :(
Wenn du Dingen keinen vernünftigen Namen geben kannst, dann ist das häufig ein Hinweis auf einen Fehler. Das kann alle möglichen Gründe haben, wie ein nicht durchdachtes Konzept, ein unnötiger Schritt oder auch zu viele Schritte auf einmal.
mutetella hat geschrieben:Was meinst Du mit "nicht benötigt"? Ist nicht das so ein Fall? Ein Bezeichner für eine Liste, die man ja eigentlich nicht benötigt. Oder wieviel mehr kann man etwas nicht benötigen (ernst gemeinte Frage!)?
Nicht benötigt bedeutet, dass der Wert danach nicht mehr verwendet wird. Sonst sollte das Objekt immer einen richtigen Namen bekommen. Alles, was du in Python an den Bezeichner _ bindest, kann quasi vergessen werden oder beliebigen Unsinn annehmen. Normalerweise, wenn man beim Unpacking etwas nicht braucht:

Code: Alles auswählen

_, x, _ = 1, 2, 3

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Mittwoch 29. August 2012, 16:32
von mutetella
Ok, hab' den underscore eliminiert...

Nochmal zu meinem eigentlichen Anliegen :wink: :

Ich grübel schon 'ne Weile darüber nach, wie man den Teil

Code: Alles auswählen

    ...
    if arg_count == 3:
        # positions of year, month, date
        ...
    elif arg_count == 2:
        # positions of month and date if no year is given
        ...
    else:
        ...
ohne diese ganze ifferei eleganter lösen könnte. Wenn 'zip()' auch unterschiedlich lange Listen verarbeiten könnte (mit einem default-Wert oder so), könnte das vielleicht 'ne Lösung sein. In etwa so:

Code: Alles auswählen

date_format = 'ymd'
date_proposal = (2012, 8, 29)
date_args = (9, 16)
fill_with_defaults(date_proposal, date_args, 2012)
Allerdings hört meine Fantasie bei der Frage auf, wie 'fill_with_defaults()' fehlende Werte an die richtige Position bringen soll. Wäre die Reihenfolge immer y, m, d wäre es kaum ein Problem...

Oder was mit defaultdict...?

Oder ist die 'arg_count'-Lösung ok?

Hab' mich da jetzt voll reingeschraubt... kann mir jemand helfen... :(

mutetella

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Mittwoch 29. August 2012, 17:14
von deets
Du hast dich geschraubt. Und wenn wuerde ich deinem code eine Heuristik spendieren, wie er M/D von D.M unterscheiden kann. Bzw. eine Option, und uU eine Heuristik, wenn man viele Werte aus derselben Quelle bekommt und irgendwann durch den Wertebereich erfaehrt, was was ist.

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Mittwoch 29. August 2012, 20:10
von lunar
@mutetella Täusche ich mich, oder suchst Du einfach dateutil.parser?

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Mittwoch 29. August 2012, 21:59
von mutetella
@lunar:
Mach' die Augen zu und stelle Dir vor wie ich mich in den Staub werfe und Dir die Füße küsse...

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Mittwoch 29. August 2012, 23:33
von deets
Ich muss dieses Bild jetzt leider auch aus meinem Kopf kriegen... :shock:

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Donnerstag 30. August 2012, 07:04
von mutetella
Ich hab' mir die 'parser.py' aus dem dateutil-Modul mal ein ganz klein wenig angeschaut und bin jetzt auch mit meiner 'arg_count'-Lösung (auch wenn ich sie jetzt nicht mehr brauche) versöhnt. Letztlich arbeitet 'parser.py' den zu parsenden date-string ähnlich durch, wenngleich auch auf höherem Niveau... :)

Und die Schreibweise kannte ich auch noch nicht:

Code: Alles auswählen

        ...
    elif len_li == 8:
        ...
    elif len_li in (12, 14):
        ...
Über solche Kleinigkeiten kann ich mich richtig freuen... :mrgreen:

Nochmals vielen Dank an lunar für den Tipp. Neben dem datutil-parser werd' ich auch 'relativedelta()' sehr intensiv nutzen. Schade nur, dass meine eigenen Lösungen in dieser Richtung nun für's Archiv sind... ;-)

mutetella

@deets
Ich hoffe doch sehr, Du hattest keine allzu heftigen Albträume...

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Donnerstag 30. August 2012, 08:39
von lunar
@mutetella Möchtest Du wirklich, dass ich mir das vorstelle? ;)

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Donnerstag 30. August 2012, 19:37
von Hyperion
Wer denkt dabei nicht an Julius Cäsar? ;-)

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Donnerstag 30. August 2012, 21:09
von mutetella
@Hyperion
Ich denke da eher an Pilatus, der rief: "Chleudert den Purchen zu Poden!"

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Donnerstag 30. August 2012, 21:15
von Hyperion
mutetella hat geschrieben:@Hyperion
Ich denke da eher an Pilatus, der rief: "Chleudert den Purchen zu Poden!"
:mrgreen: Das war aber nicht der echte! ;-)

Kennt denn niemand die Anekdote von Cäsar, als er zu Beginn des Afrikanischen Krieges bei seiner Landung stolperte und in den Sand fiel? Tse tse ste...

Re: Wieder mal die Frage: "Geht's besser?"

Verfasst: Freitag 31. August 2012, 11:21
von Dav1d
mutetella hat geschrieben:ohne diese ganze ifferei eleganter lösen könnte. Wenn 'zip()' auch unterschiedlich lange Listen verarbeiten könnte (mit einem default-Wert oder so), könnte das vielleicht 'ne Lösung sein.
itertools.izip_longest?