diff --git a/app/main/forms.py b/app/main/forms.py index 650f72891..ccd9fc14a 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -27,27 +27,55 @@ from app.main.validators import (Blacklist, CsvFileValidator, ValidGovEmail, NoC def get_time_value_and_label(future_time): return ( future_time.replace(tzinfo=None).isoformat(), - get_human_time(future_time.astimezone(pytz.timezone('Europe/London'))) + '{} at {}'.format( + get_human_day(future_time.astimezone(pytz.timezone('Europe/London'))), + get_human_time(future_time.astimezone(pytz.timezone('Europe/London'))) + ) ) def get_human_time(time): return { - '0': 'Midnight', - '12': 'Midday' + '0': 'midnight', + '12': 'midday' }.get( time.strftime('%-H'), time.strftime('%-I%p').lower() ) -def get_next_hours_from(now, hours=23): +def get_human_day(time): + # Add 1 hour to get ‘midnight today’ instead of ‘midnight tomorrow’ + time = (time - timedelta(hours=1)).strftime('%A') + if time == datetime.utcnow().strftime('%A'): + return 'Today' + if time == (datetime.utcnow() + timedelta(days=1)).strftime('%A'): + return 'Tomorrow' + return time + + +def get_furthest_possible_scheduled_time(): + return (datetime.utcnow() + timedelta(days=4)).replace(hour=0) + + +def get_next_hours_until(until): + now = datetime.utcnow() + hours = int((until - now).total_seconds() / (60 * 60)) return [ (now + timedelta(hours=i)).replace(minute=0, second=0).replace(tzinfo=pytz.utc) for i in range(1, hours + 1) ] +def get_next_days_until(until): + now = datetime.utcnow() + days = int((until - now).total_seconds() / (60 * 60 * 24)) + return [ + get_human_day((now + timedelta(days=i)).replace(tzinfo=pytz.utc)) + for i in range(0, days + 1) + ] + + def email_address(label='Email address', gov_user=True): validators = [ Length(min=5, max=255), @@ -310,7 +338,9 @@ class ChooseTimeForm(Form): def __init__(self, *args, **kwargs): super(ChooseTimeForm, self).__init__(*args, **kwargs) self.scheduled_for.choices = [('', 'Now')] + [ - get_time_value_and_label(hour) for hour in get_next_hours_from(datetime.utcnow()) + get_time_value_and_label(hour) for hour in get_next_hours_until( + get_furthest_possible_scheduled_time() + ) ] scheduled_for = RadioField( diff --git a/app/main/views/send.py b/app/main/views/send.py index 2ef85dd24..9766e7c7c 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -23,7 +23,7 @@ from notifications_utils.template import Template from notifications_utils.recipients import RecipientCSV, first_column_heading, validate_and_format_phone_number from app.main import main -from app.main.forms import CsvUploadForm, ChooseTimeForm +from app.main.forms import CsvUploadForm, ChooseTimeForm, get_next_days_until, get_furthest_possible_scheduled_time from app.main.uploader import ( s3upload, s3download diff --git a/tests/app/main/test_choose_time_form.py b/tests/app/main/test_choose_time_form.py index 70977908f..82b858ccb 100644 --- a/tests/app/main/test_choose_time_form.py +++ b/tests/app/main/test_choose_time_form.py @@ -9,12 +9,28 @@ def test_form_contains_next_24h(app_): choices = ChooseTimeForm().scheduled_for.choices + # Friday assert choices[0] == ('', 'Now') - assert choices[1] == ('2016-01-01T12:00:00.061258', 'Midday') - assert choices[23] == ('2016-01-02T10:00:00.061258', '10am') + assert choices[1] == ('2016-01-01T12:00:00.061258', 'Today at midday') + assert choices[13] == ('2016-01-02T00:00:00.061258', 'Today at midnight') + + # Saturday + assert choices[14] == ('2016-01-02T01:00:00.061258', 'Tomorrow at 1am') + assert choices[37] == ('2016-01-03T00:00:00.061258', 'Tomorrow at midnight') + + # Sunday + assert choices[38] == ('2016-01-03T01:00:00.061258', 'Sunday at 1am') + + # Monday + assert choices[84] == ('2016-01-04T23:00:00.061258', 'Monday at 11pm') + assert choices[85] == ('2016-01-05T00:00:00.061258', 'Monday at midnight') with pytest.raises(IndexError): - assert choices[24] + assert choices[ + 12 + # hours left in the day + (3 * 24) + # 3 days + 2 # magic number + ] @freeze_time("2016-01-01 11:09:00.061258")