Skip to content

Commit bf56eb7

Browse files
authored
Merge pull request #2715 from vidartf/datetime
Add datetime and time pickers
2 parents ba22d7d + d6681a6 commit bf56eb7

22 files changed

+4525
-1466
lines changed

docs/source/examples/Widget List.ipynb

+1,460-1,410
Large diffs are not rendered by default.

ipywidgets/widgets/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider, Play, SliderStyle
1616
from .widget_color import ColorPicker
1717
from .widget_date import DatePicker
18+
from .widget_datetime import DatetimePicker
19+
from .widget_time import TimePicker
1820
from .widget_output import Output
1921
from .widget_selection import RadioButtons, ToggleButtons, ToggleButtonsStyle, Dropdown, Select, SelectionSlider, SelectMultiple, SelectionRangeSlider
2022
from .widget_selectioncontainer import Tab, Accordion, Stacked
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
# Copyright (c) Vidar Tonaas Fauske.
5+
# Distributed under the terms of the Modified BSD License.
6+
7+
import pytest
8+
9+
import datetime
10+
import pytz
11+
12+
from traitlets import TraitError
13+
14+
from ..trait_types import (
15+
time_to_json,
16+
time_from_json,
17+
datetime_to_json,
18+
datetime_from_json,
19+
)
20+
21+
22+
def test_time_serialize_none():
23+
assert time_to_json(None, None) == None
24+
25+
26+
def test_time_serialize_value():
27+
t = datetime.time(13, 37, 42, 7000)
28+
assert time_to_json(t, None) == dict(
29+
hours=13, minutes=37, seconds=42, milliseconds=7
30+
)
31+
32+
33+
def test_time_deserialize_none():
34+
assert time_from_json(None, None) == None
35+
36+
37+
def test_time_deserialize_value():
38+
v = dict(hours=13, minutes=37, seconds=42, milliseconds=7)
39+
assert time_from_json(v, None) == datetime.time(13, 37, 42, 7000)
40+
41+
42+
def test_datetime_serialize_none():
43+
assert datetime_to_json(None, None) == None
44+
45+
46+
def test_datetime_serialize_value():
47+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7000, pytz.utc)
48+
assert datetime_to_json(t, None) == dict(
49+
year=2002,
50+
month=1, # Months are 0-based indices in JS
51+
date=20,
52+
hours=13,
53+
minutes=37,
54+
seconds=42,
55+
milliseconds=7,
56+
)
57+
58+
59+
def test_datetime_serialize_non_utz():
60+
# Non-existant timezone, so it wil never be the local one:
61+
tz = pytz.FixedOffset(42)
62+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7000, tz)
63+
assert datetime_to_json(t, None) == dict(
64+
year=2002,
65+
month=1, # Months are 0-based indices in JS
66+
date=20,
67+
hours=12,
68+
minutes=55,
69+
seconds=42,
70+
milliseconds=7,
71+
)
72+
73+
74+
def test_datetime_deserialize_none():
75+
assert datetime_from_json(None, None) == None
76+
77+
78+
def test_datetime_deserialize_value():
79+
tz = pytz.FixedOffset(42)
80+
v = dict(
81+
year=2002,
82+
month=1, # Months are 0-based indices in JS
83+
date=20,
84+
hours=13,
85+
minutes=37,
86+
seconds=42,
87+
milliseconds=7,
88+
)
89+
assert datetime_from_json(v, None) == datetime.datetime(
90+
2002, 2, 20, 14, 19, 42, 7000, tz
91+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
# Copyright (c) Jupyter Development Team.
5+
# Distributed under the terms of the Modified BSD License.
6+
7+
import pytest
8+
9+
import datetime
10+
11+
import pytz
12+
from traitlets import TraitError
13+
14+
from ..widget_datetime import DatetimePicker
15+
16+
17+
def test_time_creation_blank():
18+
w = DatetimePicker()
19+
assert w.value is None
20+
21+
22+
def test_time_creation_value():
23+
t = datetime.datetime.now(pytz.utc)
24+
w = DatetimePicker(value=t)
25+
assert w.value is t
26+
27+
28+
def test_time_validate_value_none():
29+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
30+
t_min = datetime.datetime(1442, 1, 1, tzinfo=pytz.utc)
31+
t_max = datetime.datetime(2056, 1, 1, tzinfo=pytz.utc)
32+
w = DatetimePicker(value=t, min=t_min, max=t_max)
33+
w.value = None
34+
assert w.value is None
35+
36+
37+
def test_time_validate_value_vs_min():
38+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
39+
t_min = datetime.datetime(2019, 1, 1, tzinfo=pytz.utc)
40+
t_max = datetime.datetime(2056, 1, 1, tzinfo=pytz.utc)
41+
w = DatetimePicker(min=t_min, max=t_max)
42+
w.value = t
43+
assert w.value.year == 2019
44+
45+
46+
def test_time_validate_value_vs_max():
47+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
48+
t_min = datetime.datetime(1664, 1, 1, tzinfo=pytz.utc)
49+
t_max = datetime.datetime(1994, 1, 1, tzinfo=pytz.utc)
50+
w = DatetimePicker(min=t_min, max=t_max)
51+
w.value = t
52+
assert w.value.year == 1994
53+
54+
55+
def test_time_validate_min_vs_value():
56+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
57+
t_min = datetime.datetime(2019, 1, 1, tzinfo=pytz.utc)
58+
t_max = datetime.datetime(2056, 1, 1, tzinfo=pytz.utc)
59+
w = DatetimePicker(value=t, max=t_max)
60+
w.min = t_min
61+
assert w.value.year == 2019
62+
63+
64+
def test_time_validate_min_vs_max():
65+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
66+
t_min = datetime.datetime(2112, 1, 1, tzinfo=pytz.utc)
67+
t_max = datetime.datetime(2056, 1, 1, tzinfo=pytz.utc)
68+
w = DatetimePicker(value=t, max=t_max)
69+
with pytest.raises(TraitError):
70+
w.min = t_min
71+
72+
73+
def test_time_validate_max_vs_value():
74+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
75+
t_min = datetime.datetime(1664, 1, 1, tzinfo=pytz.utc)
76+
t_max = datetime.datetime(1994, 1, 1, tzinfo=pytz.utc)
77+
w = DatetimePicker(value=t, min=t_min)
78+
w.max = t_max
79+
assert w.value.year == 1994
80+
81+
82+
def test_time_validate_max_vs_min():
83+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
84+
t_min = datetime.datetime(1664, 1, 1, tzinfo=pytz.utc)
85+
t_max = datetime.datetime(1337, 1, 1, tzinfo=pytz.utc)
86+
w = DatetimePicker(value=t, min=t_min)
87+
with pytest.raises(TraitError):
88+
w.max = t_max
89+
90+
91+
def test_time_validate_naive():
92+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=pytz.utc)
93+
t_min = datetime.datetime(1442, 1, 1, tzinfo=pytz.utc)
94+
t_max = datetime.datetime(2056, 1, 1, tzinfo=pytz.utc)
95+
96+
w = DatetimePicker(value=t, min=t_min, max=t_max)
97+
with pytest.raises(TraitError):
98+
w.max = t_max.replace(tzinfo=None)
99+
with pytest.raises(TraitError):
100+
w.min = t_min.replace(tzinfo=None)
101+
with pytest.raises(TraitError):
102+
w.value = t.replace(tzinfo=None)
103+
104+
105+
def test_datetime_tzinfo():
106+
tz = pytz.timezone('Australia/Sydney')
107+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=tz)
108+
w = DatetimePicker(value=t)
109+
assert w.value == t
110+
# tzinfo only changes upon input from user
111+
assert w.value.tzinfo == tz
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
# Copyright (c) Vidar Tonaas Fauske.
5+
# Distributed under the terms of the Modified BSD License.
6+
7+
import pytest
8+
9+
import datetime
10+
11+
import pytz
12+
from traitlets import TraitError
13+
14+
from ..widget_datetime import NaiveDatetimePicker
15+
16+
17+
def test_time_creation_blank():
18+
w = NaiveDatetimePicker()
19+
assert w.value is None
20+
21+
22+
def test_time_creation_value():
23+
t = datetime.datetime.today()
24+
w = NaiveDatetimePicker(value=t)
25+
assert w.value is t
26+
27+
28+
def test_time_validate_value_none():
29+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7)
30+
t_min = datetime.datetime(1442, 1, 1)
31+
t_max = datetime.datetime(2056, 1, 1)
32+
w = NaiveDatetimePicker(value=t, min=t_min, max=t_max)
33+
w.value = None
34+
assert w.value is None
35+
36+
37+
def test_time_validate_value_vs_min():
38+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7)
39+
t_min = datetime.datetime(2019, 1, 1)
40+
t_max = datetime.datetime(2056, 1, 1)
41+
w = NaiveDatetimePicker(min=t_min, max=t_max)
42+
w.value = t
43+
assert w.value.year == 2019
44+
45+
46+
def test_time_validate_value_vs_max():
47+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7)
48+
t_min = datetime.datetime(1664, 1, 1)
49+
t_max = datetime.datetime(1994, 1, 1)
50+
w = NaiveDatetimePicker(min=t_min, max=t_max)
51+
w.value = t
52+
assert w.value.year == 1994
53+
54+
55+
def test_time_validate_min_vs_value():
56+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7)
57+
t_min = datetime.datetime(2019, 1, 1)
58+
t_max = datetime.datetime(2056, 1, 1)
59+
w = NaiveDatetimePicker(value=t, max=t_max)
60+
w.min = t_min
61+
assert w.value.year == 2019
62+
63+
64+
def test_time_validate_min_vs_max():
65+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7)
66+
t_min = datetime.datetime(2112, 1, 1)
67+
t_max = datetime.datetime(2056, 1, 1)
68+
w = NaiveDatetimePicker(value=t, max=t_max)
69+
with pytest.raises(TraitError):
70+
w.min = t_min
71+
72+
73+
def test_time_validate_max_vs_value():
74+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7)
75+
t_min = datetime.datetime(1664, 1, 1)
76+
t_max = datetime.datetime(1994, 1, 1)
77+
w = NaiveDatetimePicker(value=t, min=t_min)
78+
w.max = t_max
79+
assert w.value.year == 1994
80+
81+
82+
def test_time_validate_max_vs_min():
83+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7)
84+
t_min = datetime.datetime(1664, 1, 1)
85+
t_max = datetime.datetime(1337, 1, 1)
86+
w = NaiveDatetimePicker(value=t, min=t_min)
87+
with pytest.raises(TraitError):
88+
w.max = t_max
89+
90+
91+
def test_datetime_tzinfo():
92+
tz = pytz.timezone('Australia/Sydney')
93+
t = datetime.datetime(2002, 2, 20, 13, 37, 42, 7, tzinfo=tz)
94+
with pytest.raises(TraitError):
95+
w = NaiveDatetimePicker(value=t)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#!/usr/bin/env python
2+
# coding: utf-8
3+
4+
# Copyright (c) Vidar Tonaas Fauske.
5+
# Distributed under the terms of the Modified BSD License.
6+
7+
import pytest
8+
9+
import datetime
10+
11+
from traitlets import TraitError
12+
13+
from ..widget_time import TimePicker
14+
15+
16+
def test_time_creation_blank():
17+
w = TimePicker()
18+
assert w.value is None
19+
20+
21+
def test_time_creation_value():
22+
t = datetime.time()
23+
w = TimePicker(value=t)
24+
assert w.value is t
25+
26+
27+
def test_time_validate_value_none():
28+
t = datetime.time(13, 37, 42, 7)
29+
t_min = datetime.time(2)
30+
t_max = datetime.time(22)
31+
w = TimePicker(value=t, min=t_min, max=t_max)
32+
w.value = None
33+
assert w.value is None
34+
35+
36+
def test_time_validate_value_vs_min():
37+
t = datetime.time(13, 37, 42, 7)
38+
t_min = datetime.time(14)
39+
t_max = datetime.time(22)
40+
w = TimePicker(min=t_min, max=t_max)
41+
w.value = t
42+
assert w.value.hour == 14
43+
44+
45+
def test_time_validate_value_vs_max():
46+
t = datetime.time(13, 37, 42, 7)
47+
t_min = datetime.time(2)
48+
t_max = datetime.time(12)
49+
w = TimePicker(min=t_min, max=t_max)
50+
w.value = t
51+
assert w.value.hour == 12
52+
53+
54+
def test_time_validate_min_vs_value():
55+
t = datetime.time(13, 37, 42, 7)
56+
t_min = datetime.time(14)
57+
t_max = datetime.time(22)
58+
w = TimePicker(value=t, max=t_max)
59+
w.min = t_min
60+
assert w.value.hour == 14
61+
62+
63+
def test_time_validate_min_vs_max():
64+
t = datetime.time(13, 37, 42, 7)
65+
t_min = datetime.time(14)
66+
t_max = datetime.time(12)
67+
w = TimePicker(value=t, max=t_max)
68+
with pytest.raises(TraitError):
69+
w.min = t_min
70+
71+
72+
def test_time_validate_max_vs_value():
73+
t = datetime.time(13, 37, 42, 7)
74+
t_min = datetime.time(2)
75+
t_max = datetime.time(12)
76+
w = TimePicker(value=t, min=t_min)
77+
w.max = t_max
78+
assert w.value.hour == 12
79+
80+
81+
def test_time_validate_max_vs_min():
82+
t = datetime.time(13, 37, 42, 7)
83+
t_min = datetime.time(2)
84+
t_max = datetime.time(1)
85+
w = TimePicker(value=t, min=t_min)
86+
with pytest.raises(TraitError):
87+
w.max = t_max

0 commit comments

Comments
 (0)