Warum ist strftime auf > 1899 beschränkt?

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
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

die Doku sagt
strftime() hat geschrieben:The exact range of years for which strftime() works also varies across platforms. Regardless of platform, years before 1900 cannot be used.
Warum ist das so und handle ich mir damit

Code: Alles auswählen

def strftime_(datetime_obj):
    if hasattr(datetime_obj, 'hour'):
        template = ('{d.year:=04}{d.month:=02}{d.day:=02}'
                    '{d.hour:=02}{d.minute:=02}')
    else:
        template = '{d.year:=04}{d.month:=02}{d.day:=02}'
    return template.format(d=datetime_obj)
irgendwelche Probleme ein?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Das ist seit langem so definiert für das time struct in C, dort bedeutet tm_year Jahre seit 1900. Da viele der time.h Funktionen mit dem Timestamp rechnen (Sekunden seit 1970), war unter 32bit dieses Zeitfenster sinnvoll (siehe Jahr 2038 Bug). In wie weit die Grenzen z.T. hardkodiert in den Funktionen genutzt werden - kA., so auf die Schnelle getestet, scheint strftime der glibc auf 64bit auch für ältere Daten richtig zu rechnen (ohne Gewähr):

Code: Alles auswählen

import datetime, time
from ctypes import Structure, c_int, CDLL, create_string_buffer, byref

CLIB = CDLL('libc.so.6')

# time struct                               c     python
# tm_sec  int     seconds after the minute  0-61  
# tm_min  int     minutes after the hour    0-59  
# tm_hour int     hours since midnight      0-23  
# tm_mday int     day of the month          1-31
# tm_mon  int     months since January      0-11  1-12
# tm_year int     years since 1900                absolute (x-1900)
# tm_wday int     days since Sunday         0-6   0-6 from Monday
# tm_yday int     days since January 1      0-365 day in year
# tm_isdst int    Daylight Saving Time flag

class Time(Structure):
    _fields_ = [
        ('tm_sec',   c_int),
        ('tm_min',   c_int),
        ('tm_hour',  c_int),
        ('tm_mday',  c_int),
        ('tm_mon',   c_int),
        ('tm_year',  c_int),
        ('tm_wday',  c_int),
        ('tm_yday',  c_int),
        ('tm_isdst', c_int)]
    def __init__(self, t):
        self.tm_year = t.tm_year - 1900
        self.tm_mon = t.tm_mon - 1
        self.tm_yday = t.tm_yday - 1
        self.tm_wday = (t.tm_wday + 1) % 7
        for attr in ['tm_sec', 'tm_min', 'tm_hour', 'tm_mday', 'tm_isdst']:
            setattr(self, attr, getattr(t, attr))

def my_strftime(t, fmt_str):
    out_len = len(fmt_str) + 100 # magic number for room of entry output
    c_string = create_string_buffer(out_len)
    fmt = create_string_buffer(fmt_str)
    ts = Time(t)
    CLIB.strftime(c_string, out_len, fmt, byref(ts))
    return c_string.value

if __name__ == '__main__':
    date = datetime.datetime.now()
    print my_strftime(date.timetuple(), '%c %D %U %j %e')
    print date.strftime('%c %D %U %j %e')
    bastille = datetime.datetime(year=1789,month=7, day=14, hour=5, minute=45)
    print my_strftime(bastille.timetuple(), '%c %D %U %j %e')
Der Sturm war angeblich ein einem Dienstag ;)


Was Python angeht --> http://bugs.python.org/issue1777412
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@jerch
Danke für die Infos und auch den Link... Ab Python 3.2 wurde die Beschränkung auf >= 1000 gesetzt ab Python 3.3 ganz aufgehoben... Grund genug, an meinem kleinen Workaround festzuhalten...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten