2013-12-12 14 views
0

im, используя следующее, которое отлично работает для преобразования строки UTC в дату, за исключением случаев, когда миллисекунды ДОЛЖНЫ, чем 6 цифр. чем он дует. Urgh * &^* &python strptime от строки UTC до datetime regex re.sub

format = '%Y-%m-%dT%H:%M:%S' 
if '.' in value: 
    format = format + '.%f' 
if value.endswith('Z'): 
    format = format + 'Z'   
return datetime.strptime(value, format) 

здесь является StackTrace

File "/usr/lib64/python2.6/_strptime.py", line 325, in _strptime 
    (data_string, format)) 
ValueError: time data '2013-07-19T13:02:53.8241899Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ' 

Что метод, чтобы ограничить миллисекунды до 6 цифр в длину. ive используется с использованием '{:%Y-%m-%dT%H:%M:%S.6%f}'.format( datetime), но это помогает исключить десятичные знаки (если они есть) в соответствии с символом «.'character в предоставленной строке». но я не очень хорошо разбираюсь в регулярном выражении.

im использование python 2.6. * На машине.

+0

ли вам действительно нужно имеют 6 цифр милисекунд? : O – aIKid

+0

Этот фрагмент примера может быть лучше, если сам код содержит значения для 'sz' и' value'. –

+1

для создания правильной строки, вы можете использовать 'datetime.utcnow(). Isoformat() + 'Z''. Похоже, что ['rfc3339'] (http://tools.ietf.org/search/rfc3339#section-5.6) не ограничивает число цифр после десятичной точки. Поэтому, если строка ввода заканчивается на 'Z', тогда это действительная дата rfc3339 в вашем случае. – jfs

ответ

1

Вы можете использовать .partition() метод для разбора строки:

from datetime import datetime 

sz = '2013-07-19T13:02:53.8241899Z' # utc time in rfc3339 format (without offset) 

sz = sz.rstrip('Z') # remove ending 'Z' if present 
timestr, _, digits = sz.partition('.') 
utc_dt = datetime.strptime(timestr, '%Y-%m-%dT%H:%M:%S') 
if digits: 
    microseconds = int(digits, 10) * 10**(6 - len(digits)) 
    utc_dt = utc_dt.replace(microsecond=int(microseconds + .5)) 

Если вы хотите использовать re.sub и не против усечения микросекунд:

import re 
from datetime import datetime 

sz = '2013-07-19T13:02:53.8241899Z' 
if '.' in sz: 
    sz = re.sub(r'(\.\d{,6})\d*Z?$', r'\1Z', sz) # truncate to 6 digits +Z 
else: # no fractions 
    sz = sz.rstrip('Z') + '.0Z' 

utc_dt = datetime.strptime(sz, '%Y-%m-%dT%H:%M:%S.%fZ') 
+0

thnx. плохой ваш выстрел, если метод re.sub окажется слишком медленным. С уважением. –

+0

@GabeRainbow: Я добавил код 're.sub'. – jfs

+0

праведный jf себастьян. очень хорошо –

3

Звучит как работа для dateutil.

$ pip install python-dateutil 
$ python 
>>> import dateutil.parser 
>>> d = dateutil.parser.parse('2013-07-19T13:02:53.8241899Z') 
>>> print d 
2013-07-19 13:02:53.824189+00:00 
+1

'dateutil' усекает микросекунды вместо округления их. Во всяком случае, это излишне использовать его для формата rfc3339, который заканчивается на 'Z'. [Simple '.partition ('.')' Будет работать] (http://stackoverflow.com/a/20534752/4279) – jfs

+0

thnx. Усекать нормально. может дать ему шанс в долгосрочной перспективе. С уважением. –

1

Если вы хотите сделать это с re.sub, вот краткий пример одного из способов сделать это.

import re 
from datetime import datetime 

value = '2013-07-19T13:02:53.8241899Z' 

regex = r"(\d{6,}\d+)" 

if re.search(regex, value): 
    repl = lambda x: x.group(0)[:6] 
    value = re.sub(pattern=regex, repl=repl, string=value) 

format = '%Y-%m-%dT%H:%M:%S' 
if '.' in value: 
    format = format + '.%f' 
if value.endswith('Z'): 
    format = format + 'Z'   
print datetime.strptime(value, format) 
Смежные вопросы