diff --git a/rowers/models.py b/rowers/models.py index 02ca4200..f210bd57 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -100,17 +100,25 @@ smoothingchoices = ( (16,16), ) -def half_year_from_now(): - return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=182)).date() +def half_year_from_now(ttz=None): + if ttz is None: + return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=182)).date() + return (datetime.datetime.utcnow()+timezone.timedelta(days=182)).astimezone(pytz.timezone(ttz)).date() -def a_week_from_now(): - return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=7)).date() +def a_week_from_now(ttz=None): + if ttz is None: + return (datetime.datetime.now(tz=timezone.utc)+timezone.timedelta(days=7)).date() + return (datetime.datetime.utcnow()+timezone.timedelta(days=7)).astimezone(pytz.timezone(ttz)).date() -def current_day(): - return (datetime.datetime.now(tz=timezone.utc)).date() +def current_day(ttz=None): + if ttz is None: + return (datetime.datetime.now(tz=timezone.utc)).date() + return datetime.datetime.utcnow().astimezone(pytz.timezone(ttz)).date() -def current_time(): # pragma: no cover - return datetime.datetime.now(tz=timezone.utc) +def current_time(ttz=None): # pragma: no cover + if ttz is None: + return datetime.datetime.now(tz=timezone.utc) + return (datetime.datetime.utcnow()).astimezone(pytz.timezone(ttz)) class UserFullnameChoiceField(forms.ModelChoiceField): diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index dbbee2fb..0edb75eb 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -888,8 +888,17 @@ def get_dates_timeperiod(request,startdatestring='',enddatestring='', tz = pytz.timezone(rower.defaulttimezone) startdate = arrow.get(startdate) enddate = arrow.get(enddate) - startdate = startdate.astimezone(tz) - enddate = enddate.astimezone(tz) + startdate = startdate.replace(tzinfo=tz) + enddate = enddate.replace(tzinfo=tz) + else: + startdate = dt.datetime.combine(startdate,dt.datetime.min.time()) + enddate = dt.datetime.combine(enddate,dt.datetime.min.time()) + startdate = startdate.astimezone(pytz.utc) + enddate = enddate.astimezone(pytz.utc) + + # set time to 00:00 in local time + startdate = startdate.replace(hour=0,minute=0,second=0,microsecond=0) + enddate = enddate.replace(hour=0,minute=0,second=0,microsecond=0) return startdate,enddate @@ -949,6 +958,8 @@ def get_dates_timeperiod(request,startdatestring='',enddatestring='', try: startdate = dt.datetime.strptime(tstartdatestring,'%Y-%m-%d').date() enddate = dt.datetime.strptime(tenddatestring,'%Y-%m-%d').date() + startdate = dt.datetime.combine(startdate,dt.datetime.min.time()) + enddate = dt.datetime.combine(enddate,dt.datetime.min.time()) if startdate > enddate: # pragma: no cover startdate2 = enddate enddate = startdate @@ -981,6 +992,10 @@ def get_dates_timeperiod(request,startdatestring='',enddatestring='', enddate = enddate.astimezone(tz) + # set time to 00:00 in local time + startdate = startdate.replace(hour=0,minute=0,second=0,microsecond=0) + enddate = enddate.replace(hour=0,minute=0,second=0,microsecond=0) + return startdate,enddate def get_sessions_manager(m,teamid=0,startdate=timezone.now(), diff --git a/rowers/tests/test_plans.py b/rowers/tests/test_plans.py index c30433af..f6f5b73f 100644 --- a/rowers/tests/test_plans.py +++ b/rowers/tests/test_plans.py @@ -30,6 +30,7 @@ class TrainingPlanTest(TestCase): self.r = Rower.objects.create(user=self.u, birthdate=faker.profile()['birthdate'], gdproptin=True,surveydone=True, + defaulttimezone='US/Pacific', gdproptindate=timezone.now(), rowerplan='coach') @@ -1238,6 +1239,7 @@ class PlannedSessionsView(TestCase): birthdate=faker.profile()['birthdate'], gdproptin=True,surveydone=True, gdproptindate=timezone.now(), + defaulttimezone='US/Pacific', rowerplan='coach') self.r.save() self.c = Client() diff --git a/rowers/tests/test_unit_tests.py b/rowers/tests/test_unit_tests.py index a3848a97..9deae35c 100644 --- a/rowers/tests/test_unit_tests.py +++ b/rowers/tests/test_unit_tests.py @@ -32,6 +32,7 @@ class OtherUnitTests(TestCase): birthdate=faker.profile()['birthdate'], gdproptin=True,surveydone=True, gdproptindate=timezone.now(), + defaulttimezone='US/Pacific', rowerplan='coach') workoutsbox = Mailbox.objects.create(name='workouts') @@ -39,6 +40,64 @@ class OtherUnitTests(TestCase): failbox = Mailbox.objects.create(name='Failed') failbox.save() + # Test get_dates_timeperiod + def test_get_dates_timeperiod(self): + rq = RequestFactory().get('/rowers/plannedsessions/') + middleware = SessionMiddleware() + middleware.process_request(rq) + + # blanco should just run + startdate,enddate = get_dates_timeperiod(rq,rower=self.r) + + # time should be midnight + self.assertEqual(startdate.strftime('%H:%M:%S'),'00:00:00') + + # tzinfo should be present + self.assertTrue(startdate.tzinfo is not None) + + # time zone should be US/Pacific + self.assertTrue('US/Pacific' in str(startdate.tzinfo)) + + # now with dates + startdatestring = '2021-09-26' + enddatestring = '2021-10-02' + startdate,enddate = get_dates_timeperiod(rq,startdatestring=startdatestring, + enddatestring=enddatestring) + + # time should be midnight + self.assertEqual(startdate.strftime('%H:%M:%S'),'00:00:00') + + # startdate and enddate should match + self.assertEqual(startdate.strftime('%m-%d'),'09-26') + self.assertEqual(enddate.strftime('%m-%d'),'10-02') + + + # tzinfo should be present + self.assertTrue(startdate.tzinfo is not None) + + # time zone should be US/Pacific + self.assertTrue('UTC' in str(startdate.tzinfo)) + + # now with dates and rower + startdatestring = '2021-09-26' + enddatestring = '2021-10-02' + startdate,enddate = get_dates_timeperiod(rq,startdatestring=startdatestring, + enddatestring=enddatestring,rower=self.r) + + # time should be midnight + self.assertEqual(startdate.strftime('%H:%M:%S'),'00:00:00') + + # startdate and enddate should match + self.assertEqual(startdate.strftime('%m-%d'),'09-26') + self.assertEqual(enddate.strftime('%m-%d'),'10-02') + + + # tzinfo should be present + self.assertTrue(startdate.tzinfo is not None) + + # time zone should be US/Pacific + self.assertTrue('US/Pacific' in str(startdate.tzinfo)) + @patch('rowers.tasks.requests.get',side_effect=mocked_requests) def test_strava_asyncworkout(self,mock_get): diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py index d9fba0dc..4047dbb5 100644 --- a/rowers/views/analysisviews.py +++ b/rowers/views/analysisviews.py @@ -2511,7 +2511,10 @@ def history_view_data(request,userid=0): ddict['hrmax'] = 0 ddict['powermean'] = int(wavg(ddf,'power','deltat')) - ddict['powermax'] = ddf['power'].max().astype(int) + try: + ddict['powermax'] = ddf['power'].max().astype(int) + except KeyError: + ddict['powermax'] = 0 ddict['nrworkouts'] = a_workouts.count() listofdicts.append(ddict) diff --git a/rowers/views/exportviews.py b/rowers/views/exportviews.py index b05c2108..ba0bf528 100644 --- a/rowers/views/exportviews.py +++ b/rowers/views/exportviews.py @@ -32,6 +32,8 @@ def workout_tcxemail_view(request,id=0): def plannedsessions_icsemail_view(request,userid=0): r = getrequestrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() sps = get_sessions(r,startdate=startdate,enddate=enddate) @@ -69,7 +71,8 @@ def plannedsessions_icsemail_view(request,userid=0): def plannedsessions_coach_icsemail_view(request,userid=0): therower = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) - + startdate = startdate.date() + enddate = enddate.date() if 'coach' in request.user.rower.rowerplan: sps = get_sessions_manager(request.user,teamid=0, enddate=enddate, @@ -195,9 +198,9 @@ def workouts_summaries_email_view(request): messages.error(request, message) return HttpResponseRedirect( reverse(r.defaultlandingpage, - kwargs = { - 'id':str(w.id), - }) + kwargs = { + 'id':str(w.id), + }) ) if request.method == 'POST': @@ -247,7 +250,7 @@ def workout_csvemail_view(request,id=0): df[' ElapsedTime (sec)'] = df['TimeStamp (sec)'] df['TimeStamp (sec)'] = df['TimeStamp (sec)'] + starttimeunix except KeyError: - pass + pass response = HttpResponse(df.to_csv()) response['Content-Disposition'] = 'attachment; filename="%s"' % filename @@ -276,9 +279,9 @@ def workout_csvtoadmin_view(request,id=0): # pragma: no cover successmessage = "The CSV file was sent to the site admin per email" messages.info(request,successmessage) url = reverse('workout_view', - kwargs = { - 'id':encoder.encode_hex(w.id), - }) + kwargs = { + 'id':encoder.encode_hex(w.id), + }) response = HttpResponseRedirect(url) return response diff --git a/rowers/views/importviews.py b/rowers/views/importviews.py index 5dad8ce9..3bcf2cc6 100644 --- a/rowers/views/importviews.py +++ b/rowers/views/importviews.py @@ -512,6 +512,9 @@ def rower_process_nkcallback(request): # pragma: no cover @login_required() def workout_getnkworkout_all(request,startdatestring='',enddatestring=''): startdate,enddate = get_dates_timeperiod(request,startdatestring=startdatestring,enddatestring=enddatestring) + startdate = startdate.date() + enddate = enddate.date() + before = arrow.get(enddate) before = str(int(before.timestamp()*1000)) @@ -540,6 +543,8 @@ def workout_getnkworkout_all(request,startdatestring='',enddatestring=''): @permission_required('rower.is_not_freecoach',fn=get_user_by_userid, raise_exception=True) def workout_nkimport_view(request,userid=0,after=0,before=0): startdate,enddate = get_dates_timeperiod(request,defaulttimeperiod='last30') + startdate = startdate.date() + enddate = enddate.date() r = getrequestrower(request,userid=userid) if r.user != request.user: # pragma: no cover messages.error(request,'You can only access your own workouts on the NK Logbook, not those of your athletes') diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index de955a94..5f069603 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -275,6 +275,8 @@ def plannedsession_multiclone_view( startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() teamid = get_team(request) if request.method == 'POST' and 'daterange' in request.POST: # pragma: no cover @@ -455,6 +457,8 @@ def template_library_view(request,userid=0): templates = templates | templates2 startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( @@ -515,6 +519,8 @@ def plannedsession_create_view(request, startdate,enddate = get_dates_timeperiod(request,startdatestring=startdatestring, enddatestring=enddatestring) + startdate = startdate.date() + enddate = enddate.date() timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') @@ -610,7 +616,8 @@ def plannedsession_create_view(request, if request.GET.get('startdate') or request.GET.get('when'): startdate, enddate = get_dates_timeperiod(request) - + startdate = startdate.date() + enddate = enddate.date() sps = get_sessions(r,startdate=startdate,enddate=enddate).exclude( @@ -696,7 +703,8 @@ def plannedsession_createtemplate_view(request, r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) - + startdate = startdate.date() + enddate = enddate.date() if request.method == 'POST': @@ -790,6 +798,8 @@ def plannedsession_multicreate_view(request, startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() teamid = get_team(request) try: trainingplan = TrainingPlan.objects.filter( @@ -923,6 +933,8 @@ def plannedsession_teamcreate_view(request, therower = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') teams = Team.objects.filter(manager=request.user) @@ -1101,6 +1113,8 @@ def plannedsession_teamedit_view(request, ps = get_object_or_404(PlannedSession,pk=id) startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') @@ -1110,6 +1124,8 @@ def plannedsession_teamedit_view(request, teaminitial = ps.team.all() startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( @@ -1278,7 +1294,8 @@ def plannedsessions_coach_view(request, startdate,enddate = get_dates_timeperiod(request) - + startdate = startdate.date() + enddate = enddate.date() trainingplan = None @@ -1412,17 +1429,18 @@ def plannedsessions_view(request, startdatestring=startdatestring, enddatestring=enddatestring, rower=r) - + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, rowers = r, - enddate__gte = enddate)[0] + enddate__gte = enddate + )[0] except IndexError: trainingplan = None - sps = get_sessions(r,startdate=startdate,enddate=enddate) completeness = {} @@ -1447,7 +1465,9 @@ def plannedsessions_view(request, ws = Workout.objects.filter( user=r, - date__gte=startdate,date__lte=enddate) + date__gte=startdate, + date__lte=enddate, + ) for w in ws: thetrimp,hrtss = dataprep.workout_trimp(w) @@ -1512,7 +1532,9 @@ def plannedsessions_view(request, unmatchedworkouts = Workout.objects.filter( user=r, plannedsession=None, - date__gte=startdate,date__lte=enddate) + date__gte=startdate, + date__lte=enddate + ) timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') breadcrumbs = [ @@ -1558,6 +1580,8 @@ def plannedsessions_print_view(request,userid=0,startdatestring='',enddatestring startdate,enddate = get_dates_timeperiod(request,startdatestring=startdatestring, enddatestring=enddatestring) + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( @@ -1599,6 +1623,8 @@ def plannedsessions_manage_view(request,userid=0, r = getrequestrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( @@ -1761,6 +1787,8 @@ def plannedsession_clone_view(request,id=0,userid=0): startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( @@ -1834,6 +1862,8 @@ def plannedsession_teamclone_view(request,id=0): startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( @@ -1882,6 +1912,8 @@ redirect_field_name=None) def plannedsession_templateedit_view(request,id=0): r = getrequestrower(request) startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, @@ -1992,6 +2024,8 @@ def plannedsession_togarmin_view(request,id=0): r = getrequestplanrower(request) startdate, enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() ps = get_object_or_404(PlannedSession,pk=id) @@ -2023,6 +2057,8 @@ def plannedsession_totemplate_view(request,id=0): r = getrequestplanrower(request) startdate, enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() ps = get_object_or_404(PlannedSession,pk=id) @@ -2054,6 +2090,9 @@ def plannedsession_edit_view(request,id=0,userid=0): r = getrequestplanrower(request,userid=userid) startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() + timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d') @@ -2381,6 +2420,9 @@ def plannedsession_view(request,id=0,userid=0): # if coursetest, need to reorder the ranking startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() + try: trainingplan = TrainingPlan.objects.filter( startdate__lte = startdate, @@ -3125,6 +3167,8 @@ def rower_trainingplan_execution_view(request, userid=0): startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() r = getrequestrower(request,userid=userid) @@ -3147,6 +3191,8 @@ def rower_trainingplan_execution_view(request, else: startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() if int(id)>0: data,message = get_execution_report(r,startdate,enddate,plan=plan) @@ -3221,6 +3267,8 @@ def rower_trainingplan_view(request, startdate,enddate = get_dates_timeperiod(request) + startdate = startdate.date() + enddate = enddate.date() plan = get_object_or_404(TrainingPlan,pk=id) r = getrequestrower(request,userid=userid)