Skip to content

Commit 76e4769

Browse files
authored
Merge pull request #202 from ioet/201_tz_in_time_entries
feat: 💥 add timezone_offset in date range filter #201
2 parents 5058e72 + 6cbc601 commit 76e4769

File tree

4 files changed

+136
-55
lines changed

4 files changed

+136
-55
lines changed

tests/time_tracker_api/time_entries/time_entries_namespace_test.py

Lines changed: 108 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
get_current_month,
1313
current_datetime,
1414
current_datetime_str,
15+
get_date_range_of_month,
16+
datetime_str,
1517
)
1618
from utils import worked_time
1719

@@ -581,35 +583,121 @@ def test_create_with_valid_uuid_format_should_return_created(
581583

582584

583585
@pytest.mark.parametrize(
584-
'url,month,year',
586+
'url',
585587
[
586-
('/time-entries?month=4&year=2020', 4, 2020),
587-
('/time-entries?month=4', 4, get_current_year()),
588-
('/time-entries', get_current_month(), get_current_year()),
588+
(
589+
'/time-entries?start_date=2020-04-01T00:00:00&end_date=2020-04-30T23:00:00'
590+
),
591+
('/time-entries?month=4&year=2020'),
592+
('/time-entries?month=4'),
593+
('/time-entries?year=2020'),
594+
('/time-entries'),
589595
],
590596
)
591-
def test_find_all_is_called_with_generated_dates(
597+
def test_get_all_passes_date_range_built_from_params_to_find_all(
598+
client: FlaskClient, valid_header: dict, url: str, time_entries_dao
599+
):
600+
time_entries_dao.repository.find_all = Mock(return_value=[])
601+
602+
response = client.get(url, headers=valid_header)
603+
604+
time_entries_dao.repository.find_all.assert_called_once()
605+
_, kwargs = time_entries_dao.repository.find_all.call_args
606+
assert 'date_range' in kwargs
607+
assert 'start_date' in kwargs['date_range']
608+
assert 'end_date' in kwargs['date_range']
609+
610+
611+
@pytest.mark.parametrize(
612+
'url,start_date,end_date',
613+
[
614+
(
615+
'/time-entries?month=4&year=2020',
616+
'2020-04-01T05:00:00+00:00',
617+
'2020-05-01T04:59:59.999999+00:00',
618+
),
619+
(
620+
'/time-entries?start_date=2020-04-01T00:00:00&end_date=2020-04-30T23:00:00',
621+
'2020-04-01T05:00:00+00:00',
622+
'2020-05-01T04:00:00+00:00',
623+
),
624+
],
625+
)
626+
def test_get_all_passes_date_range_to_find_all_with_default_tz_offset(
592627
client: FlaskClient,
593-
mocker: MockFixture,
594628
valid_header: dict,
595-
owner_id: str,
629+
time_entries_dao,
596630
url: str,
597-
month: int,
598-
year: int,
631+
start_date: str,
632+
end_date: str,
599633
):
600-
from time_tracker_api.time_entries.time_entries_namespace import (
601-
time_entries_dao,
602-
)
634+
time_entries_dao.repository.find_all = Mock(return_value=[])
603635

604-
dao_get_all_mock = mocker.patch.object(
605-
time_entries_dao, 'get_all', return_value=[]
606-
)
636+
response = client.get(url, headers=valid_header)
607637

608-
response = client.get(url, headers=valid_header, follow_redirects=True)
638+
time_entries_dao.repository.find_all.assert_called_once()
639+
_, kwargs = time_entries_dao.repository.find_all.call_args
640+
assert 'date_range' in kwargs
641+
assert 'start_date' in kwargs['date_range']
642+
assert 'end_date' in kwargs['date_range']
643+
assert kwargs['date_range']['start_date'] == start_date
644+
assert kwargs['date_range']['end_date'] == end_date
609645

610-
assert HTTPStatus.OK == response.status_code
611-
assert json.loads(response.data) is not None
612-
dao_get_all_mock.assert_called_once()
646+
647+
@pytest.mark.parametrize(
648+
'url,start_date,end_date',
649+
[
650+
(
651+
'/time-entries?month=4&year=2020&timezone_offset=300',
652+
'2020-04-01T05:00:00+00:00',
653+
'2020-05-01T04:59:59.999999+00:00',
654+
),
655+
(
656+
'/time-entries?start_date=2020-04-01T00:00:00&end_date=2020-04-30T23:00:00&timezone_offset=300',
657+
'2020-04-01T05:00:00+00:00',
658+
'2020-05-01T04:00:00+00:00',
659+
),
660+
(
661+
'/time-entries?month=4&year=2020&timezone_offset=-120',
662+
'2020-03-31T22:00:00+00:00',
663+
'2020-04-30T21:59:59.999999+00:00',
664+
),
665+
(
666+
'/time-entries?start_date=2020-04-01T00:00:00&end_date=2020-04-30T23:00:00&timezone_offset=-120',
667+
'2020-03-31T22:00:00+00:00',
668+
'2020-04-30T21:00:00+00:00',
669+
),
670+
(
671+
'/time-entries?month=4&year=2020&timezone_offset=420',
672+
'2020-04-01T07:00:00+00:00',
673+
'2020-05-01T06:59:59.999999+00:00',
674+
),
675+
(
676+
'/time-entries?start_date=2020-04-01T00:00:00&end_date=2020-04-30T23:00:00&timezone_offset=420',
677+
'2020-04-01T07:00:00+00:00',
678+
'2020-05-01T06:00:00+00:00',
679+
),
680+
],
681+
)
682+
def test_get_all_passes_date_range_to_find_all_with_given_tz_offset(
683+
client: FlaskClient,
684+
valid_header: dict,
685+
time_entries_dao,
686+
url: str,
687+
start_date: str,
688+
end_date: str,
689+
):
690+
time_entries_dao.repository.find_all = Mock(return_value=[])
691+
692+
response = client.get(url, headers=valid_header)
693+
694+
time_entries_dao.repository.find_all.assert_called_once()
695+
_, kwargs = time_entries_dao.repository.find_all.call_args
696+
assert 'date_range' in kwargs
697+
assert 'start_date' in kwargs['date_range']
698+
assert 'end_date' in kwargs['date_range']
699+
assert kwargs['date_range']['start_date'] == start_date
700+
assert kwargs['date_range']['end_date'] == end_date
613701

614702

615703
def test_summary_is_called_with_date_range_from_worked_time_module(
@@ -678,6 +766,6 @@ def test_paginated_sends_max_count_and_offset_on_call_to_repository(
678766

679767
time_entries_dao.repository.find_all.assert_called_once()
680768

681-
args, kwargs = time_entries_dao.repository.find_all.call_args
769+
_, kwargs = time_entries_dao.repository.find_all.call_args
682770
assert 'max_count' in kwargs and kwargs['max_count'] is not None
683771
assert 'offset' in kwargs and kwargs['offset'] is not None

time_tracker_api/time_entries/time_entries_model.py

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from flask_restplus import abort
77
from flask_restplus._http import HTTPStatus
88

9-
from datetime import datetime, timedelta
9+
from datetime import timedelta
1010

1111
from commons.data_access_layer.cosmos_db import (
1212
CosmosDBDao,
@@ -556,30 +556,22 @@ def get_worked_time(self, args: dict):
556556

557557
@staticmethod
558558
def handle_date_filter_args(args: dict) -> dict:
559-
date_range = None
560-
year = None
561-
month = None
562-
if 'month' and 'year' in args:
563-
month = int(args.get("month"))
564-
year = int(args.get("year"))
565-
args.pop('month')
566-
args.pop('year')
567-
elif "start_date" and "end_date" in args:
568-
date_range = args.copy()
569-
if "owner_id" in date_range:
570-
date_range.pop("owner_id")
571-
args.pop("start_date")
572-
args.pop("end_date")
573-
elif 'month' in args:
574-
month = int(args.get("month"))
575-
year = get_current_year()
576-
args.pop('month')
559+
if "start_date" and "end_date" in args:
560+
start_date = str_to_datetime(args.pop('start_date'))
561+
end_date = str_to_datetime(args.pop('end_date'))
577562
else:
578-
month = get_current_month()
579-
year = get_current_year()
580-
return (
581-
date_range if date_range else get_date_range_of_month(year, month)
582-
)
563+
month = int(args.pop("month", get_current_month()))
564+
year = int(args.pop("year", get_current_year()))
565+
start_date, end_date = get_date_range_of_month(year, month)
566+
567+
offset_in_minutes = int(args.pop('timezone_offset', 300))
568+
start_date = start_date + timedelta(minutes=offset_in_minutes)
569+
end_date = end_date + timedelta(minutes=offset_in_minutes)
570+
571+
return {
572+
'start_date': datetime_str(start_date),
573+
'end_date': datetime_str(end_date),
574+
}
583575

584576

585577
def create_dao() -> TimeEntriesDao:

time_tracker_api/time_entries/time_entries_namespace.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@
216216
location='args',
217217
)
218218

219+
attributes_filter.add_argument(
220+
'timezone_offset',
221+
required=False,
222+
store_missing=False,
223+
help="(Filter) Time zone difference, in minutes, from current locale (host system settings) to UTC.",
224+
location='args',
225+
)
226+
219227

220228
@ns.route('')
221229
class TimeEntries(Resource):

utils/time.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,33 +30,26 @@ def get_current_day() -> int:
3030
return datetime.now(pytz.UTC).day
3131

3232

33-
def get_date_range_of_month(year: int, month: int) -> Dict[str, str]:
33+
def get_date_range_of_month(year: int, month: int):
3434
def get_last_day_of_month(year: int, month: int) -> int:
3535
from calendar import monthrange
3636

3737
return monthrange(year=year, month=month)[1]
3838

39-
first_day_of_month = 1
40-
start_date = datetime(
41-
year=year, month=month, day=first_day_of_month, tzinfo=timezone.utc
42-
)
39+
start_date = datetime(year=year, month=month, day=1, tzinfo=timezone.utc)
4340

44-
last_day_of_month = get_last_day_of_month(year=year, month=month)
4541
end_date = datetime(
4642
year=year,
4743
month=month,
48-
day=last_day_of_month,
44+
day=get_last_day_of_month(year, month),
4945
hour=23,
5046
minute=59,
5147
second=59,
5248
microsecond=999999,
5349
tzinfo=timezone.utc,
5450
)
5551

56-
return {
57-
'start_date': datetime_str(start_date),
58-
'end_date': datetime_str(end_date),
59-
}
52+
return start_date, end_date
6053

6154

6255
def str_to_datetime(value: str) -> datetime:

0 commit comments

Comments
 (0)