Skip to content

Commit

Permalink
sort choices to make it easier to select
Browse files Browse the repository at this point in the history
The sorting is applied to both standard and GMT choices.
  • Loading branch information
hrbonz committed Jan 17, 2024
1 parent 4207dc0 commit 70dea6e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 15 deletions.
20 changes: 15 additions & 5 deletions tests/test_choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,21 @@ def tzs3_names():
]


@pytest.fixture
def tzs3_names_sorted():
yield [
"America/Argentina/Buenos_Aires",
"America/Los_Angeles",
"Europe/London",
]


@pytest.fixture
def tzs3_standard_displays():
yield [
"America/Argentina/Buenos Aires",
"America/Los Angeles",
"Europe/London",
"America/Argentina/Buenos Aires",
]


Expand Down Expand Up @@ -104,10 +113,11 @@ def test_with_gmt_offset_transition_backward(use_pytz, utc_tzobj):
assert with_gmt_offset(tz_names, now=after, use_pytz=use_pytz) == [("Europe/London", "GMT+00:00 Europe/London")]


def test_standard_using_timezone_names(tzs3_names, tzs3_standard_displays):
assert standard(tzs3_names) == list(zip(tzs3_names, tzs3_standard_displays))
def test_standard_using_timezone_names(tzs3_names, tzs3_names_sorted, tzs3_standard_displays):
assert standard(tzs3_names) == list(zip(tzs3_names_sorted, tzs3_standard_displays))


def test_standard_using_timezone_objects(tzs3_names, tzs3_standard_displays, to_tzobj):
def test_standard_using_timezone_objects(tzs3_names, tzs3_names_sorted, tzs3_standard_displays, to_tzobj):
tzs3_objects = [to_tzobj(tz) for tz in tzs3_names]
assert standard(tzs3_objects) == list(zip(tzs3_objects, tzs3_standard_displays))
tzs3_objects_sorted = [to_tzobj(tz) for tz in tzs3_names_sorted]
assert standard(tzs3_objects) == list(zip(tzs3_objects_sorted, tzs3_standard_displays))
14 changes: 6 additions & 8 deletions tests/test_choices_display_option.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ def test_form_field_invalid_choices_display(use_pytz):
def test_form_field_none(ChoicesDisplayForm, base_tzstrs):
form = ChoicesDisplayForm()
values, displays = zip(*form.fields["tz_none"].choices)
assert values == tuple(base_tzstrs)
assert displays[values.index("America/Los_Angeles")] == "America/Los Angeles"
assert displays[values.index("Asia/Kolkata")] == "Asia/Kolkata"

Expand Down Expand Up @@ -136,10 +135,10 @@ def test_form_field_limited_none(ChoicesDisplayForm):
def test_form_field_limited_standard(ChoicesDisplayForm):
form = ChoicesDisplayForm()
assert form.fields["tz_limited_standard"].choices == [
("Asia/Tokyo", "Asia/Tokyo"),
("Asia/Dubai", "Asia/Dubai"),
("America/Argentina/Buenos_Aires", "America/Argentina/Buenos Aires"),
("Africa/Nairobi", "Africa/Nairobi"),
("America/Argentina/Buenos_Aires", "America/Argentina/Buenos Aires"),
("Asia/Dubai", "Asia/Dubai"),
("Asia/Tokyo", "Asia/Tokyo"),
]


Expand All @@ -156,7 +155,6 @@ def test_form_field_limited_with_gmt_offset(ChoicesDisplayForm):
def test_model_form_field_none(ChoicesDisplayModelForm, to_tzobj, base_tzobjs):
form = ChoicesDisplayModelForm()
values, displays = zip(*form.fields["tz_none"].choices)
assert values == ("",) + tuple(base_tzobjs)
assert displays[values.index(to_tzobj("America/Los_Angeles"))] == "America/Los Angeles"
assert displays[values.index(to_tzobj("Asia/Kolkata"))] == "Asia/Kolkata"

Expand Down Expand Up @@ -192,10 +190,10 @@ def test_moel_form_field_limited_standard(ChoicesDisplayModelForm, to_tzobj):
form = ChoicesDisplayModelForm()
assert form.fields["tz_limited_standard"].choices == [
("", "---------"),
(to_tzobj("Asia/Tokyo"), "Asia/Tokyo"),
(to_tzobj("Asia/Dubai"), "Asia/Dubai"),
(to_tzobj("America/Argentina/Buenos_Aires"), "America/Argentina/Buenos Aires"),
(to_tzobj("Africa/Nairobi"), "Africa/Nairobi"),
(to_tzobj("America/Argentina/Buenos_Aires"), "America/Argentina/Buenos Aires"),
(to_tzobj("Asia/Dubai"), "Asia/Dubai"),
(to_tzobj("Asia/Tokyo"), "Asia/Tokyo"),
]


Expand Down
26 changes: 24 additions & 2 deletions timezone_field/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@
from timezone_field.backends import get_tz_backend


def normalize_standard(tztuple):
"""Normalize timezone names by replacing special characters with space.
For proper sorting, using spaces makes all comparisons mor consistent.
:param str tztuple: tuple of timezone and representation
"""
return tztuple[1].translate(str.maketrans({'-': ' ', '_': ' '}))


def normalize_gmt(tztuple):
"""Normalize timezone GMT names for sorting.
For proper sorting, using GMT values as a positive or negative number.
:param str tztuple: tuple of timezone and representation
"""
gmt = tztuple[1].split()[0]
cmp = gmt.replace('GMT','').replace(':', '')
return int(cmp)


def standard(timezones):
"""
Given a list of timezones (either strings of timezone objects),
Expand All @@ -14,7 +36,7 @@ def standard(timezones):
for tz in timezones:
tz_str = str(tz)
choices.append((tz, tz_str.replace("_", " ")))
return choices
return sorted(choices, key=normalize_standard)


def with_gmt_offset(timezones, now=None, use_pytz=None):
Expand All @@ -41,4 +63,4 @@ def with_gmt_offset(timezones, now=None, use_pytz=None):
_choices.append((delta, tz, display))
_choices.sort(key=lambda x: x[0])
choices = [(one, two) for zero, one, two in _choices]
return choices
return sorted(choices, key=normalize_gmt)

0 comments on commit 70dea6e

Please sign in to comment.