Python timedelta проблема с отрицательными значениями - PullRequest
26 голосов
/ 07 декабря 2011

Привет, мне нужна помощь, чтобы понять, почему это происходит. У меня есть метод для отслеживания «оставшегося времени» в программе события:

def get_program_time_budget(self):
    return self.estimated_duration-self.get_program_duration() 

Все хорошо, когдаtimate_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 

Ответы [ 2 ]

40 голосов
/ 07 декабря 2011

Если вы используете 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, а для отрицательных timedelt будет предшествовать '-' положительной timedelta.

13 голосов
/ 07 декабря 2011

Почему?

Возможно, в качестве непреднамеренного побочного эффекта способа // и %.

Возможно, потому что это облегчает реализацию класса 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'
...