Подсчет числа дней недели между двумя датами

Рассмотрим следующий список пар « день недели недели» в формате 24H :

 { 'Mon': [9,23], 'Thu': [12, 13, 14], 'Tue': [11, 12, 14], 'Wed': [11, 12, 13, 14] 'Fri': [13], 'Sat': [], 'Sun': [], } 

и два временных момента, например:

  • Начало:

     datetime.datetime(2015, 7, 22, 17, 58, 54, 746784) 
  • Конец :

     datetime.datetime(2015, 8, 30, 10, 22, 36, 363912) 

Скажем, нам нужно знать, сколько часов между этими двумя датами (округление вверх или вниз) для каждой из пар дней недели недели, указанных выше.

Как я могу подойти к этой проблеме в Python? Я исследовал timedelta и relativedelta в общем уровне детализации, но я не нашел ничего, что обеспечило бы что-то близкое к этому.

Для простоты можно предположить, что все относится к одному и тому же часовому поясу.


Возможно, более простая проблема заключается в том, чтобы сосредоточиться на одной дневной паре, например, сколько Wednesdays: 14 между двумя произвольными датами?

5 Solutions collect form web for “Подсчет числа дней недели между двумя датами”

Возможно, что-то вроде этого:

 from calendar import day_abbr from datetime import datetime, timedelta def solve(start, end, data): days = list(day_abbr) output = dict.fromkeys(days, 0) while start <= end: day = days[start.weekday()] if start.hour in data[day]: output[day] += 1 start = start + timedelta(minutes=60) return output data = { 'Mon': [9, 23], 'Thu': [12, 13, 14], 'Tue': [11, 12, 14], 'Wed': [11, 12, 13, 14], 'Fri': [13], 'Sat': [], 'Sun': [], } start = datetime(2015, 7, 22, 17, 58, 54, 746784) end = datetime(2015, 8, 30, 10, 22, 36, 363912) print solve(start, end, data) # {'Wed': 20, 'Sun': 0, 'Fri': 6, 'Tue': 15, 'Mon': 10, 'Thu': 18, 'Sat': 0} 

Получение счета за каждый день за часом:

 from calendar import day_abbr from collections import defaultdict from datetime import datetime, timedelta from pprint import pprint def solve(start, end, data): days = list(day_abbr) output = defaultdict(lambda: defaultdict(int)) while start <= end: day = days[start.weekday()] if start.hour in data[day]: output[day][start.hour] += 1 start = start + timedelta(minutes=60) return {k: dict(v) for k, v in output.items()} data = { 'Mon': [9, 23], 'Thu': [12, 13, 14], 'Tue': [11, 12, 14], 'Wed': [11, 12, 13, 14], 'Fri': [13], 'Sat': [], 'Sun': [], } start = datetime(2015, 7, 22, 17, 58, 54, 746784) end = datetime(2015, 8, 30, 10, 22, 36, 363912) pprint(solve(start, end, data)) # output {'Fri': {13: 6}, 'Mon': {9: 5, 23: 5}, 'Thu': {12: 6, 13: 6, 14: 6}, 'Tue': {11: 5, 12: 5, 14: 5}, 'Wed': {11: 5, 12: 5, 13: 5, 14: 5}} 

Возможно, я не полностью понимаю вашу проблему, но вы можете получить все часы между двумя датами и суммировать, сколько раз каждый час и день появляется между двумя датами:

 from datetime import datetime from dateutil import rrule,parser d={ 'Mon': [9, 23], 'Thu': [12, 13, 14], 'Tue': [11, 12, 14], 'Wed': [11, 12, 13, 14], 'Fri': [13], 'Sat': [], 'Sun': [], } st = datetime(2015, 7, 22, 17, 58, 54, 746784) ed = datetime(2015, 8, 30, 10, 22, 36, 363912) dates = list(rrule.rrule(rrule.HOURLY, dtstart=parser.parse(st.strftime("%Y-%m-%d %H:%M:%S")), until=parser.parse(ed.strftime("%Y-%m-%d %H:%M:%S")))) days = {"Mon":0,"Tue": 1,"Wed":2,"Thu": 3,"Fri":4,"Sat":5,"Sun":6} for k, val in d.items(): for v in val: print("day: {} hour: {}".format(k,v)) day = days[k] print(sum((v == dt.hour and dt.weekday() == day) for dt in dates)) 

Вывод:

 day: Wed hour: 11 5 day: Wed hour: 12 5 day: Wed hour: 13 5 day: Wed hour: 14 5 day: Fri hour: 13 6 day: Tue hour: 11 5 day: Tue hour: 12 5 day: Tue hour: 14 5 day: Mon hour: 9 6 day: Mon hour: 23 5 day: Thu hour: 12 5 day: Thu hour: 13 5 day: Thu hour: 14 5 

Не уверен, хотите ли вы получить сумму за все часы в каждом списке или общую сумму за каждый отдельный час, но в любом случае вы можете сохранить вывод в dict.

 counts = {'Thu':{}, 'Sun':{}, 'Fri':{}, 'Mon':{}, 'Tue':{}, 'Sat':{}, 'Wed':{}} for k, val in d.items(): for v in val: day = days[k] sm = sum((v == dt.hour and dt.weekday() == day) for dt in dates) counts[k][v] = sm from pprint import pprint as pp pp(counts) 

Вывод:

 {'Fri': {13: 6}, 'Mon': {9: 5, 23: 5}, 'Sat': {}, 'Sun': {}, 'Thu': {12: 6, 13: 6, 14: 6}, 'Tue': {11: 5, 12: 5, 14: 5}, 'Wed': {11: 5, 12: 5, 13: 5, 14: 5}} 

Вот решение с циклами и datetime :

 import datetime pairs = {1: [9,23], 2: [11, 12, 14], 3: [11, 12, 13, 14], 4: [12, 13, 14], 5: [13], 6: [], 7: [] } start = datetime.datetime(2015, 7, 22, 17, 58, 54, 746784) end = datetime.datetime(2015, 8, 30, 10, 22, 36, 363912) result={} for d,hl in pairs.items(): for h in hl: result[(d,h)] = 0 for diff in range((end-start).days*24): comp = start + datetime.timedelta(hours=diff) if comp.isoweekday() == d and comp.hour == h: result[(d,h)] += 1 

 >>> result {(3, 12): 5, (5, 13): 6, (3, 13): 5, (1, 23): 5, (2, 11): 5, (3, 11): 5, (4, 14): 6, (4, 13): 6, (4, 12): 6, (2, 12): 5, (2, 14): 5, (3, 14): 5, (1, 9): 5} 

Я также попробую для решения с timestamp() и % .

Вот еще одно решение с арифметикой:

 import datetime pairs = {1: [9,23], 2: [11, 12, 14], 3: [11, 12, 13, 14], 4: [12, 13, 14], 5: [13], 6: [], 7: [] } start = datetime.datetime(2015, 7, 22, 17, 58, 54, 746784) end = datetime.datetime(2015, 8, 30, 10, 22, 36, 363912) result={} weeks = (end-start).days//7 for d,hl in pairs.items(): for h in hl: initial = weeks if d > start.isoweekday() or ( d == start.isoweekday() and h >= start.hour): initial += 1 result[(d,h)] = initial 

 >>> for k in sorted(result): ... print(k, result[k]) ... (1, 9) 5 (1, 23) 5 (2, 11) 5 (2, 12) 5 (2, 14) 5 (3, 11) 5 (3, 12) 5 (3, 13) 5 (3, 14) 5 (4, 12) 6 (4, 13) 6 (4, 14) 6 (5, 13) 6 

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

 #!/usr/bin/python from __future__ import print_function import datetime import dateutil.relativedelta def hours_between(start, end, weekday, hour): first = start + dateutil.relativedelta.relativedelta( weekday=weekday, hour=hour, minute=0, second=0, microsecond=0) week = dateutil.relativedelta.relativedelta(weeks=1) all_dates = [] d = first while d < end: all_dates.append(d) d += week return all_dates def main(): start = datetime.datetime(2015, 7, 22, 17, 58, 54, 746784) end = datetime.datetime(2015, 8, 30, 10, 22, 36, 363912) all_dates = hours_between(start, end, dateutil.relativedelta.WE, 14) print(all_dates) print(len(all_dates)) main() 
  • Python: Как мне получить время от объекта datetime.timedelta?
  • Добавьте 24 часа к отрицательной разнице во времени в python
  • В чем разница между «datetime.timedelta» и «dateutil.relativedelta.relativedelta» при работе только с днями?
  • рассчитать разницу между двумя датами datetime.date () в годах и месяцах
  • Есть ли простой способ конвертировать продолжительность ISO 8601 в timedelta
  • поведение python timedelta при вычитании
  • Объекты времени Python с более чем 24 часами
  • как преобразовать объект timedelta в объект datetime
  • Python - лучший язык программирования в мире.