LINUX.ORG.RU

[python] Разбор даты

 


0

0

Так получилось, что до сего момента мне счастливилось всегда работать с временем как с секундами по Гринвичу и форматировать только их при выводе пользователю. Но тут возникла задача разбора дат такого вида:

Sun, 24 May 2009 18:44:49 +0400

Преобразовать надо в секунды по Гринвичу, естественно. Мне кажется что этот мой код - говно, хотя должен быть железобетонным, т.к даты получаются из очень хрупкого источника. Поэтому желательно получить как можно больше багов и советов по стилю. BTW, я в питоньих либах не особо шарю.

time_format = '%a, %d %b %Y %H:%M:%S'
    
time_format_without_century = '%a, %d %b %y %H:%M:%S'

tzsplit_pattern = re.compile(r'(?P<time>[^\s,]{3}\,?\s+\d{1,2}\s+'\
                              '[^\s]{3}\s+(?P<year>\d{2}|\d{4})\s+'\
                              '\d{1,2}\:\d{2}:\d{2})\s+'\
                              '(?P<tz>[+-]\d{2,6})')

def parse_date(self, arg):
  ## XXX: Fragile as shit
  m = self.tzsplit_pattern.match(arg)
  if m:
    time_str = m.group('time')
    tz_str = m.group('tz')
    with_century = len(m.group('year')) == 4
    time_struct = None
    if with_century:
      time_struct = time.strptime(time_str, self.time_format)
    else:
      time_struct = time.strptime(time_str, self.time_format_without_century)
    offset_direction = tz_str[:1]
    offset_hours = int(tz_str[1:3])
    offset_mins = 0
    offset_secs = 0
    if len(tz_str) > 3:
      offset_mins = int(tz_str[3:5])
    if len(tz_str) > 5:
      offset_secs = int(tz_str[5:7])
    offset = offset_hours * 3600 + offset_mins * 60 + offset_secs
    if offset_direction == '-':
      offset = -offset
    time0 = time.mktime((time_struct.tm_year, \
                         time_struct.tm_mon, \
                         time_struct.tm_mday, \
                         time_struct.tm_hour, \
                         time_struct.tm_min, \
                         time_struct.tm_sec, \
                         0, 0, 0)) - time.timezone + offset
    return time0
else:
  raise CantParseTimeException

★★★
Ответ на: комментарий от dimon555

>функция time.strptime должна помочь

Я ее тут и использую но, насколько я помнимаю, она не понимает таймзоны и поэтому таймзону я тут разбираю отдельно и плюсую к результату. Отдельный фуцк в том что mktime возвращает в локальном времени а не в GMT - был долгий кариес пока не наткнулся на это маленькое примечание.

Absurd ★★★
() автор топика

(a,d,b,y,hms,z) = 'Sun, 24 May 2009 18:44:49 +0400'.split()
(h,m,s) = hms.split(':')
t = map(lambda x: int(x), [y,d,h,m,s])
красивый_способ May->число
и т.д.

p.s. гавнокод, но довольно короткий

dimon555 ★★★★★
()
Ответ на: комментарий от dimon555

>гавнокод, но довольно короткий

Мне нужен был не элегантный, а железобетонный вариант. В описании модуля email.utils авторы утверждают что parsedate_tz обложена достаточным количеством костылей для разбора неправильно сформированных дат, так что пока использую ее.

Absurd ★★★
() автор топика
Ответ на: комментарий от dimon555

А еще лучше так

t = map(lambda x: (lambda x: int(x))(x), [y,d,h,m,s])

или даже так

t = map(lambda x:(* тут стопицот раз (lambda x:*) (lambda x: int(x))(* тут стопицот раз (x))*)(x), [y,d,h,m,s])

Jeka
()

Еще есть замечательный сторонний dateutil

>>> from dateutil import parser
>>> from time import mktime
>>> date = parser.parse('Sun, 24 May 2009 18:44:49 +0400')
>>> time = mktime(date.timetuple())
>>> time
1243169089.0
>>> date
datetime.datetime(2009, 5, 24, 18, 44, 49, tzinfo=tzoffset(None, 14400))
>>>

nnkd
()
Ответ на: комментарий от dccp

>> t = map(lambda x: int(x), [y,d,h,m,s])

> Откуда же вы такие пораженные лямбдой мозга беретесь-то?

> t = map(int, my_list)

Спасибо за напоминание.

AlexKiriukha ★★★★
()

вроде, что-то такое было в mxdatetime (подмодуль arpa афаик)

val-amart ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.