Проблема Python timedelta с отрицательными значениями
Привет. Мне нужна помощь, чтобы понять, почему это происходит.
У меня есть метод отслеживания "оставшегося времени" в программе событий:
def get_program_time_budget(self):
return self.estimated_duration-self.get_program_duration()
Все отлично, когда expect_duration > self.get_program_duration(), но когда это происходит, все становится забавным.
Результаты отображаются пользователю:
Estimated 11 hours Allocated 10 hours 55 minutes Remaining 5 minutes
Когда результат будет отрицательным, он делает следующее:
Estimated 11 hours Allocated 11 hours 5 minutes Remaining -1 day 23 hours 55 minutes
Любые идеи о том, как получить результат -5 минут?
EDIT:
Вот формате timedelta (обратите внимание, что это фильтр Django, поэтому получает значение timedelta как str, но оно сохраняется как timedelta):
def format_duration(value):
try:
delim = ':'
toks = value.split(',')
hour = minute = ''
d_string = value.count('day') and toks[0] or ''
h, m, s = d_string and toks[-1].strip().split(delim) or value.split(delim)
try:
hour = int(h)
except:
pass
try:
minute = int(m)
except:
pass
h_string = "%s%s%s" % (hour and hour or '', (hour and ' hour' or ''),(hour and hour > 1 and 's' or '') )
m_string = "%s%s%s" % (minute and minute or '', (minute and ' minute' or ''),(minute and minute > 1 and 's' or ''))
return "%s %s %s" % (d_string, h_string, m_string)
except Exception, e:
logging.error("Error in format_duration -> %s. Duration value=%s" % (e, value))
return ''v
Ответы
Ответ 1
Если вы используете Python 2.7 или выше, вы можете использовать timedelta.total_seconds()
, чтобы получить float
представление timedelta как положительное или отрицательное количество секунд.
>>> datetime.timedelta(-1, 86100).total_seconds()
-300.0
Вы можете использовать это, чтобы вычислить несколько минут довольно легко.
Если вы не используете Python 2.7, вы можете использовать следующую эквивалентную формулу из документов:
(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.0**6
Изменить: Похоже, вы, вероятно, используете строковое представление по умолчанию для timedelta для отображения результата, поэтому мой первоначальный ответ может быть не так полезен. Я бы предложил что-то подобное для отображения результата:
def get_program_time_budget(self):
td = self.estimated_duration-self.get_program_duration()
if td.days < 0:
return '-' + str(datetime.timedelta() - td)
return str(td)
Теперь это вернет строку вместо timedelta, а для отрицательных timedeltas она добавит '-' к положительной timedelta.
Ответ 2
Почему?
Возможно, в качестве непреднамеренного побочного эффекта пути //
и %
определены.
Возможно, потому что это упрощает реализацию класса datetime
. За пять минут до эпохи 23:55, а не 0: -5.
Это не имеет большого значения. Просто знайте, что это так, как days
, seconds
и microseconds
нормализуются. И это легко можно обойти.
def format_timedelta(td):
if td < timedelta(0):
return '-' + format_timedelta(-td)
else:
# Change this to format positive timedeltas the way you want
return str(td)
>>> format_timedelta(timedelta(minutes=-5))
'-0:05:00'