Skip to content

Instantly share code, notes, and snippets.

@samdoran
Last active April 7, 2023 21:41
Show Gist options
  • Save samdoran/94bf7071186b58d4a888a68f32fc564f to your computer and use it in GitHub Desktop.
Save samdoran/94bf7071186b58d4a888a68f32fc564f to your computer and use it in GitHub Desktop.
Refactoring `get_months_in_date_range`
diff --git koku/api/test_utils.py koku/api/test_utils.py
index 960f4653..daf3c376 100644
--- koku/api/test_utils.py
+++ koku/api/test_utils.py
@@ -290,12 +290,10 @@ class GetMonthsInDateRangeTest(unittest.TestCase):
self.early_start_date = datetime.datetime(2022, 4, 3, tzinfo=pytz.UTC)
self.early_end_date = datetime.datetime(2022, 4, 12, tzinfo=pytz.UTC)
- @patch("api.utils.DateAccessor.today")
@patch("api.utils.DateHelper.today", new_callable=PropertyMock)
- def test_get_months_in_date_range__report_with_dates(self, mock_dh_today, mock_date_accessor_today):
+ def test_get_months_in_date_range__report_with_dates(self, mock_dh_today):
"""Test that calling get_months_in_date_range with report only returns list of month tuples"""
- mock_date_accessor_today.return_value = self.start_date
mock_dh_today.return_value = self.start_date
expected_start = self.start_date.strftime("%Y-%m-%d")
expected_end = self.end_date.strftime("%Y-%m-%d")
@@ -311,16 +309,14 @@ class GetMonthsInDateRangeTest(unittest.TestCase):
self.assertEqual(returned_months, expected_months)
- @patch("api.utils.DateAccessor.today")
@patch("api.utils.DateHelper.today", new_callable=PropertyMock)
- def test_get_months_in_date_range__report_with_no_dates(self, mock_dh_today, mock_date_accessor_today):
+ def test_get_months_in_date_range__report_with_no_dates(self, mock_dh_today):
"""
Test that calling get_months_in_date_range
with a report missing start, end or both dates
returns list of month tuples.
"""
- mock_date_accessor_today.return_value = self.start_date
mock_dh_today.return_value = self.start_date
test_report = {
"schema": "org1234567",
@@ -334,16 +330,14 @@ class GetMonthsInDateRangeTest(unittest.TestCase):
self.assertEqual(returned_months, expected_months)
- @patch("api.utils.DateAccessor.today")
@patch("api.utils.DateHelper.today", new_callable=PropertyMock)
- def test_get_months_in_date_range__report_with_no_dates_year_start(self, mock_dh_today, mock_date_accessor_today):
+ def test_get_months_in_date_range__report_with_no_dates_year_start(self, mock_dh_today):
"""
Test that calling get_months_in_date_range
with a report missing start, end or both dates
returns list of month tuples at the beginning of the year
"""
- mock_date_accessor_today.return_value = self.first_of_year
mock_dh_today.return_value = self.first_of_year
test_report = {
"schema": "org1234567",
@@ -360,16 +354,14 @@ class GetMonthsInDateRangeTest(unittest.TestCase):
self.assertEqual(returned_months, expected_months)
- @patch("api.utils.DateAccessor.today")
@patch("api.utils.DateHelper.today", new_callable=PropertyMock)
- def test_get_months_in_date_range__report_with_no_dates_month_start(self, mock_dh_today, mock_date_accessor_today):
+ def test_get_months_in_date_range__report_with_no_dates_month_start(self, mock_dh_today):
"""
Test that calling get_months_in_date_range
with a report missing start, end or both dates
returns list of month tuples during first of a month
"""
- mock_date_accessor_today.return_value = self.first_of_month
mock_dh_today.return_value = self.first_of_month
test_report = {
"schema": "org1234567",
@@ -394,7 +386,7 @@ class GetMonthsInDateRangeTest(unittest.TestCase):
returns list of month tuples.
"""
- mock_dh_today.return_value.date.return_value = self.start_date
+ mock_dh_today.return_value = self.start_date
invoice_month = self.start_date.strftime("%Y%m")
expected_date = self.start_date.strftime("%Y-%m-%d")
expected_months = [(expected_date, expected_date, invoice_month)]
diff --git koku/api/utils.py koku/api/utils.py
index 542d019d..17c17023 100644
--- koku/api/utils.py
+++ koku/api/utils.py
@@ -21,7 +21,6 @@ from api.user_settings.settings import USER_SETTINGS
from koku.settings import KOKU_DEFAULT_COST_TYPE
from koku.settings import KOKU_DEFAULT_CURRENCY
from masu.config import Config
-from masu.external.date_accessor import DateAccessor
from reporting.user_settings.models import UserSettings
@@ -463,10 +462,24 @@ def get_split_date_string(date_str):
return date_str
-def get_months_in_date_range(report=None, start=None, end=None, invoice_month=None):
+def get_months_in_date_range(
+ report: dict[str, str] = None, start: str = None, end: str = None, invoice_month: str = None
+) -> list[tuple[str, str]]:
"""returns the month periods in a given date range from report"""
dh = DateHelper()
+ date_format = "%Y-%m-%d"
+ invoice_date_format = "%Y%m"
+
+ # Converting inputs to datetime objects
+ dt_start = datetime.datetime.strptime(start, date_format).replace(tzinfo=pytz.UTC) if start else None
+ dt_end = datetime.datetime.strptime(end, date_format).replace(tzinfo=pytz.UTC) if end else None
+ dt_invoice_month = (
+ datetime.datetime.strptime(invoice_month, invoice_date_format).replace(tzinfo=pytz.UTC)
+ if invoice_month
+ else None
+ )
+
if report:
manifest_start = report.get("start")
manifest_end = report.get("end")
@@ -474,55 +487,62 @@ def get_months_in_date_range(report=None, start=None, end=None, invoice_month=No
if manifest_start and manifest_end:
LOG.info(f"using start: {manifest_start} and end: {manifest_end} dates from manifest")
- start_date = manifest_start
- end_date = manifest_end
+ dt_start = datetime.datetime.strptime(manifest_start, date_format).replace(tzinfo=pytz.UTC)
+ dt_end = datetime.datetime.strptime(manifest_end, date_format).replace(tzinfo=pytz.UTC)
if manifest_invoice_month:
LOG.info(f"using invoice_month: {manifest_invoice_month}")
- invoice_month = manifest_invoice_month
+ dt_invoice_month = datetime.datetime.strptime(manifest_invoice_month, invoice_date_format).replace(
+ tzinfo=pytz.UTC
+ )
else:
LOG.info("generating start and end dates for manifest")
- start_date = DateAccessor().today() - datetime.timedelta(days=2)
- start_date = start_date.strftime("%Y-%m-%d")
- end_date = DateAccessor().today().strftime("%Y-%m-%d")
-
- elif invoice_month:
- if not end:
- end = dh.today.date().strftime("%Y-%m-%d")
- return [(start, end, invoice_month)] # For report_data masu api
-
- else:
- start_date = start
- end_date = end
+ dt_start = dh.today - datetime.timedelta(days=2)
+ dt_end = dh.today
+
+ elif dt_invoice_month:
+ if not dt_end:
+ dt_end = dh.today
+
+ # For report_data masu API
+ return [
+ (
+ dt_start.strftime(date_format),
+ dt_end.strftime(date_format),
+ dt_invoice_month.strftime(invoice_date_format),
+ )
+ ]
# Grabbing ingest delta for initial ingest/summary
- summary_month = (dh.today + relativedelta(months=-Config.INITIAL_INGEST_NUM_MONTHS)).replace(day=1)
- start_date = get_split_date_string(start_date)
- end_date = get_split_date_string(end_date)
- if datetime.datetime.strptime(start_date, "%Y-%m-%d").replace(tzinfo=pytz.UTC) < summary_month:
- start_date = summary_month.strftime("%Y-%m-01")
+ summary_month = (dh.today - relativedelta(months=Config.INITIAL_INGEST_NUM_MONTHS)).replace(day=1)
+ if dt_start < summary_month: # dt_start could be None
+ dt_start = summary_month.replace(day=1)
- if end_date and datetime.datetime.strptime(end_date, "%Y-%m-%d").replace(tzinfo=pytz.UTC) < summary_month:
- end_date = dh.today.strftime("%Y-%m-%d")
+ if dt_end < summary_month: # dt_end could be None
+ dt_end = dh.today
if report and report.get("provider_type") in [Provider.PROVIDER_GCP, Provider.PROVIDER_GCP_LOCAL]:
- return [(start_date, end_date, invoice_month)]
-
- start_date = ciso8601.parse_datetime(start_date).replace(tzinfo=pytz.UTC)
- end_date = ciso8601.parse_datetime(end_date).replace(tzinfo=pytz.UTC) if end_date else dh.today
- months = dh.list_month_tuples(start_date, end_date)
-
- num_months = len(months)
+ return [
+ (
+ dt_start.strftime(date_format),
+ dt_end.strftime(date_format),
+ dt_invoice_month.strftime(invoice_date_format),
+ )
+ ]
+
+ months = dh.list_month_tuples(dt_start, dt_end)
+ # The order is fragile here. For one item lists, months[0] == months[-1].
first_month = months[0]
- months[0] = (start_date, first_month[1])
-
- last_month = months[num_months - 1]
- months[num_months - 1] = (last_month[0], end_date)
-
- # need to format all the datetimes into strings with the format "%Y-%m-%d" for the celery task
- for i, month in enumerate(months):
- start, end = month
- start_date = start.date().strftime("%Y-%m-%d")
- end_date = end.date().strftime("%Y-%m-%d")
- months[i] = (start_date, end_date, invoice_month) # Invoice month is really only for GCP
-
- return months
+ months[0] = (dt_start, first_month[1])
+
+ last_month = months[-1]
+ months[-1] = (last_month[0], dt_end)
+
+ # Format all the datetimes into strings with the format "%Y-%m-%d" for the celery task
+ return [
+ (
+ start.strftime(date_format),
+ end.strftime(date_format),
+ invoice_month, # Invoice month is really only for GCP
+ )
+ for start, end in months
+ ]
def get_months_in_date_range(
report: dict[str, str] = None, start: str = None, end: str = None, invoice_month: str = None
) -> list[tuple[str, str]]:
"""returns the month periods in a given date range from report"""
dh = DateHelper()
date_format = "%Y-%m-%d"
invoice_date_format = "%Y%m"
# Converting inputs to datetime objects
dt_start = datetime.datetime.strptime(start, date_format).replace(tzinfo=pytz.UTC) if start else None
dt_end = datetime.datetime.strptime(end, date_format).replace(tzinfo=pytz.UTC) if end else None
dt_invoice_month = (
datetime.datetime.strptime(invoice_month, invoice_date_format).replace(tzinfo=pytz.UTC)
if invoice_month
else None
)
if report:
manifest_start = report.get("start")
manifest_end = report.get("end")
manifest_invoice_month = report.get("invoice_month")
if manifest_start and manifest_end:
LOG.info(f"using start: {manifest_start} and end: {manifest_end} dates from manifest")
dt_start = datetime.datetime.strptime(manifest_start, date_format).replace(tzinfo=pytz.UTC)
dt_end = datetime.datetime.strptime(manifest_end, date_format).replace(tzinfo=pytz.UTC)
if manifest_invoice_month:
LOG.info(f"using invoice_month: {manifest_invoice_month}")
dt_invoice_month = datetime.datetime.strptime(manifest_invoice_month, invoice_date_format).replace(
tzinfo=pytz.UTC
)
else:
LOG.info("generating start and end dates for manifest")
dt_start = dh.today - datetime.timedelta(days=2)
dt_end = dh.today
elif dt_invoice_month:
if not dt_end:
dt_end = dh.today
# For report_data masu API
return [
(
dt_start.strftime(date_format),
dt_end.strftime(date_format),
dt_invoice_month.strftime(invoice_date_format),
)
]
# Grabbing ingest delta for initial ingest/summary
summary_month = (dh.today - relativedelta(months=Config.INITIAL_INGEST_NUM_MONTHS)).replace(day=1)
if dt_start < summary_month: # dt_start could be None
dt_start = summary_month.replace(day=1)
if dt_end < summary_month: # dt_end could be None
dt_end = dh.today
if report and report.get("provider_type") in [Provider.PROVIDER_GCP, Provider.PROVIDER_GCP_LOCAL]:
return [
(
dt_start.strftime(date_format),
dt_end.strftime(date_format),
dt_invoice_month.strftime(invoice_date_format),
)
]
months = dh.list_month_tuples(dt_start, dt_end)
# The order is fragile here. For one item lists, months[0] == months[-1].
first_month = months[0]
months[0] = (dt_start, first_month[1])
last_month = months[-1]
months[-1] = (last_month[0], dt_end)
# Format all the datetimes into strings with the format "%Y-%m-%d" for the celery task
return [
(
start.strftime(date_format),
end.strftime(date_format),
invoice_month, # Invoice month is really only for GCP
)
for start, end in months
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment