От: "1 час назад", до: timedelta + точность
Есть ли функция для "обратной гуманизации" времен?
Например, задано (строки):
- "1 минуту назад"
- '7 часов назад'
- '5 дней назад'
- '2 месяца назад'
Может вернуться (извините за псевдокод):
- datetime.now () - timedelta (1 минута), точность (60 секунд)
- datetime.now () - timedelta (7 часов), точность (1 час)
- datetime.now () - timedelta (5 дней), точность (1 день)
- datetime.now () - timedelta (2 месяца), точность (1 месяц)
2 ответа
Вы не можете просто написать простую реализацию, такую как:
import datetime
def parsedatetime(str_val):
parts = str_val.split(' ')
if len(parts) != 3 and parts[2] != 'ago':
raise Exception("can't parse %s" % str_val)
try:
interval = int(parts[0])
except ValueError,e :
raise Exception("can't parse %s" % str_val)
desc = parts[1]
if 'second' in desc:
td = datetime.timedelta(seconds=interval)
elif 'minute' in desc:
td = datetime.timedelta(minutes=interval)
elif 'hour' in desc:
td = datetime.timedelta(minutes=interval*60)
elif 'day' in desc:
td = datetime.timedelta(days=interval)
else:
raise Exception("cant parse %s" % str_val)
answer = datetime.datetime.now - td
return answer
Входные данные не выглядят такими разнообразными.
Я использовал parsedatetime, и он работал довольно хорошо для меня. На домашней странице перечислены некоторые форматы, которые он может обрабатывать, например:
- через 5 минут
- Через 5 минут
- За 2 часа до полудня
- 2 дня с завтрашнего дня
Основным недостатком, который я обнаружил, является отсутствие часовых поясов.
Если это чего-то стоит, вот функция-обертка, которую я использую, которая всегда возвращает datetime
объект независимо от того, является ли входная строка относительной (как все ваши примеры) или фиксированной:
def parse_datetime(datetime_string):
datetime_parser = parsedatetime.Calendar(parsedatetime_consts.Constants())
timestamp = datetime_parser.parse(datetime_string)
if len(timestamp) == 2:
if timestamp[1] == 0:
raise ValueError(u'Failed to parse datetime: %s' % datetime_string)
timestamp = timestamp[0]
return datetime.fromtimestamp(time.mktime(timestamp))