函数在 Django 中的日期范围内给出错误的一周总计
function gives wrong total of a week day between a date range in django
我已经研究这个函数好几个小时了,我似乎无法弄清楚为什么它没有给我预期的结果。我有一个生成日期时间开始和日期时间结束的测试。我想计算在该时间范围内发生了多少 'mondays' 或任何给定的一天。
def day_count(week_day, start, end):
if week_day == 1:
day = 6
else:
day = week_day - 2
num_weekdays, remainder = divmod((end - start).days, 7)
if (day - start.weekday()) % 7 <= remainder:
return num_weekdays + 1
else:
return num_weekdays
复制,这是我给它的数据:
end: 2020-08-22 00:00:00+02:00
start: 2020-08-20 22:15:55.371646+00:00
weekday: 6
我希望回馈num_weekdays = 1
但我得到 num_weekdays = 0
我不知道如何解决这个问题,num_weekdays
和 remainder
在我调试时也是 0。
我是这样调用函数的:
total_day_count = day_count(params['dt_start__week_day'], params['dt_start__gte'], params['dt_end__lte'])
这就是我获取参数的方式:
params = {}
if self.request.GET.get('day') == 'Today':
params['dt_start__week_day'] = (timezone.now().weekday() + 1) % 7 + 1
elif is_valid_queryparam(self.request.GET.get('day')):
day_of_the_week = self.request.GET.get('day')
params['dt_start__week_day'] = (int(day_of_the_week) + 1) % 7 + 1
else:
params['dt_start__week_day'] = (timezone.now().weekday() + 1) % 7 + 1
if is_valid_queryparam(self.request.GET.get('date_start')):
unaware = datetime.strptime(self.request.GET.get('date_start'), '%Y-%m-%d')
params['dt_start__gte'] = unaware.replace(tzinfo=local_tz)
else:
dt = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
first_job = Job.objects.earliest('dt_start')
params['dt_start__gte'] = first_job.dt_start
if is_valid_queryparam(self.request.GET.get('date_end')):
unaware = datetime.strptime(self.request.GET.get('date_end'), '%Y-%m-%d')
params['dt_end__lte'] = unaware.replace(tzinfo=local_tz) + timedelta(days=1)
else:
dt = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
dt_aware = local_tz.localize(dt)
params['dt_end__lte'] = dt_aware + timedelta(days=1)
我不知道这是否有帮助,但这是测试:
class MachineDurationViewTestCase(CustomAPITestCase):
"""This testcase contains tests for the API endpoint MachineDurationView """
# todo once views and some of its variables were renamed, also apply these name changes here
fake = Faker()
def setUp(self) -> None:
self.fake.seed()
super(MachineDurationViewTestCase, self).setUp()
def test_a_single_job_that_occurs_in_the_space_of_one_hour(self):
"""
In this test a single job of 30 minutes is created occuring on the first hour on the current date. This means
that we should expect the endpoint to return an array of 24 value where the first item in the array has a value
of 0.5 (Because the first hour only occurs 1 time, and job lasts 30 minutes, machine occupancy is 50%)
"""
dt = timezone.localtime()
dt_start = dt.replace(hour=0, minute=15)
dt_end = dt.replace(hour=0, minute=45)
# dt_end = timezone.datetime(d.year, d.month, d.day, hour=0, minute=45)
# dt_start = timezone.make_aware(timezone.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))
print(dt_start)
print(dt_end)
job = JobFactory(dt_start=dt_start, dt_end=dt_end)
print(job.dt_start)
# Query the dbase to ensure the job is created
self.assertEqual(Job.objects.all().count(), 1)
# Force create/login a user to access the http mocking client
# (I don't care about authentication or permissions in this test)
self.client.force_login(user=UserFactory(is_superuser=True))
response = self.client.get(reverse('data_app:machine_avg'))
self.assertEqual(response.status_code, 200)
print(response.data['machines'])
self.assertNotEqual(response.data['machines'][0], 0.0, "Since we create a job on the first hour, we expect the"
"first item of the array not to be zero.")
self.assertEqual(response.data['machines'][0], 0.5, "Since we create a single job of 30 minutes that occurs on "
"the current date, the value on the given hour should be"
"0.5 (50% occupancy)")
# job = JobFactory(dt_start=)
我认为您的输入数据有问题。这似乎对我有用:
from datetime import date
start = date(2020, 8, 20)
end = date(2020, 8, 22)
day_count(6, start, end)
这 returns 需要输出 1。我的日期类型是:<class 'datetime.date'>
计算日期范围内具体星期几的总数的函数可以通过使用日期对象的weekday()方法来实现:
from datetime import date, timedelta
def days_count(weekdays: list, start: date, end: date):
dates_diff = end-start
days = [start + timedelta(days=i) for i in range(dates_diff.days)]
return len([day for day in days if day.weekday() in weekdays])
start = date(2020, 8, 20)
end = date(2020, 8, 22)
# total of weekend days between that range (end date is excluded)
print(days_count([5, 6], start, end)) # outputs: 0
我已经研究这个函数好几个小时了,我似乎无法弄清楚为什么它没有给我预期的结果。我有一个生成日期时间开始和日期时间结束的测试。我想计算在该时间范围内发生了多少 'mondays' 或任何给定的一天。
def day_count(week_day, start, end):
if week_day == 1:
day = 6
else:
day = week_day - 2
num_weekdays, remainder = divmod((end - start).days, 7)
if (day - start.weekday()) % 7 <= remainder:
return num_weekdays + 1
else:
return num_weekdays
复制,这是我给它的数据:
end: 2020-08-22 00:00:00+02:00
start: 2020-08-20 22:15:55.371646+00:00
weekday: 6
我希望回馈num_weekdays = 1
但我得到 num_weekdays = 0
我不知道如何解决这个问题,num_weekdays
和 remainder
在我调试时也是 0。
我是这样调用函数的:
total_day_count = day_count(params['dt_start__week_day'], params['dt_start__gte'], params['dt_end__lte'])
这就是我获取参数的方式:
params = {}
if self.request.GET.get('day') == 'Today':
params['dt_start__week_day'] = (timezone.now().weekday() + 1) % 7 + 1
elif is_valid_queryparam(self.request.GET.get('day')):
day_of_the_week = self.request.GET.get('day')
params['dt_start__week_day'] = (int(day_of_the_week) + 1) % 7 + 1
else:
params['dt_start__week_day'] = (timezone.now().weekday() + 1) % 7 + 1
if is_valid_queryparam(self.request.GET.get('date_start')):
unaware = datetime.strptime(self.request.GET.get('date_start'), '%Y-%m-%d')
params['dt_start__gte'] = unaware.replace(tzinfo=local_tz)
else:
dt = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
first_job = Job.objects.earliest('dt_start')
params['dt_start__gte'] = first_job.dt_start
if is_valid_queryparam(self.request.GET.get('date_end')):
unaware = datetime.strptime(self.request.GET.get('date_end'), '%Y-%m-%d')
params['dt_end__lte'] = unaware.replace(tzinfo=local_tz) + timedelta(days=1)
else:
dt = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
dt_aware = local_tz.localize(dt)
params['dt_end__lte'] = dt_aware + timedelta(days=1)
我不知道这是否有帮助,但这是测试:
class MachineDurationViewTestCase(CustomAPITestCase):
"""This testcase contains tests for the API endpoint MachineDurationView """
# todo once views and some of its variables were renamed, also apply these name changes here
fake = Faker()
def setUp(self) -> None:
self.fake.seed()
super(MachineDurationViewTestCase, self).setUp()
def test_a_single_job_that_occurs_in_the_space_of_one_hour(self):
"""
In this test a single job of 30 minutes is created occuring on the first hour on the current date. This means
that we should expect the endpoint to return an array of 24 value where the first item in the array has a value
of 0.5 (Because the first hour only occurs 1 time, and job lasts 30 minutes, machine occupancy is 50%)
"""
dt = timezone.localtime()
dt_start = dt.replace(hour=0, minute=15)
dt_end = dt.replace(hour=0, minute=45)
# dt_end = timezone.datetime(d.year, d.month, d.day, hour=0, minute=45)
# dt_start = timezone.make_aware(timezone.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))
print(dt_start)
print(dt_end)
job = JobFactory(dt_start=dt_start, dt_end=dt_end)
print(job.dt_start)
# Query the dbase to ensure the job is created
self.assertEqual(Job.objects.all().count(), 1)
# Force create/login a user to access the http mocking client
# (I don't care about authentication or permissions in this test)
self.client.force_login(user=UserFactory(is_superuser=True))
response = self.client.get(reverse('data_app:machine_avg'))
self.assertEqual(response.status_code, 200)
print(response.data['machines'])
self.assertNotEqual(response.data['machines'][0], 0.0, "Since we create a job on the first hour, we expect the"
"first item of the array not to be zero.")
self.assertEqual(response.data['machines'][0], 0.5, "Since we create a single job of 30 minutes that occurs on "
"the current date, the value on the given hour should be"
"0.5 (50% occupancy)")
# job = JobFactory(dt_start=)
我认为您的输入数据有问题。这似乎对我有用:
from datetime import date
start = date(2020, 8, 20)
end = date(2020, 8, 22)
day_count(6, start, end)
这 returns 需要输出 1。我的日期类型是:<class 'datetime.date'>
计算日期范围内具体星期几的总数的函数可以通过使用日期对象的weekday()方法来实现:
from datetime import date, timedelta
def days_count(weekdays: list, start: date, end: date):
dates_diff = end-start
days = [start + timedelta(days=i) for i in range(dates_diff.days)]
return len([day for day in days if day.weekday() in weekdays])
start = date(2020, 8, 20)
end = date(2020, 8, 22)
# total of weekend days between that range (end date is excluded)
print(days_count([5, 6], start, end)) # outputs: 0