2009-07-09 11 views

cevap

93

Sen dateutil gelen ayrıştırma işlevini kullanabilirsiniz:

>>> from dateutil.parser import parse 
>>> d = parse('2009/05/13 19:19:30 -0400') 
>>> d 
datetime.datetime(2009, 5, 13, 19, 19, 30, tzinfo=tzoffset(None, -14400)) 

Eğer o zaman kullanabileceğiniz bir datetime nesnesi elde Bu şekilde.

answered olarak, dateutil2.0, Python 3.0 için yazılmıştır ve Python 2.x ile çalışmaz. Python 2.x için dateutil1.5 kullanılmalıdır.

+1

THis Python 2.6 –

+11

üzerinde dateutil sürüm 2.0 çalışmaz Bu benim için çalışıyor ('dateutil' 2.1) Python '2.7.2' ile; Python 3 gerekli değildir. Pip'ten yüklüyorsanız paketin adı python-dateutil'dir. – BigglesZX

-8

Linux üzerinde ise, o zaman dwim harici date komutunu kullanabilirsiniz: date aynı zamanda "gibi girişleri kabul eder, çünkü

import commands, datetime 

def parsedate(text): 
    output=commands.getoutput('date -d "%s" +%%s' % text) 
    try: 
     stamp=eval(output) 
    except: 
     print output 
     raise 
    return datetime.datetime.frometimestamp(stamp) 

Bu elbette az dateutil daha taşınabilir, ama biraz daha esnektir dün "veya" geçen yıl ":-)

+3

Bunun için harici bir program çağırmanın iyi bir şey olduğunu düşünmüyorum. Ve bir sonraki zayıf nokta: eval(): Artık bir web sunucusunun bu kodu çalıştırması durumunda, sunucuda keyfi bir kod yürütme yapabilirsiniz! – guettli

+5

Her şey bağlamına bağlıdır: eğer peşinde olduğumuz şey sadece bir yazıp atma betiğiyse, o zaman bu zayıflıklar sadece anlamsızdır :-) – Gyom

+8

Aşağı oylama çünkü: 1) Bir sistem çağrısı yapar. önemsiz bir şey, 2) Dizeleri doğrudan bir kabuk çağrısına enjekte eder, 3) eval() ve 4'ü çağırır. Bu bir istisna yakalama özelliğine sahiptir. Temel olarak, bu şeylerin * nasıl yapıldığının bir örneğidir. – benjaoming

7

Dateutil'ın kullanılmasıyla ilgili sorun, dateutil'ın sınırlı biçimlendirme seçenekleri olduğundan (yalnızca dayfirst ve yearfirst), serileştirme ve serileştirme için aynı biçim dizisine sahip olamayacağınızdır.

Uygulamamda, biçim dizesini .INI dosyasında saklıyorum ve her dağıtımın kendi biçimi olabilir. Böylece, dateutil yaklaşımını beğenmiyorum.

from datetime import datetime, timedelta 

from pytz import timezone, utc 
from pytz.tzinfo import StaticTzInfo 

class OffsetTime(StaticTzInfo): 
    def __init__(self, offset): 
     """A dumb timezone based on offset such as +0530, -0600, etc. 
     """ 
     hours = int(offset[:3]) 
     minutes = int(offset[0] + offset[3:]) 
     self._utcoffset = timedelta(hours=hours, minutes=minutes) 

def load_datetime(value, format): 
    if format.endswith('%z'): 
     format = format[:-2] 
     offset = value[-5:] 
     value = value[:-5] 
     return OffsetTime(offset).localize(datetime.strptime(value, format)) 

    return datetime.strptime(value, format) 

def dump_datetime(value, format): 
    return value.strftime(format) 

value = '2009/05/13 19:19:30 -0400' 
format = '%Y/%m/%d %H:%M:%S %z' 

assert dump_datetime(load_datetime(value, format), format) == value 
assert datetime(2009, 5, 13, 23, 19, 30, tzinfo=utc) \ 
    .astimezone(timezone('US/Eastern')) == load_datetime(value, format) 
32

%z 3.2+ Python desteklenir:: eski sürümlerinde

>>> from datetime import datetime 
>>> datetime.strptime('2009/05/13 19:19:30 -0400', '%Y/%m/%d %H:%M:%S %z') 
datetime.datetime(2009, 5, 13, 19, 19, 30, 
        tzinfo=datetime.timezone(datetime.timedelta(-1, 72000))) 

:

from datetime import datetime 

date_str = '2009/05/13 19:19:30 -0400' 
naive_date_str, _, offset_str = date_str.rpartition(' ') 
naive_dt = datetime.strptime(naive_date_str, '%Y/%m/%d %H:%M:%S') 
offset = int(offset_str[-4:-2])*60 + int(offset_str[-2:]) 
if offset_str[0] == "-": 
    offset = -offset 
dt = naive_dt.replace(tzinfo=FixedOffset(offset)) 
print(repr(dt)) 
# -> datetime.datetime(2009, 5, 13, 19, 19, 30, tzinfo=FixedOffset(-240)) 
print(dt) 
# -> 2009-05-13 19:19:30-04:00 

FixedOffset bir olduğunu

İşte yerine pytz kullanan alternatif bir yöntem vardır the code example from the docs:tabanlı sınıf

datetime.strptime(t,'%Y-%m-%dT%H:%M %z') 

Kullanım timedelta saat dilimine hesaba böyle:

İşte
from datetime import timedelta, tzinfo 

class FixedOffset(tzinfo): 
    """Fixed offset in minutes: `time = utc_time + utc_offset`.""" 
    def __init__(self, offset): 
     self.__offset = timedelta(minutes=offset) 
     hours, minutes = divmod(offset, 60) 
     #NOTE: the last part is to remind about deprecated POSIX GMT+h timezones 
     # that have the opposite sign in the name; 
     # the corresponding numeric value is not used e.g., no minutes 
     self.__name = '<%+03d%02d>%+d' % (hours, minutes, -hours) 
    def utcoffset(self, dt=None): 
     return self.__offset 
    def tzname(self, dt=None): 
     return self.__name 
    def dst(self, dt=None): 
     return timedelta(0) 
    def __repr__(self): 
     return 'FixedOffset(%d)' % (self.utcoffset().total_seconds()/60) 
+0

Bu, bir 'ValueError: 'z' durumda benim durumumda '% Y-% m-% d% M:% H:% S.% f% z' biçiminde hatalı bir direktiftir (Python 2.7). – Sheljohn

+0

@ Sheljohn Python 2.7 üzerinde çalışmaması gerekiyor. Cevabın en tepesine bakın. – jfs

+0

garip, bu arada, Python'da bahsedilen TÜMÜNÜ DEĞİLDİR * 2.7 * docs: https://docs.python.org/2.7/library/datetime.html?highlight=datetime#strftime-strptime-behavior – 62mkv

12
Python 2.7 için "%z" sorunun bir düzeltme ve kullanmak yerine daha erken

olduğunu

from datetime import datetime,timedelta 
def dt_parse(t): 
    ret = datetime.strptime(t[0:16],'%Y-%m-%dT%H:%M') 
    if t[18]=='+': 
     ret-=timedelta(hours=int(t[19:22]),minutes=int(t[23:])) 
    elif t[18]=='-': 
     ret+=timedelta(hours=int(t[19:22]),minutes=int(t[23:])) 
    return ret 

Tarihlerin GMT, WHI'ye dönüştürüleceğini unutmayın. ch, saat dilimleri hakkında endişelenmeden tarih aritmetiği yapmanıza izin verir.

+0

I Bunun gibi, 'seconds =' ile 'minutes =' arasında değiştirmeniz gerekiyor. – Dave

+0

teşekkürler @Dave, GMT'ye dönüştüren –

+1

'u düzeltmiş olursunuz ... eğer gerçekten istediğin buysa ... –

0

Eski Pythonlar için bir astar var.Bunu aşağıdaki gibi, +/- işareti bağlı olarak 1/-1 ile bir timedelta çarpabilirsiniz:

datetime.strptime(s[:19], '%Y-%m-%dT%H:%M:%S') + timedelta(hours=int(s[20:22]), minutes=int(s[23:])) * (-1 if s[19] == '+' else 1)