use dates rather than datetimes when comparing with bst_date

bst_date is a date field. Comparing dates with datetimes in postgres
gets confusing and dangerous. See this example, where a date evaluates
as older than midnight that same day.

```
notification_api=# select '2019-04-01' >= '2019-04-01 00:00';
 ?column?
----------
 f
(1 row)
```

By only using dates everywhere, we reduce the chance of these bugs
happening
This commit is contained in:
Leo Hemsted
2019-08-30 17:16:43 +01:00
parent 5975ae2383
commit 93e631221a
4 changed files with 12 additions and 9 deletions

View File

@@ -1,4 +1,4 @@
from datetime import datetime, timedelta
from datetime import datetime, timedelta, date, time
from notifications_utils.timezones import convert_bst_to_utc
import pytz
@@ -64,6 +64,9 @@ def get_current_financial_year_start_year():
def get_financial_year_for_datetime(start_date):
if type(start_date) == date:
start_date = datetime.combine(start_date, time.min)
year = int(start_date.strftime('%Y'))
if start_date < get_april_fools(year):
return year - 1

View File

@@ -1,4 +1,4 @@
from datetime import datetime, timedelta, time
from datetime import datetime, timedelta, time, date
from flask import current_app
from notifications_utils.timezones import convert_bst_to_utc, convert_utc_to_bst
@@ -7,7 +7,6 @@ from sqlalchemy import func, case, desc, Date, Integer, and_
from app import db
from app.dao.date_util import (
get_april_fools as financial_year_start,
get_financial_year,
get_financial_year_for_datetime
)
@@ -34,7 +33,7 @@ from app.utils import get_london_midnight_in_utc
def fetch_sms_free_allowance_remainder(start_date):
# ASSUMPTION: AnnualBilling has been populated for year.
billing_year = get_financial_year_for_datetime(start_date)
start_of_year = convert_utc_to_bst(financial_year_start(billing_year))
start_of_year = date(billing_year, 4, 1)
billable_units = func.coalesce(func.sum(FactBilling.billable_units * FactBilling.rate_multiplier), 0)

View File

@@ -50,15 +50,15 @@ def validate_date_range_is_within_a_financial_year(start_date, end_date):
if start_fy != end_fy:
raise InvalidRequest(message="Date must be in a single financial year.", status_code=400)
return start_date, end_date
@platform_stats_blueprint.route('usage-for-all-services')
def get_usage_for_all_services():
start_date = request.args.get('start_date')
end_date = request.args.get('end_date')
validate_date_range_is_within_a_financial_year(start_date, end_date)
start_date = datetime.strptime(start_date, "%Y-%m-%d")
end_date = datetime.strptime(end_date, "%Y-%m-%d")
start_date, end_date = validate_date_range_is_within_a_financial_year(start_date, end_date)
sms_costs = fetch_sms_billing_for_all_services(start_date, end_date)
letter_costs = fetch_letter_costs_for_all_services(start_date, end_date)

View File

@@ -1,4 +1,4 @@
from datetime import datetime
from datetime import datetime, date
import pytest
@@ -40,7 +40,8 @@ def test_get_month_start_and_end_date_in_utc(month, year, expected_start, expect
(datetime(2018, 3, 31, 23, 0, 0), 2018),
(datetime(2019, 3, 31, 22, 59, 59), 2018),
(datetime(2019, 3, 31, 23, 0, 0), 2019),
(datetime(2020, 3, 31, 22, 59, 0), 2019),
(date(2019, 3, 31), 2018),
(date(2019, 4, 1), 2019),
])
def test_get_financial_year_for_datetime(dt, fy):
assert get_financial_year_for_datetime(dt) == fy