2015-07-30 2 views
4

Я искал ответ stackoverflow для ответа, но я не смог найти то, что искал в Python и в Pythonic.Python получить дни/недели/месяцы вперед

Я пытаюсь получить количество дней, недель или месяцев вперед в зависимости от двух дат. Вот небольшой скрипт, который я создал, который делает то, что я хочу сделать, но меня это беспокоит.

import datetime 
from dateutil.relativedelta import relativedelta 


now = datetime.datetime.now() 
days_ahead = datetime.datetime.now() + relativedelta(days=3) 
weeks_ahead = datetime.datetime.now() + relativedelta(weeks=2) 
month_ahead = datetime.datetime.now() + relativedelta(months=1) 
months_ahead = datetime.datetime.now() + relativedelta(months=3) 


def get_relative_date(dt): 

    ahead = (dt - now).days 

    if ahead < 7: 
     return "Due in " + str(ahead) + " days" 

    elif ahead < 31: 
     return "Due in " + str(ahead/7) + " weeks" 

    else: 
     return "Due in " + str(ahead/30) + " months" 

print get_relative_date(days_ahead) 
print get_relative_date(weeks_ahead) 
print get_relative_date(month_ahead) 
print get_relative_date(months_ahead) 

В результате получается следующее:

Due in 3 days 
Due in 2 weeks 
Due in 1 months 
Due in 3 months 

Несмотря на хороший ответ мои проблемы связаны с:

  • Я использую ahead < 30 но как насчет месяцев 31 день? Разве это не вызовет какие-то накладные расходы и не даст ошибок в какой-то момент?
  • Есть ли лучший способ получить эту информацию? Какая-то библиотека или встроенная функция для datetime или dateutil, которая возвращает вам эту информацию?

Заранее спасибо. Если бы на вопрос ответили, напишите мне сообщение, и я внимательно прочитаю его. Я желаю предоставить дополнительную информацию, если потребуется.

Редактировать

Я включил здесь мой полный обновленный код для тех, кто требуется слишком эта функция в Python. Он также заботится о негативных значениях дня и сегодня.

def relative_date(dt): 

    if dt is not None and len(dt) > 0: 

     now = datetime.now() 
     then = arrow.get(dt).naive 

     rd = relativedelta(then, now) 
     if rd.years or rd.months: 
      months = 12 * rd.years + rd.months 

      if months < 0: 
       if months == -1: 
        return "Due 1 month ago" 

       return "Due %i months ago" % -months 

      if months == 1: 
       return "Due in 1 month" 
      return "Due in %d months" % months 

     elif rd.days > 7 or rd.days < -7: 
      weeks = rd.days/7 

      if weeks < 0: 
       if weeks == -1: 
        return "Due 1 week ago" 
       return "Due %i weeks ago" % -weeks 

      if weeks == 1: 
       return "Due in 1 week" 
      return "Due in %d weeks" % weeks 

     else: 

      if rd.days == 0: 
       return "Due Today" 

      elif rd.days < 0: 
       if rd.days == -1: 
        return "Due 1 day ago" 
       return "Due %i days ago" % -rd.days 

      elif rd.days == 1: 
       return "Due in 1 day" 

      return "Due in %d days" % rd.days 

    else: 
     return "" 

ответ

4

Да, ваш текущий код является проблемой, поскольку не все месяцы имеют 31 день. На практике вы можете решить, что это не слишком важно, если он говорит «Долг в 2 месяца», когда он на самом деле должен быть в течение 1 месяца и 28 дней. В конце концов, округление означает, что вы показываете «Долг в 2 месяца», когда он должен быть через 2 месяца и 28 дней.

Поскольку вы используете модуль dateutil уже, обратите внимание, что вы также можете использовать relativedelta (см. the examples page).

Если экземпляр relativedelta с двумя объектами даты, она возвращает relativedelta объект с year, month и day атрибутов.

>>> relativedelta(date(2015, 7, 20), date(2014, 6, 10)) 
relativedelta(years=+1, months=+1, days=+10) 

Вы можете использовать это в вашем методе следующим образом:

from dateutil.relativedelta import relativedelta 

def get_relative_date(dt): 

    rd = relativedelta(dt, now) 
    if rd.years or rd.months: 
     months = 12 * rd.years + rd.months: 
     return "Due in %d months" % months 
    elif rd.days > 7: 
     weeks = rd.days/7 
     return "Due in %d weeks" % weeks 
    else: 
     return "Due in %d days" % rd.days 
+0

Удивительная не знал об этом. Большое спасибо. –

Смежные вопросы