perspective-python 4.2.0__cp311-abi3-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- perspective/__init__.py +396 -0
- perspective/extension/finos-perspective-nbextension.json +5 -0
- perspective/handlers/__init__.py +11 -0
- perspective/handlers/aiohttp.py +61 -0
- perspective/handlers/starlette.py +55 -0
- perspective/handlers/tornado.py +184 -0
- perspective/perspective.pyd +0 -0
- perspective/templates/exported_widget.html.template +35 -0
- perspective/tests/__init__.py +11 -0
- perspective/tests/async/test_async_client.py +83 -0
- perspective/tests/async/test_websocket_client.py +124 -0
- perspective/tests/conftest.py +272 -0
- perspective/tests/core/__init__.py +11 -0
- perspective/tests/core/test_async.py +351 -0
- perspective/tests/multi_threaded/__init__.py +11 -0
- perspective/tests/multi_threaded/test_multi_threaded.py +201 -0
- perspective/tests/server/__init__.py +11 -0
- perspective/tests/server/test_server.py +1016 -0
- perspective/tests/server/test_session.py +110 -0
- perspective/tests/table/__init__.py +11 -0
- perspective/tests/table/arrow/date32.arrow +0 -0
- perspective/tests/table/arrow/date64.arrow +0 -0
- perspective/tests/table/arrow/dict.arrow +0 -0
- perspective/tests/table/arrow/dict_update.arrow +0 -0
- perspective/tests/table/arrow/int_float_str.arrow +0 -0
- perspective/tests/table/arrow/int_float_str_file.arrow +0 -0
- perspective/tests/table/arrow/int_float_str_update.arrow +0 -0
- perspective/tests/table/object_sequence.py +402 -0
- perspective/tests/table/test_column_paths.py +89 -0
- perspective/tests/table/test_delete.py +124 -0
- perspective/tests/table/test_exception.py +65 -0
- perspective/tests/table/test_leaks.py +54 -0
- perspective/tests/table/test_ports.py +178 -0
- perspective/tests/table/test_remove.py +102 -0
- perspective/tests/table/test_table.py +641 -0
- perspective/tests/table/test_table_arrow.py +503 -0
- perspective/tests/table/test_table_datetime.py +2409 -0
- perspective/tests/table/test_table_infer.py +201 -0
- perspective/tests/table/test_table_limit.py +45 -0
- perspective/tests/table/test_table_numpy.py +1022 -0
- perspective/tests/table/test_table_pandas.py +1018 -0
- perspective/tests/table/test_table_polars.py +251 -0
- perspective/tests/table/test_table_view_table.py +130 -0
- perspective/tests/table/test_to_arrow.py +417 -0
- perspective/tests/table/test_to_arrow_lz4.py +32 -0
- perspective/tests/table/test_to_format.py +1024 -0
- perspective/tests/table/test_to_polars.py +26 -0
- perspective/tests/table/test_update.py +545 -0
- perspective/tests/table/test_update_arrow.py +980 -0
- perspective/tests/table/test_update_pandas.py +211 -0
- perspective/tests/table/test_view.py +2261 -0
- perspective/tests/table/test_view_expression.py +1940 -0
- perspective/tests/test_dependencies.py +53 -0
- perspective/tests/viewer/__init__.py +11 -0
- perspective/tests/viewer/test_viewer.py +246 -0
- perspective/tests/widget/__init__.py +11 -0
- perspective/tests/widget/test_widget.py +278 -0
- perspective/tests/widget/test_widget_pandas.py +453 -0
- perspective/virtual_servers/__init__.py +134 -0
- perspective/virtual_servers/clickhouse.py +245 -0
- perspective/virtual_servers/duckdb.py +236 -0
- perspective/widget/__init__.py +349 -0
- perspective/widget/viewer/__init__.py +15 -0
- perspective/widget/viewer/validate.py +22 -0
- perspective/widget/viewer/viewer.py +343 -0
- perspective/widget/viewer/viewer_traitlets.py +101 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/install.json +5 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/package.json +71 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/253.5f5c9e80605aa4106a28.js +2 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/253.5f5c9e80605aa4106a28.js.LICENSE.txt +25 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/523.c030af5d3c4f67ff83f6.js +1 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/remoteEntry.95a8ea1b44d96032833f.js +1 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/style.js +4 -0
- perspective_python-4.2.0.data/data/share/jupyter/labextensions/@perspective-dev/jupyterlab/static/third-party-licenses.json +16 -0
- perspective_python-4.2.0.dist-info/METADATA +27 -0
- perspective_python-4.2.0.dist-info/RECORD +79 -0
- perspective_python-4.2.0.dist-info/WHEEL +4 -0
- perspective_python-4.2.0.dist-info/licenses/LICENSE.md +193 -0
- perspective_python-4.2.0.dist-info/licenses/LICENSE_THIRDPARTY_cargo.yml +17395 -0
|
@@ -0,0 +1,2409 @@
|
|
|
1
|
+
# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
# ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
# ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
# ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
# ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
# ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
# ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
# ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
# ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
# ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import time
|
|
15
|
+
from perspective.tests.conftest import Util
|
|
16
|
+
import pytz
|
|
17
|
+
import numpy as np
|
|
18
|
+
import pandas as pd
|
|
19
|
+
from datetime import date, datetime, timedelta
|
|
20
|
+
from dateutil import tz
|
|
21
|
+
from pytest import mark, raises
|
|
22
|
+
from perspective import PerspectiveError
|
|
23
|
+
import perspective as psp
|
|
24
|
+
|
|
25
|
+
client = psp.Server().new_local_client()
|
|
26
|
+
Table = client.table
|
|
27
|
+
|
|
28
|
+
LOCAL_DATETIMES = [
|
|
29
|
+
datetime(2019, 1, 11, 0, 10, 20),
|
|
30
|
+
datetime(2019, 1, 11, 11, 10, 20),
|
|
31
|
+
datetime(2019, 1, 11, 19, 10, 20),
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
LOCAL_DATETIMES_TS = [int(d.timestamp() * 1000) for d in LOCAL_DATETIMES]
|
|
35
|
+
|
|
36
|
+
# Test the DST transition for Continental US
|
|
37
|
+
LOCAL_DATETIMES_DST = [
|
|
38
|
+
datetime(2019, 3, 9, 12, 10, 20),
|
|
39
|
+
datetime(2019, 3, 19, 12, 10, 20),
|
|
40
|
+
datetime(2019, 11, 2, 12, 10, 20),
|
|
41
|
+
datetime(2019, 11, 3, 12, 10, 20),
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
LOCAL_DATETIMES_DST_TS = [int(d.timestamp() * 1000) for d in LOCAL_DATETIMES_DST]
|
|
45
|
+
|
|
46
|
+
LOCAL_TIMESTAMPS = [pd.Timestamp(d) for d in LOCAL_DATETIMES]
|
|
47
|
+
LOCAL_TIMESTAMPS_DST = [pd.Timestamp(d) for d in LOCAL_DATETIMES_DST]
|
|
48
|
+
|
|
49
|
+
# Set up testing data
|
|
50
|
+
UTC = pytz.UTC
|
|
51
|
+
|
|
52
|
+
UTC_DATETIMES = [UTC.localize(d) for d in LOCAL_DATETIMES]
|
|
53
|
+
UTC_TIMESTAMPS = [UTC.localize(d) for d in LOCAL_TIMESTAMPS]
|
|
54
|
+
|
|
55
|
+
UTC_DATETIMES_DST = [UTC.localize(d, is_dst=True) for d in LOCAL_DATETIMES_DST]
|
|
56
|
+
UTC_TIMESTAMPS_DST = [UTC.localize(d, is_dst=True) for d in LOCAL_TIMESTAMPS_DST]
|
|
57
|
+
|
|
58
|
+
PST = pytz.timezone("US/Pacific")
|
|
59
|
+
CST = pytz.timezone("US/Central")
|
|
60
|
+
EST = pytz.timezone("US/Eastern")
|
|
61
|
+
GMT = pytz.timezone("GMT")
|
|
62
|
+
HKT = pytz.timezone("Asia/Hong_Kong")
|
|
63
|
+
JPT = pytz.timezone("Asia/Tokyo")
|
|
64
|
+
ACT = pytz.timezone("Australia/ACT")
|
|
65
|
+
|
|
66
|
+
TIMEZONES = [PST, CST, EST, GMT, HKT, JPT, ACT]
|
|
67
|
+
|
|
68
|
+
TZ_DATETIMES = {}
|
|
69
|
+
TZ_TIMESTAMPS = {}
|
|
70
|
+
|
|
71
|
+
TZ_DATETIMES_DST = {}
|
|
72
|
+
TZ_TIMESTAMPS_DST = {}
|
|
73
|
+
|
|
74
|
+
for TZ in TIMEZONES:
|
|
75
|
+
TZ_DATETIMES[TZ.zone] = [TZ.localize(d) for d in LOCAL_DATETIMES]
|
|
76
|
+
TZ_TIMESTAMPS[TZ.zone] = [d.tz_localize(TZ) for d in LOCAL_TIMESTAMPS]
|
|
77
|
+
TZ_DATETIMES_DST[TZ.zone] = [d.astimezone(TZ) for d in UTC_DATETIMES_DST]
|
|
78
|
+
TZ_TIMESTAMPS_DST[TZ.zone] = [d.tz_convert(TZ) for d in UTC_TIMESTAMPS_DST]
|
|
79
|
+
|
|
80
|
+
if os.name != "nt":
|
|
81
|
+
# no tzset on windows, run these tests on linux/mac only
|
|
82
|
+
|
|
83
|
+
class TestTableLocalDateTime(object):
|
|
84
|
+
"""Test datetimes across configurations such as local time, timezone-aware,
|
|
85
|
+
timezone-naive, and UTC implementations.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def setup_method(self):
|
|
89
|
+
# To make sure that local times are not changed, set timezone to EST
|
|
90
|
+
os.environ["TZ"] = "US/Eastern"
|
|
91
|
+
time.tzset()
|
|
92
|
+
|
|
93
|
+
def teardown_method(self):
|
|
94
|
+
# go back to UTC at end of each test method, for consistency
|
|
95
|
+
os.environ["TZ"] = "UTC"
|
|
96
|
+
time.tzset()
|
|
97
|
+
|
|
98
|
+
def test_table_should_assume_local_time(self):
|
|
99
|
+
"""If a datetime object has no `tzinfo`, it should be assumed to be in
|
|
100
|
+
local time and not be converted at all.
|
|
101
|
+
"""
|
|
102
|
+
data = {"a": LOCAL_DATETIMES}
|
|
103
|
+
table = Table(data)
|
|
104
|
+
assert table.view().to_columns()["a"] == LOCAL_DATETIMES_TS
|
|
105
|
+
|
|
106
|
+
@mark.skip(reason="no numpy support in JSON Table constructor")
|
|
107
|
+
def test_table_should_assume_local_time_numpy_datetime64(self):
|
|
108
|
+
data = {"a": [np.datetime64(d) for d in LOCAL_DATETIMES]}
|
|
109
|
+
table = Table(data)
|
|
110
|
+
assert table.view().to_columns()["a"] == LOCAL_DATETIMES_TS
|
|
111
|
+
|
|
112
|
+
def test_table_should_assume_local_time_pandas_timestamp(self):
|
|
113
|
+
data = {"a": LOCAL_TIMESTAMPS}
|
|
114
|
+
|
|
115
|
+
# Timestamps are assumed to be in UTC by pandas
|
|
116
|
+
table = Table(data)
|
|
117
|
+
|
|
118
|
+
# Timestamps are read out in local time
|
|
119
|
+
assert table.view().to_columns()["a"] == LOCAL_DATETIMES_TS
|
|
120
|
+
|
|
121
|
+
@mark.skip(reason="no numpy support in JSON Table constructor")
|
|
122
|
+
def test_table_should_assume_local_time_pandas_timestamp_df(self, util: Util):
|
|
123
|
+
data = pd.DataFrame({"a": LOCAL_TIMESTAMPS})
|
|
124
|
+
|
|
125
|
+
# Timestamps are assumed to be in UTC by pandas
|
|
126
|
+
table = Table(data)
|
|
127
|
+
|
|
128
|
+
# Timestamps are read out in local time
|
|
129
|
+
assert table.view().to_columns()["a"] == [
|
|
130
|
+
util.to_timestamp(datetime(2019, 1, 10, 19, 10, 20)),
|
|
131
|
+
util.to_timestamp(datetime(2019, 1, 11, 6, 10, 20)),
|
|
132
|
+
util.to_timestamp(datetime(2019, 1, 11, 14, 10, 20)),
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
def test_table_should_assume_local_time_dst(self):
|
|
136
|
+
"""If a datetime object has no `tzinfo`, it should be assumed to be in
|
|
137
|
+
local time and not be converted at all.
|
|
138
|
+
"""
|
|
139
|
+
data = {"a": LOCAL_DATETIMES_DST}
|
|
140
|
+
table = Table(data)
|
|
141
|
+
assert table.view().to_columns()["a"] == LOCAL_DATETIMES_DST_TS
|
|
142
|
+
|
|
143
|
+
@mark.skip(reason="Do not support numpy in JSON constructor")
|
|
144
|
+
def test_table_should_assume_local_time_numpy_datetime64_dst(self):
|
|
145
|
+
data = {"a": [np.datetime64(d) for d in LOCAL_DATETIMES_DST]}
|
|
146
|
+
table = Table(data)
|
|
147
|
+
assert table.view().to_columns()["a"] == LOCAL_DATETIMES_DST_TS
|
|
148
|
+
|
|
149
|
+
def test_table_should_assume_local_time_pandas_timestamp_dst(self):
|
|
150
|
+
data = {"a": LOCAL_TIMESTAMPS_DST}
|
|
151
|
+
table = Table(data)
|
|
152
|
+
assert table.view().to_columns()["a"] == LOCAL_DATETIMES_DST_TS
|
|
153
|
+
|
|
154
|
+
def test_table_should_assume_local_time_pandas_timestamp_dst_df(self, util):
|
|
155
|
+
data = pd.DataFrame({"a": LOCAL_TIMESTAMPS_DST})
|
|
156
|
+
table = Table(data)
|
|
157
|
+
assert table.view().to_columns()["a"] == [
|
|
158
|
+
util.to_timestamp(datetime(2019, 3, 9, 7, 10, 20)),
|
|
159
|
+
util.to_timestamp(datetime(2019, 3, 19, 8, 10, 20)),
|
|
160
|
+
util.to_timestamp(datetime(2019, 11, 2, 8, 10, 20)),
|
|
161
|
+
util.to_timestamp(datetime(2019, 11, 3, 7, 10, 20)),
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
@mark.skip(reason="Python specific behavior we don't need")
|
|
165
|
+
def test_table_datetime_min(self, util):
|
|
166
|
+
data = {"a": [datetime.min]}
|
|
167
|
+
table = Table(data)
|
|
168
|
+
assert table.view().to_columns()["a"] == [
|
|
169
|
+
util.to_timestamp(datetime(1969, 12, 31, 19, 0))
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
@mark.skip(reason="Python specific behavior we don't need")
|
|
173
|
+
def test_table_datetime_min_df(self, util):
|
|
174
|
+
data = pd.DataFrame({"a": [datetime.min]})
|
|
175
|
+
table = Table(data)
|
|
176
|
+
assert table.view().to_columns()["a"] == [
|
|
177
|
+
util.to_timestamp(datetime(1969, 12, 31, 19, 0))
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
def test_table_datetime_1900(self, util):
|
|
181
|
+
table = Table({"a": "datetime"})
|
|
182
|
+
table.update({"a": [util.to_timestamp(datetime(1900, 1, 1))]})
|
|
183
|
+
assert table.view().to_columns()["a"] == [
|
|
184
|
+
util.to_timestamp(datetime(1900, 1, 1))
|
|
185
|
+
]
|
|
186
|
+
|
|
187
|
+
def test_table_datetime_1900_df(self, util):
|
|
188
|
+
data = pd.DataFrame({"a": [datetime(1900, 1, 1)]})
|
|
189
|
+
table = Table(data)
|
|
190
|
+
assert table.view().to_columns()["a"] == [
|
|
191
|
+
util.to_timestamp(datetime(1899, 12, 31, 19))
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
def test_table_datetime_1899(self, util: Util):
|
|
195
|
+
table = Table({"a": "datetime"})
|
|
196
|
+
table.update({"a": [datetime(1899, 1, 1)]})
|
|
197
|
+
assert table.view().to_columns()["a"] == [
|
|
198
|
+
util.to_timestamp(datetime(1898, 12, 31, 19))
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
def test_table_datetime_1899_df(self, util):
|
|
202
|
+
data = pd.DataFrame({"a": [datetime(1899, 1, 1)]})
|
|
203
|
+
table = Table(data)
|
|
204
|
+
assert table.view().to_columns()["a"] == [
|
|
205
|
+
util.to_timestamp(datetime(1898, 12, 31, 19))
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
def test_table_datetime_min_epoch(self, util):
|
|
209
|
+
data = {"a": [0]}
|
|
210
|
+
table = Table({"a": "datetime"})
|
|
211
|
+
table.update(data)
|
|
212
|
+
assert table.view().to_columns()["a"] == [
|
|
213
|
+
util.to_timestamp(datetime(1969, 12, 31, 19, 0))
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
def test_table_datetime_cant_convert_from_int(self):
|
|
217
|
+
data = pd.DataFrame({"a": [0]})
|
|
218
|
+
table = Table({"a": "datetime"})
|
|
219
|
+
with raises(PerspectiveError):
|
|
220
|
+
table.update(data)
|
|
221
|
+
# assert str(ex.value) == "..."
|
|
222
|
+
|
|
223
|
+
@mark.skip(
|
|
224
|
+
reason="we do not support this conversion, wrote a test above to ensure it fails"
|
|
225
|
+
)
|
|
226
|
+
def test_table_datetime_min_epoch_df(self, util):
|
|
227
|
+
data = pd.DataFrame({"a": [0]})
|
|
228
|
+
table = Table({"a": "datetime"})
|
|
229
|
+
table.update(data)
|
|
230
|
+
assert table.view().to_columns()["a"] == [
|
|
231
|
+
util.to_timestamp(datetime(1969, 12, 31, 19, 0))
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
@mark.skip
|
|
235
|
+
def test_table_datetime_max(self, util):
|
|
236
|
+
data = {"a": [datetime.max]}
|
|
237
|
+
table = Table(data)
|
|
238
|
+
|
|
239
|
+
# lol - result is converted from UTC to EST (local time)
|
|
240
|
+
assert table.view().to_columns()["a"] == [
|
|
241
|
+
util.to_timestamp(datetime(9999, 12, 31, 18, 59, 59))
|
|
242
|
+
]
|
|
243
|
+
|
|
244
|
+
@mark.skip
|
|
245
|
+
def test_table_datetime_max_df(self, util):
|
|
246
|
+
data = pd.DataFrame({"a": [datetime.max]})
|
|
247
|
+
table = Table(data)
|
|
248
|
+
assert table.view().to_columns()["a"] == [
|
|
249
|
+
util.to_timestamp(datetime(9999, 12, 31, 18, 59, 59))
|
|
250
|
+
]
|
|
251
|
+
|
|
252
|
+
class TestTableDateTimeUTCToLocal(object):
|
|
253
|
+
def teardown_method(self):
|
|
254
|
+
# Set timezone to UTC, always
|
|
255
|
+
os.environ["TZ"] = "UTC"
|
|
256
|
+
time.tzset()
|
|
257
|
+
|
|
258
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
259
|
+
def test_table_should_convert_UTC_to_local_time_pytz_pacific(self):
|
|
260
|
+
"""If the datetime has `tzinfo` set, use it to convert the datetime to
|
|
261
|
+
UTC. Make sure this works with both `pytz` and `dateutil` for
|
|
262
|
+
`datetime` and `pandas.Timestamp`.
|
|
263
|
+
"""
|
|
264
|
+
data = {"a": UTC_DATETIMES}
|
|
265
|
+
table = Table(data)
|
|
266
|
+
|
|
267
|
+
os.environ["TZ"] = "US/Pacific"
|
|
268
|
+
time.tzset()
|
|
269
|
+
|
|
270
|
+
# Should be in PST now
|
|
271
|
+
assert table.view().to_columns() == {
|
|
272
|
+
"a": [d.astimezone(PST).replace(tzinfo=None) for d in data["a"]]
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
def test_table_should_convert_UTC_to_local_time_pytz_central(self, util: Util):
|
|
276
|
+
data = {"a": UTC_DATETIMES}
|
|
277
|
+
table = Table(data)
|
|
278
|
+
|
|
279
|
+
os.environ["TZ"] = "US/Central"
|
|
280
|
+
time.tzset()
|
|
281
|
+
|
|
282
|
+
# Should be in CST now
|
|
283
|
+
assert table.view().to_columns() == {
|
|
284
|
+
"a": [
|
|
285
|
+
util.to_timestamp(d.astimezone(CST).replace(tzinfo=None))
|
|
286
|
+
for d in data["a"]
|
|
287
|
+
]
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
def test_table_should_convert_UTC_to_local_time_pytz_eastern(self, util: Util):
|
|
291
|
+
data = {"a": UTC_DATETIMES}
|
|
292
|
+
table = Table(data)
|
|
293
|
+
|
|
294
|
+
os.environ["TZ"] = "US/Eastern"
|
|
295
|
+
time.tzset()
|
|
296
|
+
|
|
297
|
+
# Should be in EST now
|
|
298
|
+
assert table.view().to_columns() == {
|
|
299
|
+
"a": [
|
|
300
|
+
util.to_timestamp(d.astimezone(EST).replace(tzinfo=None))
|
|
301
|
+
for d in data["a"]
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
def test_table_should_convert_UTC_to_local_time_pytz_GMT(self, util: Util):
|
|
306
|
+
data = {"a": UTC_DATETIMES}
|
|
307
|
+
table = Table(data)
|
|
308
|
+
|
|
309
|
+
os.environ["TZ"] = "GMT"
|
|
310
|
+
time.tzset()
|
|
311
|
+
|
|
312
|
+
# Should be in GMT now
|
|
313
|
+
assert table.view().to_columns() == {
|
|
314
|
+
"a": [
|
|
315
|
+
util.to_timestamp(d.astimezone(GMT).replace(tzinfo=None))
|
|
316
|
+
for d in data["a"]
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
def test_table_should_convert_UTC_to_local_time_pytz_HKT(self, util: Util):
|
|
321
|
+
data = {"a": UTC_DATETIMES}
|
|
322
|
+
table = Table(data)
|
|
323
|
+
|
|
324
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
325
|
+
time.tzset()
|
|
326
|
+
|
|
327
|
+
assert table.view().to_columns() == {
|
|
328
|
+
"a": [
|
|
329
|
+
util.to_timestamp(d.astimezone(HKT).replace(tzinfo=None))
|
|
330
|
+
for d in data["a"]
|
|
331
|
+
]
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
def test_table_should_convert_UTC_to_local_time_pytz_JPT(self, util: Util):
|
|
335
|
+
data = {"a": UTC_DATETIMES}
|
|
336
|
+
table = Table(data)
|
|
337
|
+
|
|
338
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
339
|
+
time.tzset()
|
|
340
|
+
|
|
341
|
+
assert table.view().to_columns() == {
|
|
342
|
+
"a": [
|
|
343
|
+
util.to_timestamp(d.astimezone(JPT).replace(tzinfo=None))
|
|
344
|
+
for d in data["a"]
|
|
345
|
+
]
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
def test_table_should_convert_UTC_to_local_time_pytz_ACT(self, util: Util):
|
|
349
|
+
data = {"a": UTC_DATETIMES}
|
|
350
|
+
table = Table(data)
|
|
351
|
+
|
|
352
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
353
|
+
time.tzset()
|
|
354
|
+
|
|
355
|
+
assert table.view().to_columns() == {
|
|
356
|
+
"a": [
|
|
357
|
+
util.to_timestamp(d.astimezone(ACT).replace(tzinfo=None))
|
|
358
|
+
for d in data["a"]
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_pacific(
|
|
363
|
+
self, util: Util
|
|
364
|
+
):
|
|
365
|
+
data = {"a": UTC_DATETIMES}
|
|
366
|
+
table = Table(data)
|
|
367
|
+
|
|
368
|
+
os.environ["TZ"] = "US/Pacific"
|
|
369
|
+
time.tzset()
|
|
370
|
+
|
|
371
|
+
# Should be in PST now
|
|
372
|
+
assert table.view().to_columns() == {
|
|
373
|
+
"a": [
|
|
374
|
+
util.to_timestamp(d.astimezone(PST).replace(tzinfo=None))
|
|
375
|
+
for d in data["a"]
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_central(
|
|
380
|
+
self, util: Util
|
|
381
|
+
):
|
|
382
|
+
data = {"a": UTC_DATETIMES}
|
|
383
|
+
table = Table(data)
|
|
384
|
+
|
|
385
|
+
os.environ["TZ"] = "US/Central"
|
|
386
|
+
time.tzset()
|
|
387
|
+
|
|
388
|
+
# Should be in CST now
|
|
389
|
+
assert table.view().to_columns() == {
|
|
390
|
+
"a": [
|
|
391
|
+
util.to_timestamp(d.astimezone(CST).replace(tzinfo=None))
|
|
392
|
+
for d in data["a"]
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_eastern(
|
|
397
|
+
self, util: Util
|
|
398
|
+
):
|
|
399
|
+
data = {"a": UTC_DATETIMES}
|
|
400
|
+
table = Table(data)
|
|
401
|
+
|
|
402
|
+
os.environ["TZ"] = "US/Eastern"
|
|
403
|
+
time.tzset()
|
|
404
|
+
|
|
405
|
+
# Should be in EST now
|
|
406
|
+
assert table.view().to_columns() == {
|
|
407
|
+
"a": [
|
|
408
|
+
util.to_timestamp(d.astimezone(EST).replace(tzinfo=None))
|
|
409
|
+
for d in data["a"]
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_GMT(self, util: Util):
|
|
414
|
+
data = {"a": UTC_DATETIMES}
|
|
415
|
+
table = Table(data)
|
|
416
|
+
|
|
417
|
+
os.environ["TZ"] = "GMT"
|
|
418
|
+
time.tzset()
|
|
419
|
+
|
|
420
|
+
# Should be in GMT now
|
|
421
|
+
assert table.view().to_columns() == {
|
|
422
|
+
"a": [
|
|
423
|
+
util.to_timestamp(d.astimezone(GMT).replace(tzinfo=None))
|
|
424
|
+
for d in data["a"]
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_pacific_DST(
|
|
429
|
+
self, util: Util
|
|
430
|
+
):
|
|
431
|
+
data = {"a": UTC_DATETIMES_DST}
|
|
432
|
+
table = Table(data)
|
|
433
|
+
|
|
434
|
+
os.environ["TZ"] = "US/Pacific"
|
|
435
|
+
time.tzset()
|
|
436
|
+
|
|
437
|
+
# Should be in PST now
|
|
438
|
+
assert table.view().to_columns() == {
|
|
439
|
+
"a": [
|
|
440
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
441
|
+
for d in TZ_DATETIMES_DST["US/Pacific"]
|
|
442
|
+
]
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_central_DST(
|
|
446
|
+
self, util: Util
|
|
447
|
+
):
|
|
448
|
+
data = {"a": UTC_DATETIMES_DST}
|
|
449
|
+
table = Table(data)
|
|
450
|
+
|
|
451
|
+
os.environ["TZ"] = "US/Central"
|
|
452
|
+
time.tzset()
|
|
453
|
+
|
|
454
|
+
# Should be in CST now
|
|
455
|
+
assert table.view().to_columns() == {
|
|
456
|
+
"a": [
|
|
457
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
458
|
+
for d in TZ_DATETIMES_DST["US/Central"]
|
|
459
|
+
]
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_eastern_DST(
|
|
463
|
+
self, util: Util
|
|
464
|
+
):
|
|
465
|
+
data = {"a": UTC_DATETIMES_DST}
|
|
466
|
+
table = Table(data)
|
|
467
|
+
|
|
468
|
+
os.environ["TZ"] = "US/Eastern"
|
|
469
|
+
time.tzset()
|
|
470
|
+
|
|
471
|
+
# Should be in EST now
|
|
472
|
+
assert table.view().to_columns() == {
|
|
473
|
+
"a": [
|
|
474
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
475
|
+
for d in TZ_DATETIMES_DST["US/Eastern"]
|
|
476
|
+
]
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_GMT_DST(
|
|
480
|
+
self, util: Util
|
|
481
|
+
):
|
|
482
|
+
data = {"a": UTC_DATETIMES_DST}
|
|
483
|
+
table = Table(data)
|
|
484
|
+
|
|
485
|
+
os.environ["TZ"] = "GMT"
|
|
486
|
+
time.tzset()
|
|
487
|
+
|
|
488
|
+
# Should be in GMT now
|
|
489
|
+
assert table.view().to_columns() == {
|
|
490
|
+
"a": [
|
|
491
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
492
|
+
for d in TZ_DATETIMES_DST["GMT"]
|
|
493
|
+
]
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_pacific_DST_timestamp(
|
|
497
|
+
self, util
|
|
498
|
+
):
|
|
499
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS_DST})
|
|
500
|
+
table = Table(data)
|
|
501
|
+
|
|
502
|
+
os.environ["TZ"] = "US/Pacific"
|
|
503
|
+
time.tzset()
|
|
504
|
+
|
|
505
|
+
# Should be in PST now
|
|
506
|
+
assert table.view().to_columns()["a"] == [
|
|
507
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
508
|
+
for d in TZ_DATETIMES_DST["US/Pacific"]
|
|
509
|
+
]
|
|
510
|
+
|
|
511
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_central_DST_timestamp(
|
|
512
|
+
self, util
|
|
513
|
+
):
|
|
514
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS_DST})
|
|
515
|
+
table = Table(data)
|
|
516
|
+
|
|
517
|
+
os.environ["TZ"] = "US/Central"
|
|
518
|
+
time.tzset()
|
|
519
|
+
|
|
520
|
+
# Should be in CST now
|
|
521
|
+
assert table.view().to_columns()["a"] == [
|
|
522
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
523
|
+
for d in TZ_DATETIMES_DST["US/Central"]
|
|
524
|
+
]
|
|
525
|
+
|
|
526
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_eastern_DST_timestamp(
|
|
527
|
+
self, util
|
|
528
|
+
):
|
|
529
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS_DST})
|
|
530
|
+
table = Table(data)
|
|
531
|
+
|
|
532
|
+
os.environ["TZ"] = "US/Eastern"
|
|
533
|
+
time.tzset()
|
|
534
|
+
|
|
535
|
+
# Should be in EST now
|
|
536
|
+
assert table.view().to_columns()["a"] == [
|
|
537
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
538
|
+
for d in TZ_DATETIMES_DST["US/Eastern"]
|
|
539
|
+
]
|
|
540
|
+
|
|
541
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_GMT_DST_timestamp(
|
|
542
|
+
self, util
|
|
543
|
+
):
|
|
544
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS_DST})
|
|
545
|
+
table = Table(data)
|
|
546
|
+
|
|
547
|
+
os.environ["TZ"] = "GMT"
|
|
548
|
+
time.tzset()
|
|
549
|
+
|
|
550
|
+
# Should be in GMT now
|
|
551
|
+
assert table.view().to_columns()["a"] == [
|
|
552
|
+
util.to_timestamp(d.replace(tzinfo=None))
|
|
553
|
+
for d in TZ_DATETIMES_DST["GMT"]
|
|
554
|
+
]
|
|
555
|
+
|
|
556
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_HKT(self, util: Util):
|
|
557
|
+
data = {"a": UTC_DATETIMES}
|
|
558
|
+
table = Table(data)
|
|
559
|
+
|
|
560
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
561
|
+
time.tzset()
|
|
562
|
+
|
|
563
|
+
assert table.view().to_columns() == {
|
|
564
|
+
"a": [
|
|
565
|
+
util.to_timestamp(d.astimezone(HKT).replace(tzinfo=None))
|
|
566
|
+
for d in data["a"]
|
|
567
|
+
]
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_JPT(self, util: Util):
|
|
571
|
+
data = {"a": UTC_DATETIMES}
|
|
572
|
+
table = Table(data)
|
|
573
|
+
|
|
574
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
575
|
+
time.tzset()
|
|
576
|
+
|
|
577
|
+
assert table.view().to_columns() == {
|
|
578
|
+
"a": [
|
|
579
|
+
util.to_timestamp(d.astimezone(JPT).replace(tzinfo=None))
|
|
580
|
+
for d in data["a"]
|
|
581
|
+
]
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_ACT(self, util: Util):
|
|
585
|
+
data = {"a": UTC_DATETIMES}
|
|
586
|
+
table = Table(data)
|
|
587
|
+
|
|
588
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
589
|
+
time.tzset()
|
|
590
|
+
|
|
591
|
+
ACT = tz.gettz("Australia/Sydney")
|
|
592
|
+
|
|
593
|
+
assert table.view().to_columns() == {
|
|
594
|
+
"a": [
|
|
595
|
+
util.to_timestamp(d.astimezone(ACT).replace(tzinfo=None))
|
|
596
|
+
for d in data["a"]
|
|
597
|
+
]
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
def test_table_should_convert_UTC_to_local_time_pytz_pacific_timestamp(
|
|
601
|
+
self, util
|
|
602
|
+
):
|
|
603
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
604
|
+
table = Table(data)
|
|
605
|
+
|
|
606
|
+
os.environ["TZ"] = "US/Pacific"
|
|
607
|
+
time.tzset()
|
|
608
|
+
|
|
609
|
+
# Should be in PST now
|
|
610
|
+
assert table.view().to_columns()["a"] == [
|
|
611
|
+
util.to_timestamp(
|
|
612
|
+
d.astimezone(PST).replace(tzinfo=None).to_pydatetime()
|
|
613
|
+
)
|
|
614
|
+
for d in data["a"]
|
|
615
|
+
]
|
|
616
|
+
|
|
617
|
+
def test_table_should_convert_UTC_to_local_time_pytz_central_timestamp(
|
|
618
|
+
self, util
|
|
619
|
+
):
|
|
620
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
621
|
+
table = Table(data)
|
|
622
|
+
|
|
623
|
+
os.environ["TZ"] = "US/Central"
|
|
624
|
+
time.tzset()
|
|
625
|
+
|
|
626
|
+
# Should be in CST now
|
|
627
|
+
assert table.view().to_columns()["a"] == [
|
|
628
|
+
util.to_timestamp(
|
|
629
|
+
d.astimezone(CST).replace(tzinfo=None).to_pydatetime()
|
|
630
|
+
)
|
|
631
|
+
for d in data["a"]
|
|
632
|
+
]
|
|
633
|
+
|
|
634
|
+
def test_table_should_convert_UTC_to_local_time_pytz_eastern_timestamp(
|
|
635
|
+
self, util
|
|
636
|
+
):
|
|
637
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
638
|
+
table = Table(data)
|
|
639
|
+
|
|
640
|
+
os.environ["TZ"] = "US/Eastern"
|
|
641
|
+
time.tzset()
|
|
642
|
+
|
|
643
|
+
# Should be in EST now
|
|
644
|
+
assert table.view().to_columns()["a"] == [
|
|
645
|
+
util.to_timestamp(
|
|
646
|
+
d.astimezone(EST).replace(tzinfo=None).to_pydatetime()
|
|
647
|
+
)
|
|
648
|
+
for d in data["a"]
|
|
649
|
+
]
|
|
650
|
+
|
|
651
|
+
def test_table_should_convert_UTC_to_local_time_pytz_GMT_timestamp(self, util):
|
|
652
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
653
|
+
table = Table(data)
|
|
654
|
+
|
|
655
|
+
os.environ["TZ"] = "GMT"
|
|
656
|
+
time.tzset()
|
|
657
|
+
|
|
658
|
+
# Should be in GMT now
|
|
659
|
+
assert table.view().to_columns()["a"] == [
|
|
660
|
+
util.to_timestamp(
|
|
661
|
+
d.astimezone(GMT).replace(tzinfo=None).to_pydatetime()
|
|
662
|
+
)
|
|
663
|
+
for d in data["a"]
|
|
664
|
+
]
|
|
665
|
+
|
|
666
|
+
def test_table_should_convert_UTC_to_local_time_pytz_HKT_timestamp(self, util):
|
|
667
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
668
|
+
table = Table(data)
|
|
669
|
+
|
|
670
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
671
|
+
time.tzset()
|
|
672
|
+
|
|
673
|
+
assert table.view().to_columns()["a"] == [
|
|
674
|
+
util.to_timestamp(
|
|
675
|
+
d.astimezone(HKT).replace(tzinfo=None).to_pydatetime()
|
|
676
|
+
)
|
|
677
|
+
for d in data["a"]
|
|
678
|
+
]
|
|
679
|
+
|
|
680
|
+
def test_table_should_convert_UTC_to_local_time_pytz_JPT_timestamp(self, util):
|
|
681
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
682
|
+
table = Table(data)
|
|
683
|
+
|
|
684
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
685
|
+
time.tzset()
|
|
686
|
+
|
|
687
|
+
assert table.view().to_columns()["a"] == [
|
|
688
|
+
util.to_timestamp(
|
|
689
|
+
d.astimezone(JPT).replace(tzinfo=None).to_pydatetime()
|
|
690
|
+
)
|
|
691
|
+
for d in data["a"]
|
|
692
|
+
]
|
|
693
|
+
|
|
694
|
+
def test_table_should_convert_UTC_to_local_time_pytz_ACT_timestamp(self, util):
|
|
695
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
696
|
+
table = Table(data)
|
|
697
|
+
|
|
698
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
699
|
+
time.tzset()
|
|
700
|
+
|
|
701
|
+
assert table.view().to_columns()["a"] == [
|
|
702
|
+
util.to_timestamp(
|
|
703
|
+
d.astimezone(ACT).replace(tzinfo=None).to_pydatetime()
|
|
704
|
+
)
|
|
705
|
+
for d in data["a"]
|
|
706
|
+
]
|
|
707
|
+
|
|
708
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_pacific_timestamp(
|
|
709
|
+
self, util
|
|
710
|
+
):
|
|
711
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
712
|
+
table = Table(data)
|
|
713
|
+
|
|
714
|
+
os.environ["TZ"] = "US/Pacific"
|
|
715
|
+
time.tzset()
|
|
716
|
+
|
|
717
|
+
# Should be in PST now
|
|
718
|
+
assert table.view().to_columns()["a"] == [
|
|
719
|
+
util.to_timestamp(
|
|
720
|
+
d.astimezone(PST).replace(tzinfo=None).to_pydatetime()
|
|
721
|
+
)
|
|
722
|
+
for d in data["a"]
|
|
723
|
+
]
|
|
724
|
+
|
|
725
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_central_timestamp(
|
|
726
|
+
self,
|
|
727
|
+
util,
|
|
728
|
+
):
|
|
729
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
730
|
+
table = Table(data)
|
|
731
|
+
|
|
732
|
+
os.environ["TZ"] = "US/Central"
|
|
733
|
+
time.tzset()
|
|
734
|
+
|
|
735
|
+
CST = tz.gettz("US/Central")
|
|
736
|
+
|
|
737
|
+
# Should be in CST now
|
|
738
|
+
assert table.view().to_columns()["a"] == [
|
|
739
|
+
util.to_timestamp(
|
|
740
|
+
d.astimezone(CST).replace(tzinfo=None).to_pydatetime()
|
|
741
|
+
)
|
|
742
|
+
for d in data["a"]
|
|
743
|
+
]
|
|
744
|
+
|
|
745
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_eastern_timestamp(
|
|
746
|
+
self, util
|
|
747
|
+
):
|
|
748
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
749
|
+
table = Table(data)
|
|
750
|
+
|
|
751
|
+
os.environ["TZ"] = "US/Eastern"
|
|
752
|
+
time.tzset()
|
|
753
|
+
|
|
754
|
+
# Should be in EST now
|
|
755
|
+
assert table.view().to_columns()["a"] == [
|
|
756
|
+
util.to_timestamp(
|
|
757
|
+
d.astimezone(EST).replace(tzinfo=None).to_pydatetime()
|
|
758
|
+
)
|
|
759
|
+
for d in data["a"]
|
|
760
|
+
]
|
|
761
|
+
|
|
762
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_GMT_timestamp(
|
|
763
|
+
self, util
|
|
764
|
+
):
|
|
765
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
766
|
+
table = Table(data)
|
|
767
|
+
|
|
768
|
+
os.environ["TZ"] = "GMT"
|
|
769
|
+
time.tzset()
|
|
770
|
+
|
|
771
|
+
GMT = tz.gettz("GMT")
|
|
772
|
+
|
|
773
|
+
# Should be in GMT now
|
|
774
|
+
assert table.view().to_columns()["a"] == [
|
|
775
|
+
util.to_timestamp(
|
|
776
|
+
d.astimezone(GMT).replace(tzinfo=None).to_pydatetime()
|
|
777
|
+
)
|
|
778
|
+
for d in data["a"]
|
|
779
|
+
]
|
|
780
|
+
|
|
781
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_HKT_timestamp(
|
|
782
|
+
self, util
|
|
783
|
+
):
|
|
784
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
785
|
+
table = Table(data)
|
|
786
|
+
|
|
787
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
788
|
+
time.tzset()
|
|
789
|
+
|
|
790
|
+
assert table.view().to_columns()["a"] == [
|
|
791
|
+
util.to_timestamp(
|
|
792
|
+
d.astimezone(HKT).replace(tzinfo=None).to_pydatetime()
|
|
793
|
+
)
|
|
794
|
+
for d in data["a"]
|
|
795
|
+
]
|
|
796
|
+
|
|
797
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_JPT_timestamp(
|
|
798
|
+
self, util
|
|
799
|
+
):
|
|
800
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
801
|
+
table = Table(data)
|
|
802
|
+
|
|
803
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
804
|
+
time.tzset()
|
|
805
|
+
|
|
806
|
+
assert table.view().to_columns()["a"] == [
|
|
807
|
+
util.to_timestamp(
|
|
808
|
+
d.astimezone(JPT).replace(tzinfo=None).to_pydatetime()
|
|
809
|
+
)
|
|
810
|
+
for d in data["a"]
|
|
811
|
+
]
|
|
812
|
+
|
|
813
|
+
def test_table_should_convert_UTC_to_local_time_dateutil_ACT_timestamp(
|
|
814
|
+
self, util
|
|
815
|
+
):
|
|
816
|
+
data = pd.DataFrame({"a": UTC_TIMESTAMPS})
|
|
817
|
+
table = Table(data)
|
|
818
|
+
|
|
819
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
820
|
+
time.tzset()
|
|
821
|
+
|
|
822
|
+
assert table.view().to_columns()["a"] == [
|
|
823
|
+
util.to_timestamp(
|
|
824
|
+
d.astimezone(ACT).replace(tzinfo=None).to_pydatetime()
|
|
825
|
+
)
|
|
826
|
+
for d in data["a"]
|
|
827
|
+
]
|
|
828
|
+
|
|
829
|
+
class TestTableDateTimeArbitaryToLocal(object):
|
|
830
|
+
def teardown_method(self):
|
|
831
|
+
# Set timezone to UTC, always
|
|
832
|
+
os.environ["TZ"] = "UTC"
|
|
833
|
+
time.tzset()
|
|
834
|
+
|
|
835
|
+
def test_table_should_convert_PST_to_local_time_pytz_central(self, util: Util):
|
|
836
|
+
data = {"a": TZ_DATETIMES["US/Pacific"]}
|
|
837
|
+
table = Table(data)
|
|
838
|
+
|
|
839
|
+
os.environ["TZ"] = "US/Central"
|
|
840
|
+
time.tzset()
|
|
841
|
+
|
|
842
|
+
# Should be in CST now
|
|
843
|
+
assert table.view().to_columns() == {
|
|
844
|
+
"a": [
|
|
845
|
+
util.to_timestamp(d.astimezone(CST).replace(tzinfo=None))
|
|
846
|
+
for d in data["a"]
|
|
847
|
+
]
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
def test_table_should_convert_CST_to_local_time_pytz_eastern(self, util: Util):
|
|
851
|
+
data = {"a": TZ_DATETIMES["US/Central"]}
|
|
852
|
+
table = Table(data)
|
|
853
|
+
|
|
854
|
+
os.environ["TZ"] = "US/Eastern"
|
|
855
|
+
time.tzset()
|
|
856
|
+
|
|
857
|
+
# Should be in EST now
|
|
858
|
+
assert table.view().to_columns() == {
|
|
859
|
+
"a": [
|
|
860
|
+
util.to_timestamp(d.astimezone(EST).replace(tzinfo=None))
|
|
861
|
+
for d in data["a"]
|
|
862
|
+
]
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
def test_table_should_convert_EST_to_local_time_pytz_GMT(self, util: Util):
|
|
866
|
+
data = {"a": TZ_DATETIMES["US/Eastern"]}
|
|
867
|
+
table = Table(data)
|
|
868
|
+
|
|
869
|
+
os.environ["TZ"] = "GMT"
|
|
870
|
+
time.tzset()
|
|
871
|
+
|
|
872
|
+
# Should be in GMT now
|
|
873
|
+
assert table.view().to_columns() == {
|
|
874
|
+
"a": [
|
|
875
|
+
util.to_timestamp(d.astimezone(GMT).replace(tzinfo=None))
|
|
876
|
+
for d in data["a"]
|
|
877
|
+
]
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
def test_table_should_convert_GMT_to_local_time_pytz_HKT(self, util: Util):
|
|
881
|
+
data = {"a": TZ_DATETIMES["GMT"]}
|
|
882
|
+
table = Table(data)
|
|
883
|
+
|
|
884
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
885
|
+
time.tzset()
|
|
886
|
+
|
|
887
|
+
assert table.view().to_columns() == {
|
|
888
|
+
"a": [
|
|
889
|
+
util.to_timestamp(d.astimezone(HKT).replace(tzinfo=None))
|
|
890
|
+
for d in data["a"]
|
|
891
|
+
]
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
def test_table_should_convert_HKT_to_local_time_pytz_JPT(self, util: Util):
|
|
895
|
+
data = {"a": TZ_DATETIMES["Asia/Hong_Kong"]}
|
|
896
|
+
table = Table(data)
|
|
897
|
+
|
|
898
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
899
|
+
time.tzset()
|
|
900
|
+
|
|
901
|
+
assert table.view().to_columns() == {
|
|
902
|
+
"a": [
|
|
903
|
+
util.to_timestamp(d.astimezone(JPT).replace(tzinfo=None))
|
|
904
|
+
for d in data["a"]
|
|
905
|
+
]
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
def test_table_should_convert_JPT_to_local_time_pytz_ACT(self, util: Util):
|
|
909
|
+
data = {"a": TZ_DATETIMES["Asia/Tokyo"]}
|
|
910
|
+
table = Table(data)
|
|
911
|
+
|
|
912
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
913
|
+
time.tzset()
|
|
914
|
+
|
|
915
|
+
assert table.view().to_columns() == {
|
|
916
|
+
"a": [
|
|
917
|
+
util.to_timestamp(d.astimezone(ACT).replace(tzinfo=None))
|
|
918
|
+
for d in data["a"]
|
|
919
|
+
]
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
def test_table_should_convert_PST_to_local_time_dateutil_central(
|
|
923
|
+
self, util: Util
|
|
924
|
+
):
|
|
925
|
+
data = {"a": TZ_DATETIMES["US/Pacific"]}
|
|
926
|
+
table = Table(data)
|
|
927
|
+
|
|
928
|
+
os.environ["TZ"] = "US/Central"
|
|
929
|
+
time.tzset()
|
|
930
|
+
|
|
931
|
+
# Should be in CST now
|
|
932
|
+
assert table.view().to_columns() == {
|
|
933
|
+
"a": [
|
|
934
|
+
util.to_timestamp(d.astimezone(CST).replace(tzinfo=None))
|
|
935
|
+
for d in data["a"]
|
|
936
|
+
]
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
def test_table_should_convert_CST_to_local_time_dateutil_eastern(
|
|
940
|
+
self, util: Util
|
|
941
|
+
):
|
|
942
|
+
data = {"a": TZ_DATETIMES["US/Central"]}
|
|
943
|
+
table = Table(data)
|
|
944
|
+
|
|
945
|
+
os.environ["TZ"] = "US/Eastern"
|
|
946
|
+
time.tzset()
|
|
947
|
+
|
|
948
|
+
# Should be in EST now
|
|
949
|
+
assert table.view().to_columns() == {
|
|
950
|
+
"a": [
|
|
951
|
+
util.to_timestamp(d.astimezone(EST).replace(tzinfo=None))
|
|
952
|
+
for d in data["a"]
|
|
953
|
+
]
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
def test_table_should_convert_EST_to_local_time_dateutil_GMT(self, util: Util):
|
|
957
|
+
data = {"a": TZ_DATETIMES["US/Eastern"]}
|
|
958
|
+
table = Table(data)
|
|
959
|
+
|
|
960
|
+
os.environ["TZ"] = "GMT"
|
|
961
|
+
time.tzset()
|
|
962
|
+
|
|
963
|
+
# Should be in GMT now
|
|
964
|
+
assert table.view().to_columns() == {
|
|
965
|
+
"a": [
|
|
966
|
+
util.to_timestamp(d.astimezone(GMT).replace(tzinfo=None))
|
|
967
|
+
for d in data["a"]
|
|
968
|
+
]
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
def test_table_should_convert_GMT_to_local_time_dateutil_HKT(self, util: Util):
|
|
972
|
+
data = {"a": TZ_DATETIMES["GMT"]}
|
|
973
|
+
table = Table(data)
|
|
974
|
+
|
|
975
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
976
|
+
time.tzset()
|
|
977
|
+
|
|
978
|
+
assert table.view().to_columns() == {
|
|
979
|
+
"a": [
|
|
980
|
+
util.to_timestamp(d.astimezone(HKT).replace(tzinfo=None))
|
|
981
|
+
for d in data["a"]
|
|
982
|
+
]
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
def test_table_should_convert_HKT_to_local_time_dateutil_JPT(self, util: Util):
|
|
986
|
+
data = {"a": TZ_DATETIMES["Asia/Hong_Kong"]}
|
|
987
|
+
table = Table(data)
|
|
988
|
+
|
|
989
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
990
|
+
time.tzset()
|
|
991
|
+
|
|
992
|
+
assert table.view().to_columns() == {
|
|
993
|
+
"a": [
|
|
994
|
+
util.to_timestamp(d.astimezone(JPT).replace(tzinfo=None))
|
|
995
|
+
for d in data["a"]
|
|
996
|
+
]
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
def test_table_should_convert_JPT_to_local_time_dateutil_ACT(self, util: Util):
|
|
1000
|
+
data = {"a": TZ_DATETIMES["Asia/Tokyo"]}
|
|
1001
|
+
table = Table(data)
|
|
1002
|
+
|
|
1003
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
1004
|
+
time.tzset()
|
|
1005
|
+
|
|
1006
|
+
assert table.view().to_columns() == {
|
|
1007
|
+
"a": [
|
|
1008
|
+
util.to_timestamp(d.astimezone(ACT).replace(tzinfo=None))
|
|
1009
|
+
for d in data["a"]
|
|
1010
|
+
]
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
def test_table_should_convert_PST_to_local_time_pytz_central_timestamp(
|
|
1014
|
+
self, util: Util
|
|
1015
|
+
):
|
|
1016
|
+
data = {"a": TZ_TIMESTAMPS["US/Pacific"]}
|
|
1017
|
+
table = Table(pd.DataFrame(data))
|
|
1018
|
+
|
|
1019
|
+
os.environ["TZ"] = "US/Central"
|
|
1020
|
+
time.tzset()
|
|
1021
|
+
|
|
1022
|
+
# Should be in CST now
|
|
1023
|
+
assert table.view().to_columns()["a"] == [
|
|
1024
|
+
util.to_timestamp(
|
|
1025
|
+
d.astimezone(CST).replace(tzinfo=None).to_pydatetime()
|
|
1026
|
+
)
|
|
1027
|
+
for d in data["a"]
|
|
1028
|
+
]
|
|
1029
|
+
|
|
1030
|
+
def test_table_should_convert_CST_to_local_time_pytz_eastern_timestamp(
|
|
1031
|
+
self, util
|
|
1032
|
+
):
|
|
1033
|
+
data = {"a": TZ_TIMESTAMPS["US/Central"]}
|
|
1034
|
+
table = Table(pd.DataFrame(data))
|
|
1035
|
+
|
|
1036
|
+
os.environ["TZ"] = "US/Eastern"
|
|
1037
|
+
time.tzset()
|
|
1038
|
+
|
|
1039
|
+
# Should be in EST now
|
|
1040
|
+
assert table.view().to_columns()["a"] == [
|
|
1041
|
+
util.to_timestamp(
|
|
1042
|
+
d.astimezone(EST).replace(tzinfo=None).to_pydatetime()
|
|
1043
|
+
)
|
|
1044
|
+
for d in data["a"]
|
|
1045
|
+
]
|
|
1046
|
+
|
|
1047
|
+
def test_table_should_convert_EST_to_local_time_pytz_GMT_timestamp(self, util):
|
|
1048
|
+
data = {"a": TZ_TIMESTAMPS["US/Eastern"]}
|
|
1049
|
+
table = Table(pd.DataFrame(data))
|
|
1050
|
+
|
|
1051
|
+
os.environ["TZ"] = "GMT"
|
|
1052
|
+
time.tzset()
|
|
1053
|
+
|
|
1054
|
+
# Should be in GMT now
|
|
1055
|
+
assert table.view().to_columns()["a"] == [
|
|
1056
|
+
util.to_timestamp(
|
|
1057
|
+
d.astimezone(GMT).replace(tzinfo=None).to_pydatetime()
|
|
1058
|
+
)
|
|
1059
|
+
for d in data["a"]
|
|
1060
|
+
]
|
|
1061
|
+
|
|
1062
|
+
def test_table_should_convert_GMT_to_local_time_pytz_HKT_timestamp(self, util):
|
|
1063
|
+
data = {"a": TZ_TIMESTAMPS["GMT"]}
|
|
1064
|
+
table = Table(pd.DataFrame(data))
|
|
1065
|
+
|
|
1066
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
1067
|
+
time.tzset()
|
|
1068
|
+
|
|
1069
|
+
assert table.view().to_columns()["a"] == [
|
|
1070
|
+
util.to_timestamp(
|
|
1071
|
+
d.astimezone(HKT).replace(tzinfo=None).to_pydatetime()
|
|
1072
|
+
)
|
|
1073
|
+
for d in data["a"]
|
|
1074
|
+
]
|
|
1075
|
+
|
|
1076
|
+
def test_table_should_convert_HKT_to_local_time_pytz_JPT_timestamp(self, util):
|
|
1077
|
+
data = {"a": TZ_TIMESTAMPS["Asia/Hong_Kong"]}
|
|
1078
|
+
table = Table(pd.DataFrame(data))
|
|
1079
|
+
|
|
1080
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
1081
|
+
time.tzset()
|
|
1082
|
+
|
|
1083
|
+
assert table.view().to_columns()["a"] == [
|
|
1084
|
+
util.to_timestamp(
|
|
1085
|
+
d.astimezone(JPT).replace(tzinfo=None).to_pydatetime()
|
|
1086
|
+
)
|
|
1087
|
+
for d in data["a"]
|
|
1088
|
+
]
|
|
1089
|
+
|
|
1090
|
+
def test_table_should_convert_JPT_to_local_time_pytz_ACT_timestamp(self, util):
|
|
1091
|
+
data = {"a": TZ_TIMESTAMPS["Asia/Tokyo"]}
|
|
1092
|
+
table = Table(pd.DataFrame(data))
|
|
1093
|
+
|
|
1094
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
1095
|
+
time.tzset()
|
|
1096
|
+
|
|
1097
|
+
assert table.view().to_columns()["a"] == [
|
|
1098
|
+
util.to_timestamp(
|
|
1099
|
+
d.astimezone(ACT).replace(tzinfo=None).to_pydatetime()
|
|
1100
|
+
)
|
|
1101
|
+
for d in data["a"]
|
|
1102
|
+
]
|
|
1103
|
+
|
|
1104
|
+
def test_table_should_convert_PST_to_local_time_dateutil_central_timestamp(
|
|
1105
|
+
self, util
|
|
1106
|
+
):
|
|
1107
|
+
data = {"a": TZ_TIMESTAMPS["US/Pacific"]}
|
|
1108
|
+
table = Table(pd.DataFrame(data))
|
|
1109
|
+
|
|
1110
|
+
os.environ["TZ"] = "US/Central"
|
|
1111
|
+
time.tzset()
|
|
1112
|
+
|
|
1113
|
+
# Should be in CST now
|
|
1114
|
+
assert table.view().to_columns()["a"] == [
|
|
1115
|
+
util.to_timestamp(
|
|
1116
|
+
d.astimezone(CST).replace(tzinfo=None).to_pydatetime()
|
|
1117
|
+
)
|
|
1118
|
+
for d in data["a"]
|
|
1119
|
+
]
|
|
1120
|
+
|
|
1121
|
+
def test_table_should_convert_CST_to_local_time_dateutil_eastern_timestamp(
|
|
1122
|
+
self, util
|
|
1123
|
+
):
|
|
1124
|
+
data = {"a": TZ_TIMESTAMPS["US/Central"]}
|
|
1125
|
+
table = Table(pd.DataFrame(data))
|
|
1126
|
+
|
|
1127
|
+
os.environ["TZ"] = "US/Eastern"
|
|
1128
|
+
time.tzset()
|
|
1129
|
+
|
|
1130
|
+
# Should be in EST now
|
|
1131
|
+
assert table.view().to_columns()["a"] == [
|
|
1132
|
+
util.to_timestamp(
|
|
1133
|
+
d.astimezone(EST).replace(tzinfo=None).to_pydatetime()
|
|
1134
|
+
)
|
|
1135
|
+
for d in data["a"]
|
|
1136
|
+
]
|
|
1137
|
+
|
|
1138
|
+
def test_table_should_convert_EST_to_local_time_dateutil_GMT_timestamp(
|
|
1139
|
+
self, util
|
|
1140
|
+
):
|
|
1141
|
+
data = {"a": TZ_TIMESTAMPS["US/Eastern"]}
|
|
1142
|
+
table = Table(pd.DataFrame(data))
|
|
1143
|
+
|
|
1144
|
+
os.environ["TZ"] = "GMT"
|
|
1145
|
+
time.tzset()
|
|
1146
|
+
|
|
1147
|
+
# Should be in GMT now
|
|
1148
|
+
assert table.view().to_columns()["a"] == [
|
|
1149
|
+
util.to_timestamp(
|
|
1150
|
+
d.astimezone(GMT).replace(tzinfo=None).to_pydatetime()
|
|
1151
|
+
)
|
|
1152
|
+
for d in data["a"]
|
|
1153
|
+
]
|
|
1154
|
+
|
|
1155
|
+
def test_table_should_convert_GMT_to_local_time_dateutil_HKT_timestamp(
|
|
1156
|
+
self, util
|
|
1157
|
+
):
|
|
1158
|
+
data = {"a": TZ_TIMESTAMPS["GMT"]}
|
|
1159
|
+
table = Table(pd.DataFrame(data))
|
|
1160
|
+
|
|
1161
|
+
os.environ["TZ"] = "Asia/Hong_Kong"
|
|
1162
|
+
time.tzset()
|
|
1163
|
+
|
|
1164
|
+
assert table.view().to_columns()["a"] == [
|
|
1165
|
+
util.to_timestamp(
|
|
1166
|
+
d.astimezone(HKT).replace(tzinfo=None).to_pydatetime()
|
|
1167
|
+
)
|
|
1168
|
+
for d in data["a"]
|
|
1169
|
+
]
|
|
1170
|
+
|
|
1171
|
+
def test_table_should_convert_HKT_to_local_time_dateutil_JPT_timestamp(
|
|
1172
|
+
self, util
|
|
1173
|
+
):
|
|
1174
|
+
data = {"a": TZ_TIMESTAMPS["Asia/Hong_Kong"]}
|
|
1175
|
+
table = Table(pd.DataFrame(data))
|
|
1176
|
+
|
|
1177
|
+
os.environ["TZ"] = "Asia/Tokyo"
|
|
1178
|
+
time.tzset()
|
|
1179
|
+
|
|
1180
|
+
assert table.view().to_columns()["a"] == [
|
|
1181
|
+
util.to_timestamp(
|
|
1182
|
+
d.astimezone(JPT).replace(tzinfo=None).to_pydatetime()
|
|
1183
|
+
)
|
|
1184
|
+
for d in data["a"]
|
|
1185
|
+
]
|
|
1186
|
+
|
|
1187
|
+
def test_table_should_convert_JPT_to_local_time_dateutil_ACT_timestamp(
|
|
1188
|
+
self, util
|
|
1189
|
+
):
|
|
1190
|
+
data = {"a": TZ_TIMESTAMPS["Asia/Tokyo"]}
|
|
1191
|
+
table = Table(pd.DataFrame(data))
|
|
1192
|
+
|
|
1193
|
+
os.environ["TZ"] = "Australia/Sydney"
|
|
1194
|
+
time.tzset()
|
|
1195
|
+
|
|
1196
|
+
assert table.view().to_columns()["a"] == [
|
|
1197
|
+
util.to_timestamp(
|
|
1198
|
+
d.astimezone(ACT).replace(tzinfo=None).to_pydatetime()
|
|
1199
|
+
)
|
|
1200
|
+
for d in data["a"]
|
|
1201
|
+
]
|
|
1202
|
+
|
|
1203
|
+
class TestTableDateTimeRowColumnPaths(object):
|
|
1204
|
+
"""Assert correctness of row and column paths in different timezones."""
|
|
1205
|
+
|
|
1206
|
+
def setup_method(self):
|
|
1207
|
+
# To make sure that local times are not changed, set timezone to EST
|
|
1208
|
+
os.environ["TZ"] = "US/Eastern"
|
|
1209
|
+
time.tzset()
|
|
1210
|
+
|
|
1211
|
+
def teardown_method(self):
|
|
1212
|
+
# Set timezone to UTC, always
|
|
1213
|
+
os.environ["TZ"] = "UTC"
|
|
1214
|
+
time.tzset()
|
|
1215
|
+
|
|
1216
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1217
|
+
def test_table_group_by_datetime_row_path_local_time_EST(self, util: Util):
|
|
1218
|
+
"""Make sure that string datetimes generated in Python are in
|
|
1219
|
+
local time and not UTC."""
|
|
1220
|
+
data = {"a": LOCAL_DATETIMES, "b": [i for i in range(len(LOCAL_DATETIMES))]}
|
|
1221
|
+
|
|
1222
|
+
table = Table(data)
|
|
1223
|
+
|
|
1224
|
+
view = table.view(group_by=["a"])
|
|
1225
|
+
assert view.to_columns() == {
|
|
1226
|
+
"__ROW_PATH__": [
|
|
1227
|
+
[],
|
|
1228
|
+
[util.to_timestamp(datetime(2019, 1, 11, 0, 10, 20))],
|
|
1229
|
+
[util.to_timestamp(datetime(2019, 1, 11, 11, 10, 20))],
|
|
1230
|
+
[util.to_timestamp(datetime(2019, 1, 11, 19, 10, 20))],
|
|
1231
|
+
],
|
|
1232
|
+
"a": [3, 1, 1, 1],
|
|
1233
|
+
"b": [3, 0, 1, 2],
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
def test_table_group_by_datetime_row_path_UTC(self, util: Util):
|
|
1237
|
+
"""Make sure that string datetimes generated in Python are in
|
|
1238
|
+
UTC if the timezone is UTC.
|
|
1239
|
+
|
|
1240
|
+
Set the timezone before creating the table so that the local
|
|
1241
|
+
datetime is in the intended timezone, as this test asserts that
|
|
1242
|
+
paths in the same timezone are not edited to UTC."""
|
|
1243
|
+
os.environ["TZ"] = "UTC"
|
|
1244
|
+
time.tzset()
|
|
1245
|
+
|
|
1246
|
+
data = {"a": LOCAL_DATETIMES, "b": [i for i in range(len(LOCAL_DATETIMES))]}
|
|
1247
|
+
|
|
1248
|
+
table = Table(data)
|
|
1249
|
+
|
|
1250
|
+
view = table.view(group_by=["a"])
|
|
1251
|
+
assert view.to_columns() == {
|
|
1252
|
+
"__ROW_PATH__": [
|
|
1253
|
+
[],
|
|
1254
|
+
[util.to_timestamp(datetime(2019, 1, 11, 0, 10, 20))],
|
|
1255
|
+
[util.to_timestamp(datetime(2019, 1, 11, 11, 10, 20))],
|
|
1256
|
+
[util.to_timestamp(datetime(2019, 1, 11, 19, 10, 20))],
|
|
1257
|
+
],
|
|
1258
|
+
"a": [3, 1, 1, 1],
|
|
1259
|
+
"b": [3, 0, 1, 2],
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1263
|
+
def test_table_group_by_datetime_row_path_CST(self):
|
|
1264
|
+
"""Make sure that string datetimes generated in Python are in
|
|
1265
|
+
CST if the timezone is CST."""
|
|
1266
|
+
os.environ["TZ"] = "US/Central"
|
|
1267
|
+
time.tzset()
|
|
1268
|
+
|
|
1269
|
+
data = {"a": LOCAL_DATETIMES, "b": [i for i in range(len(LOCAL_DATETIMES))]}
|
|
1270
|
+
|
|
1271
|
+
table = Table(data)
|
|
1272
|
+
|
|
1273
|
+
view = table.view(group_by=["a"])
|
|
1274
|
+
assert view.to_columns() == {
|
|
1275
|
+
"__ROW_PATH__": [
|
|
1276
|
+
[],
|
|
1277
|
+
[datetime(2019, 1, 11, 0, 10, 20)],
|
|
1278
|
+
[datetime(2019, 1, 11, 11, 10, 20)],
|
|
1279
|
+
[datetime(2019, 1, 11, 19, 10, 20)],
|
|
1280
|
+
],
|
|
1281
|
+
"a": [3, 1, 1, 1],
|
|
1282
|
+
"b": [3, 0, 1, 2],
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1286
|
+
def test_table_group_by_datetime_row_path_PST(self):
|
|
1287
|
+
"""Make sure that string datetimes generated in Python are in
|
|
1288
|
+
CST if the timezone is CST."""
|
|
1289
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1290
|
+
time.tzset()
|
|
1291
|
+
|
|
1292
|
+
data = {"a": LOCAL_DATETIMES, "b": [i for i in range(len(LOCAL_DATETIMES))]}
|
|
1293
|
+
|
|
1294
|
+
table = Table(data)
|
|
1295
|
+
|
|
1296
|
+
view = table.view(group_by=["a"])
|
|
1297
|
+
assert view.to_columns() == {
|
|
1298
|
+
"__ROW_PATH__": [
|
|
1299
|
+
[],
|
|
1300
|
+
[datetime(2019, 1, 11, 0, 10, 20)],
|
|
1301
|
+
[datetime(2019, 1, 11, 11, 10, 20)],
|
|
1302
|
+
[datetime(2019, 1, 11, 19, 10, 20)],
|
|
1303
|
+
],
|
|
1304
|
+
"a": [3, 1, 1, 1],
|
|
1305
|
+
"b": [3, 0, 1, 2],
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
class TestTableDateTimeExpressions(object):
|
|
1309
|
+
"""Assert correctness of datetime-related expressions in
|
|
1310
|
+
different timezones."""
|
|
1311
|
+
|
|
1312
|
+
def setup_method(self):
|
|
1313
|
+
# To make sure that local times are not changed, set timezone to EST
|
|
1314
|
+
os.environ["TZ"] = "US/Eastern"
|
|
1315
|
+
time.tzset()
|
|
1316
|
+
|
|
1317
|
+
def teardown_method(self):
|
|
1318
|
+
# Set timezone to UTC, always
|
|
1319
|
+
os.environ["TZ"] = "UTC"
|
|
1320
|
+
time.tzset()
|
|
1321
|
+
|
|
1322
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1323
|
+
def test_table_now_in_EST(self, util):
|
|
1324
|
+
data = {"a": LOCAL_DATETIMES}
|
|
1325
|
+
|
|
1326
|
+
table = Table(data)
|
|
1327
|
+
now = datetime.now()
|
|
1328
|
+
view = table.view(expressions=["now()"])
|
|
1329
|
+
result = view.to_columns()
|
|
1330
|
+
|
|
1331
|
+
for item in result["now()"]:
|
|
1332
|
+
in_range = (
|
|
1333
|
+
now - timedelta(seconds=2) < item < now + timedelta(seconds=2)
|
|
1334
|
+
)
|
|
1335
|
+
assert in_range is True
|
|
1336
|
+
|
|
1337
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1338
|
+
def test_table_now_in_CST(self, util):
|
|
1339
|
+
os.environ["TZ"] = "US/Central"
|
|
1340
|
+
time.tzset()
|
|
1341
|
+
|
|
1342
|
+
data = {"a": LOCAL_DATETIMES}
|
|
1343
|
+
|
|
1344
|
+
table = Table(data)
|
|
1345
|
+
now = datetime.now()
|
|
1346
|
+
view = table.view(expressions=["now()"])
|
|
1347
|
+
result = view.to_columns()
|
|
1348
|
+
|
|
1349
|
+
for item in result["now()"]:
|
|
1350
|
+
in_range = (
|
|
1351
|
+
now - timedelta(seconds=2) < item < now + timedelta(seconds=2)
|
|
1352
|
+
)
|
|
1353
|
+
assert in_range is True
|
|
1354
|
+
|
|
1355
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1356
|
+
def test_table_now_in_PST(self, util):
|
|
1357
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1358
|
+
time.tzset()
|
|
1359
|
+
|
|
1360
|
+
data = {"a": LOCAL_DATETIMES}
|
|
1361
|
+
|
|
1362
|
+
table = Table(data)
|
|
1363
|
+
now = datetime.now()
|
|
1364
|
+
view = table.view(expressions=["now()"])
|
|
1365
|
+
result = view.to_columns()
|
|
1366
|
+
|
|
1367
|
+
for item in result["now()"]:
|
|
1368
|
+
in_range = (
|
|
1369
|
+
now - timedelta(seconds=2) < item < now + timedelta(seconds=2)
|
|
1370
|
+
)
|
|
1371
|
+
assert in_range is True
|
|
1372
|
+
|
|
1373
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1374
|
+
def test_table_hour_of_day_in_EST(self):
|
|
1375
|
+
data = {"a": LOCAL_DATETIMES}
|
|
1376
|
+
|
|
1377
|
+
table = Table(data)
|
|
1378
|
+
view = table.view(expressions=['hour_of_day("a")'])
|
|
1379
|
+
result = view.to_columns()
|
|
1380
|
+
assert result['hour_of_day("a")'] == [0, 11, 19]
|
|
1381
|
+
|
|
1382
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1383
|
+
def test_table_hour_of_day_in_CST(self):
|
|
1384
|
+
os.environ["TZ"] = "US/Central"
|
|
1385
|
+
time.tzset()
|
|
1386
|
+
|
|
1387
|
+
data = {"a": LOCAL_DATETIMES}
|
|
1388
|
+
|
|
1389
|
+
table = Table(data)
|
|
1390
|
+
view = table.view(expressions=['hour_of_day("a")'])
|
|
1391
|
+
result = view.to_columns()
|
|
1392
|
+
assert result['hour_of_day("a")'] == [0, 11, 19]
|
|
1393
|
+
|
|
1394
|
+
@mark.skip(reason="Unsupported non-UTC timezone")
|
|
1395
|
+
def test_table_hour_of_day_in_PST(self):
|
|
1396
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1397
|
+
time.tzset()
|
|
1398
|
+
|
|
1399
|
+
data = {"a": LOCAL_DATETIMES}
|
|
1400
|
+
|
|
1401
|
+
table = Table(data)
|
|
1402
|
+
view = table.view(expressions=['hour_of_day("a")'])
|
|
1403
|
+
result = view.to_columns()
|
|
1404
|
+
assert result['hour_of_day("a")'] == [0, 11, 19]
|
|
1405
|
+
|
|
1406
|
+
def test_table_day_of_week_edge_in_EST(self):
|
|
1407
|
+
"""Make sure edge cases are fixed for day of week - if a local
|
|
1408
|
+
time converted to UTC is in the next day, the day of week
|
|
1409
|
+
computation needs to be in local time."""
|
|
1410
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1411
|
+
|
|
1412
|
+
table = Table(data)
|
|
1413
|
+
view = table.view(expressions=['day_of_week("a")'])
|
|
1414
|
+
result = view.to_columns()
|
|
1415
|
+
assert result['day_of_week("a")'] == ["6 Friday"]
|
|
1416
|
+
|
|
1417
|
+
def test_table_day_of_week_edge_in_CST(self):
|
|
1418
|
+
os.environ["TZ"] = "US/Central"
|
|
1419
|
+
time.tzset()
|
|
1420
|
+
|
|
1421
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1422
|
+
|
|
1423
|
+
table = Table(data)
|
|
1424
|
+
view = table.view(expressions=['day_of_week("a")'])
|
|
1425
|
+
result = view.to_columns()
|
|
1426
|
+
assert result['day_of_week("a")'] == ["6 Friday"]
|
|
1427
|
+
|
|
1428
|
+
def test_table_day_of_week_edge_in_PST(self):
|
|
1429
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1430
|
+
time.tzset()
|
|
1431
|
+
|
|
1432
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1433
|
+
|
|
1434
|
+
table = Table(data)
|
|
1435
|
+
view = table.view(expressions=['day_of_week("a")'])
|
|
1436
|
+
result = view.to_columns()
|
|
1437
|
+
assert result['day_of_week("a")'] == ["6 Friday"]
|
|
1438
|
+
|
|
1439
|
+
def test_table_month_of_year_edge_in_EST(self):
|
|
1440
|
+
"""Make sure edge cases are fixed for month of year - if a local
|
|
1441
|
+
time converted to UTC is in the next month, the month of year
|
|
1442
|
+
computation needs to be in local time."""
|
|
1443
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1444
|
+
|
|
1445
|
+
table = Table(data)
|
|
1446
|
+
view = table.view(expressions=['month_of_year("a")'])
|
|
1447
|
+
result = view.to_columns()
|
|
1448
|
+
assert result['month_of_year("a")'] == ["01 January"]
|
|
1449
|
+
|
|
1450
|
+
def test_table_month_of_year_edge_in_CST(self):
|
|
1451
|
+
os.environ["TZ"] = "US/Central"
|
|
1452
|
+
time.tzset()
|
|
1453
|
+
|
|
1454
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1455
|
+
|
|
1456
|
+
table = Table(data)
|
|
1457
|
+
view = table.view(expressions=['month_of_year("a")'])
|
|
1458
|
+
result = view.to_columns()
|
|
1459
|
+
assert result['month_of_year("a")'] == ["01 January"]
|
|
1460
|
+
|
|
1461
|
+
def test_table_month_of_year_edge_in_PST(self):
|
|
1462
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1463
|
+
time.tzset()
|
|
1464
|
+
|
|
1465
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1466
|
+
|
|
1467
|
+
table = Table(data)
|
|
1468
|
+
view = table.view(expressions=['month_of_year("a")'])
|
|
1469
|
+
result = view.to_columns()
|
|
1470
|
+
assert result['month_of_year("a")'] == ["01 January"]
|
|
1471
|
+
|
|
1472
|
+
def test_table_day_bucket_edge_in_EST(self, util):
|
|
1473
|
+
"""Make sure edge cases are fixed for day_bucket - if a local
|
|
1474
|
+
time converted to UTC is in the next day, the day_bucket
|
|
1475
|
+
computation needs to be in local time."""
|
|
1476
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1477
|
+
|
|
1478
|
+
table = Table(data)
|
|
1479
|
+
view = table.view(expressions=["bucket(\"a\", 'D')"])
|
|
1480
|
+
result = view.to_columns()
|
|
1481
|
+
assert result["bucket(\"a\", 'D')"] == [
|
|
1482
|
+
util.to_timestamp(datetime(2020, 1, 31))
|
|
1483
|
+
]
|
|
1484
|
+
|
|
1485
|
+
def test_table_day_bucket_edge_in_CST(self, util):
|
|
1486
|
+
os.environ["TZ"] = "US/Central"
|
|
1487
|
+
time.tzset()
|
|
1488
|
+
|
|
1489
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1490
|
+
|
|
1491
|
+
table = Table(data)
|
|
1492
|
+
view = table.view(expressions=["bucket(\"a\", 'D')"])
|
|
1493
|
+
result = view.to_columns()
|
|
1494
|
+
assert result["bucket(\"a\", 'D')"] == [
|
|
1495
|
+
util.to_timestamp(datetime(2020, 1, 31))
|
|
1496
|
+
]
|
|
1497
|
+
|
|
1498
|
+
def test_table_day_bucket_edge_in_PST(self, util):
|
|
1499
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1500
|
+
time.tzset()
|
|
1501
|
+
|
|
1502
|
+
data = {"a": [datetime(2020, 1, 31, 23, 59)]}
|
|
1503
|
+
|
|
1504
|
+
table = Table(data)
|
|
1505
|
+
view = table.view(expressions=["bucket(\"a\", 'D')"])
|
|
1506
|
+
result = view.to_columns()
|
|
1507
|
+
assert result["bucket(\"a\", 'D')"] == [
|
|
1508
|
+
util.to_timestamp(datetime(2020, 1, 31))
|
|
1509
|
+
]
|
|
1510
|
+
|
|
1511
|
+
def test_table_week_bucket_edge_in_EST(self, util):
|
|
1512
|
+
"""Make sure edge cases are fixed for week_bucket - if a local
|
|
1513
|
+
time converted to UTC is in the next day, the week_bucket
|
|
1514
|
+
computation needs to be in local time."""
|
|
1515
|
+
data = {"a": [datetime(2020, 2, 2, 23, 59)]}
|
|
1516
|
+
|
|
1517
|
+
table = Table(data)
|
|
1518
|
+
view = table.view(expressions=["bucket(\"a\", 'W')"])
|
|
1519
|
+
result = view.to_columns()
|
|
1520
|
+
assert result["bucket(\"a\", 'W')"] == [
|
|
1521
|
+
util.to_timestamp(datetime(2020, 1, 27))
|
|
1522
|
+
]
|
|
1523
|
+
|
|
1524
|
+
def test_table_week_bucket_edge_in_CST(self, util):
|
|
1525
|
+
os.environ["TZ"] = "US/Central"
|
|
1526
|
+
time.tzset()
|
|
1527
|
+
|
|
1528
|
+
data = {"a": [datetime(2020, 2, 2, 23, 59)]}
|
|
1529
|
+
|
|
1530
|
+
table = Table(data)
|
|
1531
|
+
view = table.view(expressions=["bucket(\"a\", 'W')"])
|
|
1532
|
+
result = view.to_columns()
|
|
1533
|
+
assert result["bucket(\"a\", 'W')"] == [
|
|
1534
|
+
util.to_timestamp(datetime(2020, 1, 27))
|
|
1535
|
+
]
|
|
1536
|
+
|
|
1537
|
+
def test_table_week_bucket_edge_in_PST(self, util):
|
|
1538
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1539
|
+
time.tzset()
|
|
1540
|
+
|
|
1541
|
+
data = {"a": [datetime(2020, 2, 2, 23, 59)]}
|
|
1542
|
+
|
|
1543
|
+
table = Table(data)
|
|
1544
|
+
view = table.view(expressions=["bucket(\"a\", 'W')"])
|
|
1545
|
+
result = view.to_columns()
|
|
1546
|
+
assert result["bucket(\"a\", 'W')"] == [
|
|
1547
|
+
util.to_timestamp(datetime(2020, 1, 27))
|
|
1548
|
+
]
|
|
1549
|
+
|
|
1550
|
+
def test_table_week_bucket_edge_flip_in_EST(self, util):
|
|
1551
|
+
"""Week bucket should flip backwards to last month."""
|
|
1552
|
+
data = {"a": [datetime(2020, 3, 1, 12, 59)]}
|
|
1553
|
+
|
|
1554
|
+
table = Table(data)
|
|
1555
|
+
view = table.view(expressions=["bucket(\"a\", 'W')"])
|
|
1556
|
+
result = view.to_columns()
|
|
1557
|
+
assert result["bucket(\"a\", 'W')"] == [
|
|
1558
|
+
util.to_timestamp(datetime(2020, 2, 24))
|
|
1559
|
+
]
|
|
1560
|
+
|
|
1561
|
+
def test_table_week_bucket_edge_flip_in_CST(self, util):
|
|
1562
|
+
os.environ["TZ"] = "US/Central"
|
|
1563
|
+
time.tzset()
|
|
1564
|
+
data = {"a": [datetime(2020, 3, 1, 12, 59)]}
|
|
1565
|
+
|
|
1566
|
+
table = Table(data)
|
|
1567
|
+
view = table.view(expressions=["bucket(\"a\", 'W')"])
|
|
1568
|
+
result = view.to_columns()
|
|
1569
|
+
assert result["bucket(\"a\", 'W')"] == [
|
|
1570
|
+
util.to_timestamp(datetime(2020, 2, 24))
|
|
1571
|
+
]
|
|
1572
|
+
|
|
1573
|
+
def test_table_week_bucket_edge_flip_in_PST(self, util):
|
|
1574
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1575
|
+
time.tzset()
|
|
1576
|
+
data = {"a": [datetime(2020, 3, 1, 12, 59)]}
|
|
1577
|
+
|
|
1578
|
+
table = Table(data)
|
|
1579
|
+
view = table.view(expressions=["bucket(\"a\", 'W')"])
|
|
1580
|
+
result = view.to_columns()
|
|
1581
|
+
assert result["bucket(\"a\", 'W')"] == [
|
|
1582
|
+
util.to_timestamp(datetime(2020, 2, 24))
|
|
1583
|
+
]
|
|
1584
|
+
|
|
1585
|
+
def test_table_month_bucket_edge_in_EST(self, util):
|
|
1586
|
+
"""Make sure edge cases are fixed for month_bucket - if a local
|
|
1587
|
+
time converted to UTC is in the next day, the month_bucket
|
|
1588
|
+
computation needs to be in local time."""
|
|
1589
|
+
data = {"a": [datetime(2020, 6, 30, 23, 59)]}
|
|
1590
|
+
|
|
1591
|
+
table = Table(data)
|
|
1592
|
+
view = table.view(expressions=["bucket(\"a\", 'M')"])
|
|
1593
|
+
result = view.to_columns()
|
|
1594
|
+
assert result["bucket(\"a\", 'M')"] == [
|
|
1595
|
+
util.to_timestamp(datetime(2020, 6, 1))
|
|
1596
|
+
]
|
|
1597
|
+
|
|
1598
|
+
def test_table_month_bucket_edge_in_CST(self, util):
|
|
1599
|
+
os.environ["TZ"] = "US/Central"
|
|
1600
|
+
time.tzset()
|
|
1601
|
+
|
|
1602
|
+
data = {"a": [datetime(2020, 6, 30, 23, 59)]}
|
|
1603
|
+
|
|
1604
|
+
table = Table(data)
|
|
1605
|
+
view = table.view(expressions=["bucket(\"a\", 'M')"])
|
|
1606
|
+
result = view.to_columns()
|
|
1607
|
+
assert result["bucket(\"a\", 'M')"] == [
|
|
1608
|
+
util.to_timestamp(datetime(2020, 6, 1))
|
|
1609
|
+
]
|
|
1610
|
+
|
|
1611
|
+
def test_table_month_bucket_edge_in_PST(self, util):
|
|
1612
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1613
|
+
time.tzset()
|
|
1614
|
+
|
|
1615
|
+
data = {"a": [datetime(2020, 6, 30, 23, 59)]}
|
|
1616
|
+
|
|
1617
|
+
table = Table(data)
|
|
1618
|
+
view = table.view(expressions=["bucket(\"a\", 'M')"])
|
|
1619
|
+
result = view.to_columns()
|
|
1620
|
+
assert result["bucket(\"a\", 'M')"] == [
|
|
1621
|
+
util.to_timestamp(datetime(2020, 6, 1))
|
|
1622
|
+
]
|
|
1623
|
+
|
|
1624
|
+
def test_table_year_bucket_edge_in_EST(self, util):
|
|
1625
|
+
"""Make sure edge cases are fixed for year_bucket - if a local
|
|
1626
|
+
time converted to UTC is in the next day, the year_bucket
|
|
1627
|
+
computation needs to be in local time."""
|
|
1628
|
+
data = {"a": [datetime(2019, 12, 31, 23, 59)]}
|
|
1629
|
+
|
|
1630
|
+
table = Table(data)
|
|
1631
|
+
view = table.view(expressions=["bucket(\"a\", 'Y')"])
|
|
1632
|
+
result = view.to_columns()
|
|
1633
|
+
assert result["bucket(\"a\", 'Y')"] == [
|
|
1634
|
+
util.to_timestamp(datetime(2019, 1, 1))
|
|
1635
|
+
]
|
|
1636
|
+
|
|
1637
|
+
def test_table_year_bucket_edge_in_CST(self, util):
|
|
1638
|
+
os.environ["TZ"] = "US/Central"
|
|
1639
|
+
time.tzset()
|
|
1640
|
+
data = {"a": [datetime(2019, 12, 31, 23, 59)]}
|
|
1641
|
+
|
|
1642
|
+
table = Table(data)
|
|
1643
|
+
view = table.view(expressions=["bucket(\"a\", 'Y')"])
|
|
1644
|
+
result = view.to_columns()
|
|
1645
|
+
assert result["bucket(\"a\", 'Y')"] == [
|
|
1646
|
+
util.to_timestamp(datetime(2019, 1, 1))
|
|
1647
|
+
]
|
|
1648
|
+
|
|
1649
|
+
def test_table_year_bucket_edge_in_PST(self, util):
|
|
1650
|
+
os.environ["TZ"] = "US/Pacific"
|
|
1651
|
+
time.tzset()
|
|
1652
|
+
data = {"a": [datetime(2019, 12, 31, 23, 59)]}
|
|
1653
|
+
|
|
1654
|
+
table = Table(data)
|
|
1655
|
+
view = table.view(expressions=["bucket(\"a\", 'Y')"])
|
|
1656
|
+
result = view.to_columns()
|
|
1657
|
+
assert result["bucket(\"a\", 'Y')"] == [
|
|
1658
|
+
util.to_timestamp(datetime(2019, 1, 1))
|
|
1659
|
+
]
|
|
1660
|
+
|
|
1661
|
+
|
|
1662
|
+
class TestTableDateTimePivots(object):
|
|
1663
|
+
def test_table_group_by_date_correct(self, util: Util):
|
|
1664
|
+
data = {
|
|
1665
|
+
"a": [date(2020, i, 15) for i in range(1, 13)],
|
|
1666
|
+
"b": [i for i in range(1, 13)],
|
|
1667
|
+
}
|
|
1668
|
+
table = Table(data)
|
|
1669
|
+
view = table.view(group_by=["a"])
|
|
1670
|
+
assert view.to_columns() == {
|
|
1671
|
+
"__ROW_PATH__": [
|
|
1672
|
+
[],
|
|
1673
|
+
[util.to_timestamp(datetime(2020, 1, 15, 0, 0))],
|
|
1674
|
+
[util.to_timestamp(datetime(2020, 2, 15, 0, 0))],
|
|
1675
|
+
[util.to_timestamp(datetime(2020, 3, 15, 0, 0))],
|
|
1676
|
+
[util.to_timestamp(datetime(2020, 4, 15, 0, 0))],
|
|
1677
|
+
[util.to_timestamp(datetime(2020, 5, 15, 0, 0))],
|
|
1678
|
+
[util.to_timestamp(datetime(2020, 6, 15, 0, 0))],
|
|
1679
|
+
[util.to_timestamp(datetime(2020, 7, 15, 0, 0))],
|
|
1680
|
+
[util.to_timestamp(datetime(2020, 8, 15, 0, 0))],
|
|
1681
|
+
[util.to_timestamp(datetime(2020, 9, 15, 0, 0))],
|
|
1682
|
+
[util.to_timestamp(datetime(2020, 10, 15, 0, 0))],
|
|
1683
|
+
[util.to_timestamp(datetime(2020, 11, 15, 0, 0))],
|
|
1684
|
+
[util.to_timestamp(datetime(2020, 12, 15, 0, 0))],
|
|
1685
|
+
],
|
|
1686
|
+
"a": [12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
1687
|
+
"b": [78, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
def test_table_group_by_pandas_date_correct(self, util: Util):
|
|
1691
|
+
data = {
|
|
1692
|
+
"a": [date(2020, i, 15) for i in range(1, 13)],
|
|
1693
|
+
"b": [i for i in range(1, 13)],
|
|
1694
|
+
}
|
|
1695
|
+
table = Table(pd.DataFrame(data))
|
|
1696
|
+
view = table.view(group_by=["a"])
|
|
1697
|
+
assert view.to_columns() == {
|
|
1698
|
+
"__ROW_PATH__": [
|
|
1699
|
+
[],
|
|
1700
|
+
[util.to_timestamp(datetime(2020, 1, 15, 0, 0))],
|
|
1701
|
+
[util.to_timestamp(datetime(2020, 2, 15, 0, 0))],
|
|
1702
|
+
[util.to_timestamp(datetime(2020, 3, 15, 0, 0))],
|
|
1703
|
+
[util.to_timestamp(datetime(2020, 4, 15, 0, 0))],
|
|
1704
|
+
[util.to_timestamp(datetime(2020, 5, 15, 0, 0))],
|
|
1705
|
+
[util.to_timestamp(datetime(2020, 6, 15, 0, 0))],
|
|
1706
|
+
[util.to_timestamp(datetime(2020, 7, 15, 0, 0))],
|
|
1707
|
+
[util.to_timestamp(datetime(2020, 8, 15, 0, 0))],
|
|
1708
|
+
[util.to_timestamp(datetime(2020, 9, 15, 0, 0))],
|
|
1709
|
+
[util.to_timestamp(datetime(2020, 10, 15, 0, 0))],
|
|
1710
|
+
[util.to_timestamp(datetime(2020, 11, 15, 0, 0))],
|
|
1711
|
+
[util.to_timestamp(datetime(2020, 12, 15, 0, 0))],
|
|
1712
|
+
],
|
|
1713
|
+
"index": [66, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
|
1714
|
+
"a": [12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
|
1715
|
+
"b": [78, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
def test_table_split_by_date_correct(self, util: Util):
|
|
1719
|
+
data = {
|
|
1720
|
+
"a": [date(2020, i, 15) for i in range(1, 13)],
|
|
1721
|
+
"b": [i for i in range(1, 13)],
|
|
1722
|
+
}
|
|
1723
|
+
table = Table(data)
|
|
1724
|
+
view = table.view(split_by=["a"])
|
|
1725
|
+
assert view.to_columns() == {
|
|
1726
|
+
"2020-01-15|a": [
|
|
1727
|
+
util.to_timestamp(datetime(2020, 1, 15, 0, 0)),
|
|
1728
|
+
None,
|
|
1729
|
+
None,
|
|
1730
|
+
None,
|
|
1731
|
+
None,
|
|
1732
|
+
None,
|
|
1733
|
+
None,
|
|
1734
|
+
None,
|
|
1735
|
+
None,
|
|
1736
|
+
None,
|
|
1737
|
+
None,
|
|
1738
|
+
None,
|
|
1739
|
+
],
|
|
1740
|
+
"2020-01-15|b": [
|
|
1741
|
+
1,
|
|
1742
|
+
None,
|
|
1743
|
+
None,
|
|
1744
|
+
None,
|
|
1745
|
+
None,
|
|
1746
|
+
None,
|
|
1747
|
+
None,
|
|
1748
|
+
None,
|
|
1749
|
+
None,
|
|
1750
|
+
None,
|
|
1751
|
+
None,
|
|
1752
|
+
None,
|
|
1753
|
+
],
|
|
1754
|
+
"2020-02-15|a": [
|
|
1755
|
+
None,
|
|
1756
|
+
util.to_timestamp(datetime(2020, 2, 15, 0, 0)),
|
|
1757
|
+
None,
|
|
1758
|
+
None,
|
|
1759
|
+
None,
|
|
1760
|
+
None,
|
|
1761
|
+
None,
|
|
1762
|
+
None,
|
|
1763
|
+
None,
|
|
1764
|
+
None,
|
|
1765
|
+
None,
|
|
1766
|
+
None,
|
|
1767
|
+
],
|
|
1768
|
+
"2020-02-15|b": [
|
|
1769
|
+
None,
|
|
1770
|
+
2,
|
|
1771
|
+
None,
|
|
1772
|
+
None,
|
|
1773
|
+
None,
|
|
1774
|
+
None,
|
|
1775
|
+
None,
|
|
1776
|
+
None,
|
|
1777
|
+
None,
|
|
1778
|
+
None,
|
|
1779
|
+
None,
|
|
1780
|
+
None,
|
|
1781
|
+
],
|
|
1782
|
+
"2020-03-15|a": [
|
|
1783
|
+
None,
|
|
1784
|
+
None,
|
|
1785
|
+
util.to_timestamp(datetime(2020, 3, 15, 0, 0)),
|
|
1786
|
+
None,
|
|
1787
|
+
None,
|
|
1788
|
+
None,
|
|
1789
|
+
None,
|
|
1790
|
+
None,
|
|
1791
|
+
None,
|
|
1792
|
+
None,
|
|
1793
|
+
None,
|
|
1794
|
+
None,
|
|
1795
|
+
],
|
|
1796
|
+
"2020-03-15|b": [
|
|
1797
|
+
None,
|
|
1798
|
+
None,
|
|
1799
|
+
3,
|
|
1800
|
+
None,
|
|
1801
|
+
None,
|
|
1802
|
+
None,
|
|
1803
|
+
None,
|
|
1804
|
+
None,
|
|
1805
|
+
None,
|
|
1806
|
+
None,
|
|
1807
|
+
None,
|
|
1808
|
+
None,
|
|
1809
|
+
],
|
|
1810
|
+
"2020-04-15|a": [
|
|
1811
|
+
None,
|
|
1812
|
+
None,
|
|
1813
|
+
None,
|
|
1814
|
+
util.to_timestamp(datetime(2020, 4, 15, 0, 0)),
|
|
1815
|
+
None,
|
|
1816
|
+
None,
|
|
1817
|
+
None,
|
|
1818
|
+
None,
|
|
1819
|
+
None,
|
|
1820
|
+
None,
|
|
1821
|
+
None,
|
|
1822
|
+
None,
|
|
1823
|
+
],
|
|
1824
|
+
"2020-04-15|b": [
|
|
1825
|
+
None,
|
|
1826
|
+
None,
|
|
1827
|
+
None,
|
|
1828
|
+
4,
|
|
1829
|
+
None,
|
|
1830
|
+
None,
|
|
1831
|
+
None,
|
|
1832
|
+
None,
|
|
1833
|
+
None,
|
|
1834
|
+
None,
|
|
1835
|
+
None,
|
|
1836
|
+
None,
|
|
1837
|
+
],
|
|
1838
|
+
"2020-05-15|a": [
|
|
1839
|
+
None,
|
|
1840
|
+
None,
|
|
1841
|
+
None,
|
|
1842
|
+
None,
|
|
1843
|
+
util.to_timestamp(datetime(2020, 5, 15, 0, 0)),
|
|
1844
|
+
None,
|
|
1845
|
+
None,
|
|
1846
|
+
None,
|
|
1847
|
+
None,
|
|
1848
|
+
None,
|
|
1849
|
+
None,
|
|
1850
|
+
None,
|
|
1851
|
+
],
|
|
1852
|
+
"2020-05-15|b": [
|
|
1853
|
+
None,
|
|
1854
|
+
None,
|
|
1855
|
+
None,
|
|
1856
|
+
None,
|
|
1857
|
+
5,
|
|
1858
|
+
None,
|
|
1859
|
+
None,
|
|
1860
|
+
None,
|
|
1861
|
+
None,
|
|
1862
|
+
None,
|
|
1863
|
+
None,
|
|
1864
|
+
None,
|
|
1865
|
+
],
|
|
1866
|
+
"2020-06-15|a": [
|
|
1867
|
+
None,
|
|
1868
|
+
None,
|
|
1869
|
+
None,
|
|
1870
|
+
None,
|
|
1871
|
+
None,
|
|
1872
|
+
util.to_timestamp(datetime(2020, 6, 15, 0, 0)),
|
|
1873
|
+
None,
|
|
1874
|
+
None,
|
|
1875
|
+
None,
|
|
1876
|
+
None,
|
|
1877
|
+
None,
|
|
1878
|
+
None,
|
|
1879
|
+
],
|
|
1880
|
+
"2020-06-15|b": [
|
|
1881
|
+
None,
|
|
1882
|
+
None,
|
|
1883
|
+
None,
|
|
1884
|
+
None,
|
|
1885
|
+
None,
|
|
1886
|
+
6,
|
|
1887
|
+
None,
|
|
1888
|
+
None,
|
|
1889
|
+
None,
|
|
1890
|
+
None,
|
|
1891
|
+
None,
|
|
1892
|
+
None,
|
|
1893
|
+
],
|
|
1894
|
+
"2020-07-15|a": [
|
|
1895
|
+
None,
|
|
1896
|
+
None,
|
|
1897
|
+
None,
|
|
1898
|
+
None,
|
|
1899
|
+
None,
|
|
1900
|
+
None,
|
|
1901
|
+
util.to_timestamp(datetime(2020, 7, 15, 0, 0)),
|
|
1902
|
+
None,
|
|
1903
|
+
None,
|
|
1904
|
+
None,
|
|
1905
|
+
None,
|
|
1906
|
+
None,
|
|
1907
|
+
],
|
|
1908
|
+
"2020-07-15|b": [
|
|
1909
|
+
None,
|
|
1910
|
+
None,
|
|
1911
|
+
None,
|
|
1912
|
+
None,
|
|
1913
|
+
None,
|
|
1914
|
+
None,
|
|
1915
|
+
7,
|
|
1916
|
+
None,
|
|
1917
|
+
None,
|
|
1918
|
+
None,
|
|
1919
|
+
None,
|
|
1920
|
+
None,
|
|
1921
|
+
],
|
|
1922
|
+
"2020-08-15|a": [
|
|
1923
|
+
None,
|
|
1924
|
+
None,
|
|
1925
|
+
None,
|
|
1926
|
+
None,
|
|
1927
|
+
None,
|
|
1928
|
+
None,
|
|
1929
|
+
None,
|
|
1930
|
+
util.to_timestamp(datetime(2020, 8, 15, 0, 0)),
|
|
1931
|
+
None,
|
|
1932
|
+
None,
|
|
1933
|
+
None,
|
|
1934
|
+
None,
|
|
1935
|
+
],
|
|
1936
|
+
"2020-08-15|b": [
|
|
1937
|
+
None,
|
|
1938
|
+
None,
|
|
1939
|
+
None,
|
|
1940
|
+
None,
|
|
1941
|
+
None,
|
|
1942
|
+
None,
|
|
1943
|
+
None,
|
|
1944
|
+
8,
|
|
1945
|
+
None,
|
|
1946
|
+
None,
|
|
1947
|
+
None,
|
|
1948
|
+
None,
|
|
1949
|
+
],
|
|
1950
|
+
"2020-09-15|a": [
|
|
1951
|
+
None,
|
|
1952
|
+
None,
|
|
1953
|
+
None,
|
|
1954
|
+
None,
|
|
1955
|
+
None,
|
|
1956
|
+
None,
|
|
1957
|
+
None,
|
|
1958
|
+
None,
|
|
1959
|
+
util.to_timestamp(datetime(2020, 9, 15, 0, 0)),
|
|
1960
|
+
None,
|
|
1961
|
+
None,
|
|
1962
|
+
None,
|
|
1963
|
+
],
|
|
1964
|
+
"2020-09-15|b": [
|
|
1965
|
+
None,
|
|
1966
|
+
None,
|
|
1967
|
+
None,
|
|
1968
|
+
None,
|
|
1969
|
+
None,
|
|
1970
|
+
None,
|
|
1971
|
+
None,
|
|
1972
|
+
None,
|
|
1973
|
+
9,
|
|
1974
|
+
None,
|
|
1975
|
+
None,
|
|
1976
|
+
None,
|
|
1977
|
+
],
|
|
1978
|
+
"2020-10-15|a": [
|
|
1979
|
+
None,
|
|
1980
|
+
None,
|
|
1981
|
+
None,
|
|
1982
|
+
None,
|
|
1983
|
+
None,
|
|
1984
|
+
None,
|
|
1985
|
+
None,
|
|
1986
|
+
None,
|
|
1987
|
+
None,
|
|
1988
|
+
util.to_timestamp(datetime(2020, 10, 15, 0, 0)),
|
|
1989
|
+
None,
|
|
1990
|
+
None,
|
|
1991
|
+
],
|
|
1992
|
+
"2020-10-15|b": [
|
|
1993
|
+
None,
|
|
1994
|
+
None,
|
|
1995
|
+
None,
|
|
1996
|
+
None,
|
|
1997
|
+
None,
|
|
1998
|
+
None,
|
|
1999
|
+
None,
|
|
2000
|
+
None,
|
|
2001
|
+
None,
|
|
2002
|
+
10,
|
|
2003
|
+
None,
|
|
2004
|
+
None,
|
|
2005
|
+
],
|
|
2006
|
+
"2020-11-15|a": [
|
|
2007
|
+
None,
|
|
2008
|
+
None,
|
|
2009
|
+
None,
|
|
2010
|
+
None,
|
|
2011
|
+
None,
|
|
2012
|
+
None,
|
|
2013
|
+
None,
|
|
2014
|
+
None,
|
|
2015
|
+
None,
|
|
2016
|
+
None,
|
|
2017
|
+
util.to_timestamp(datetime(2020, 11, 15, 0, 0)),
|
|
2018
|
+
None,
|
|
2019
|
+
],
|
|
2020
|
+
"2020-11-15|b": [
|
|
2021
|
+
None,
|
|
2022
|
+
None,
|
|
2023
|
+
None,
|
|
2024
|
+
None,
|
|
2025
|
+
None,
|
|
2026
|
+
None,
|
|
2027
|
+
None,
|
|
2028
|
+
None,
|
|
2029
|
+
None,
|
|
2030
|
+
None,
|
|
2031
|
+
11,
|
|
2032
|
+
None,
|
|
2033
|
+
],
|
|
2034
|
+
"2020-12-15|a": [
|
|
2035
|
+
None,
|
|
2036
|
+
None,
|
|
2037
|
+
None,
|
|
2038
|
+
None,
|
|
2039
|
+
None,
|
|
2040
|
+
None,
|
|
2041
|
+
None,
|
|
2042
|
+
None,
|
|
2043
|
+
None,
|
|
2044
|
+
None,
|
|
2045
|
+
None,
|
|
2046
|
+
util.to_timestamp(datetime(2020, 12, 15, 0, 0)),
|
|
2047
|
+
],
|
|
2048
|
+
"2020-12-15|b": [
|
|
2049
|
+
None,
|
|
2050
|
+
None,
|
|
2051
|
+
None,
|
|
2052
|
+
None,
|
|
2053
|
+
None,
|
|
2054
|
+
None,
|
|
2055
|
+
None,
|
|
2056
|
+
None,
|
|
2057
|
+
None,
|
|
2058
|
+
None,
|
|
2059
|
+
None,
|
|
2060
|
+
12,
|
|
2061
|
+
],
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
def test_table_split_by_pandas_date_correct(self, util: Util):
|
|
2065
|
+
data = {
|
|
2066
|
+
"a": [date(2020, i, 15) for i in range(1, 13)],
|
|
2067
|
+
"b": [i for i in range(1, 13)],
|
|
2068
|
+
}
|
|
2069
|
+
table = Table(pd.DataFrame(data))
|
|
2070
|
+
view = table.view(columns=["a", "b"], split_by=["a"])
|
|
2071
|
+
print(f"XXXX: {view.to_columns()}")
|
|
2072
|
+
assert view.to_columns() == {
|
|
2073
|
+
"2020-01-15|a": [
|
|
2074
|
+
util.to_timestamp(datetime(2020, 1, 15, 0, 0)),
|
|
2075
|
+
None,
|
|
2076
|
+
None,
|
|
2077
|
+
None,
|
|
2078
|
+
None,
|
|
2079
|
+
None,
|
|
2080
|
+
None,
|
|
2081
|
+
None,
|
|
2082
|
+
None,
|
|
2083
|
+
None,
|
|
2084
|
+
None,
|
|
2085
|
+
None,
|
|
2086
|
+
],
|
|
2087
|
+
"2020-01-15|b": [
|
|
2088
|
+
1,
|
|
2089
|
+
None,
|
|
2090
|
+
None,
|
|
2091
|
+
None,
|
|
2092
|
+
None,
|
|
2093
|
+
None,
|
|
2094
|
+
None,
|
|
2095
|
+
None,
|
|
2096
|
+
None,
|
|
2097
|
+
None,
|
|
2098
|
+
None,
|
|
2099
|
+
None,
|
|
2100
|
+
],
|
|
2101
|
+
"2020-02-15|a": [
|
|
2102
|
+
None,
|
|
2103
|
+
util.to_timestamp(datetime(2020, 2, 15, 0, 0)),
|
|
2104
|
+
None,
|
|
2105
|
+
None,
|
|
2106
|
+
None,
|
|
2107
|
+
None,
|
|
2108
|
+
None,
|
|
2109
|
+
None,
|
|
2110
|
+
None,
|
|
2111
|
+
None,
|
|
2112
|
+
None,
|
|
2113
|
+
None,
|
|
2114
|
+
],
|
|
2115
|
+
"2020-02-15|b": [
|
|
2116
|
+
None,
|
|
2117
|
+
2,
|
|
2118
|
+
None,
|
|
2119
|
+
None,
|
|
2120
|
+
None,
|
|
2121
|
+
None,
|
|
2122
|
+
None,
|
|
2123
|
+
None,
|
|
2124
|
+
None,
|
|
2125
|
+
None,
|
|
2126
|
+
None,
|
|
2127
|
+
None,
|
|
2128
|
+
],
|
|
2129
|
+
"2020-03-15|a": [
|
|
2130
|
+
None,
|
|
2131
|
+
None,
|
|
2132
|
+
util.to_timestamp(datetime(2020, 3, 15, 0, 0)),
|
|
2133
|
+
None,
|
|
2134
|
+
None,
|
|
2135
|
+
None,
|
|
2136
|
+
None,
|
|
2137
|
+
None,
|
|
2138
|
+
None,
|
|
2139
|
+
None,
|
|
2140
|
+
None,
|
|
2141
|
+
None,
|
|
2142
|
+
],
|
|
2143
|
+
"2020-03-15|b": [
|
|
2144
|
+
None,
|
|
2145
|
+
None,
|
|
2146
|
+
3,
|
|
2147
|
+
None,
|
|
2148
|
+
None,
|
|
2149
|
+
None,
|
|
2150
|
+
None,
|
|
2151
|
+
None,
|
|
2152
|
+
None,
|
|
2153
|
+
None,
|
|
2154
|
+
None,
|
|
2155
|
+
None,
|
|
2156
|
+
],
|
|
2157
|
+
"2020-04-15|a": [
|
|
2158
|
+
None,
|
|
2159
|
+
None,
|
|
2160
|
+
None,
|
|
2161
|
+
util.to_timestamp(datetime(2020, 4, 15, 0, 0)),
|
|
2162
|
+
None,
|
|
2163
|
+
None,
|
|
2164
|
+
None,
|
|
2165
|
+
None,
|
|
2166
|
+
None,
|
|
2167
|
+
None,
|
|
2168
|
+
None,
|
|
2169
|
+
None,
|
|
2170
|
+
],
|
|
2171
|
+
"2020-04-15|b": [
|
|
2172
|
+
None,
|
|
2173
|
+
None,
|
|
2174
|
+
None,
|
|
2175
|
+
4,
|
|
2176
|
+
None,
|
|
2177
|
+
None,
|
|
2178
|
+
None,
|
|
2179
|
+
None,
|
|
2180
|
+
None,
|
|
2181
|
+
None,
|
|
2182
|
+
None,
|
|
2183
|
+
None,
|
|
2184
|
+
],
|
|
2185
|
+
"2020-05-15|a": [
|
|
2186
|
+
None,
|
|
2187
|
+
None,
|
|
2188
|
+
None,
|
|
2189
|
+
None,
|
|
2190
|
+
util.to_timestamp(datetime(2020, 5, 15, 0, 0)),
|
|
2191
|
+
None,
|
|
2192
|
+
None,
|
|
2193
|
+
None,
|
|
2194
|
+
None,
|
|
2195
|
+
None,
|
|
2196
|
+
None,
|
|
2197
|
+
None,
|
|
2198
|
+
],
|
|
2199
|
+
"2020-05-15|b": [
|
|
2200
|
+
None,
|
|
2201
|
+
None,
|
|
2202
|
+
None,
|
|
2203
|
+
None,
|
|
2204
|
+
5,
|
|
2205
|
+
None,
|
|
2206
|
+
None,
|
|
2207
|
+
None,
|
|
2208
|
+
None,
|
|
2209
|
+
None,
|
|
2210
|
+
None,
|
|
2211
|
+
None,
|
|
2212
|
+
],
|
|
2213
|
+
"2020-06-15|a": [
|
|
2214
|
+
None,
|
|
2215
|
+
None,
|
|
2216
|
+
None,
|
|
2217
|
+
None,
|
|
2218
|
+
None,
|
|
2219
|
+
util.to_timestamp(datetime(2020, 6, 15, 0, 0)),
|
|
2220
|
+
None,
|
|
2221
|
+
None,
|
|
2222
|
+
None,
|
|
2223
|
+
None,
|
|
2224
|
+
None,
|
|
2225
|
+
None,
|
|
2226
|
+
],
|
|
2227
|
+
"2020-06-15|b": [
|
|
2228
|
+
None,
|
|
2229
|
+
None,
|
|
2230
|
+
None,
|
|
2231
|
+
None,
|
|
2232
|
+
None,
|
|
2233
|
+
6,
|
|
2234
|
+
None,
|
|
2235
|
+
None,
|
|
2236
|
+
None,
|
|
2237
|
+
None,
|
|
2238
|
+
None,
|
|
2239
|
+
None,
|
|
2240
|
+
],
|
|
2241
|
+
"2020-07-15|a": [
|
|
2242
|
+
None,
|
|
2243
|
+
None,
|
|
2244
|
+
None,
|
|
2245
|
+
None,
|
|
2246
|
+
None,
|
|
2247
|
+
None,
|
|
2248
|
+
util.to_timestamp(datetime(2020, 7, 15, 0, 0)),
|
|
2249
|
+
None,
|
|
2250
|
+
None,
|
|
2251
|
+
None,
|
|
2252
|
+
None,
|
|
2253
|
+
None,
|
|
2254
|
+
],
|
|
2255
|
+
"2020-07-15|b": [
|
|
2256
|
+
None,
|
|
2257
|
+
None,
|
|
2258
|
+
None,
|
|
2259
|
+
None,
|
|
2260
|
+
None,
|
|
2261
|
+
None,
|
|
2262
|
+
7,
|
|
2263
|
+
None,
|
|
2264
|
+
None,
|
|
2265
|
+
None,
|
|
2266
|
+
None,
|
|
2267
|
+
None,
|
|
2268
|
+
],
|
|
2269
|
+
"2020-08-15|a": [
|
|
2270
|
+
None,
|
|
2271
|
+
None,
|
|
2272
|
+
None,
|
|
2273
|
+
None,
|
|
2274
|
+
None,
|
|
2275
|
+
None,
|
|
2276
|
+
None,
|
|
2277
|
+
util.to_timestamp(datetime(2020, 8, 15, 0, 0)),
|
|
2278
|
+
None,
|
|
2279
|
+
None,
|
|
2280
|
+
None,
|
|
2281
|
+
None,
|
|
2282
|
+
],
|
|
2283
|
+
"2020-08-15|b": [
|
|
2284
|
+
None,
|
|
2285
|
+
None,
|
|
2286
|
+
None,
|
|
2287
|
+
None,
|
|
2288
|
+
None,
|
|
2289
|
+
None,
|
|
2290
|
+
None,
|
|
2291
|
+
8,
|
|
2292
|
+
None,
|
|
2293
|
+
None,
|
|
2294
|
+
None,
|
|
2295
|
+
None,
|
|
2296
|
+
],
|
|
2297
|
+
"2020-09-15|a": [
|
|
2298
|
+
None,
|
|
2299
|
+
None,
|
|
2300
|
+
None,
|
|
2301
|
+
None,
|
|
2302
|
+
None,
|
|
2303
|
+
None,
|
|
2304
|
+
None,
|
|
2305
|
+
None,
|
|
2306
|
+
util.to_timestamp(datetime(2020, 9, 15, 0, 0)),
|
|
2307
|
+
None,
|
|
2308
|
+
None,
|
|
2309
|
+
None,
|
|
2310
|
+
],
|
|
2311
|
+
"2020-09-15|b": [
|
|
2312
|
+
None,
|
|
2313
|
+
None,
|
|
2314
|
+
None,
|
|
2315
|
+
None,
|
|
2316
|
+
None,
|
|
2317
|
+
None,
|
|
2318
|
+
None,
|
|
2319
|
+
None,
|
|
2320
|
+
9,
|
|
2321
|
+
None,
|
|
2322
|
+
None,
|
|
2323
|
+
None,
|
|
2324
|
+
],
|
|
2325
|
+
"2020-10-15|a": [
|
|
2326
|
+
None,
|
|
2327
|
+
None,
|
|
2328
|
+
None,
|
|
2329
|
+
None,
|
|
2330
|
+
None,
|
|
2331
|
+
None,
|
|
2332
|
+
None,
|
|
2333
|
+
None,
|
|
2334
|
+
None,
|
|
2335
|
+
util.to_timestamp(datetime(2020, 10, 15, 0, 0)),
|
|
2336
|
+
None,
|
|
2337
|
+
None,
|
|
2338
|
+
],
|
|
2339
|
+
"2020-10-15|b": [
|
|
2340
|
+
None,
|
|
2341
|
+
None,
|
|
2342
|
+
None,
|
|
2343
|
+
None,
|
|
2344
|
+
None,
|
|
2345
|
+
None,
|
|
2346
|
+
None,
|
|
2347
|
+
None,
|
|
2348
|
+
None,
|
|
2349
|
+
10,
|
|
2350
|
+
None,
|
|
2351
|
+
None,
|
|
2352
|
+
],
|
|
2353
|
+
"2020-11-15|a": [
|
|
2354
|
+
None,
|
|
2355
|
+
None,
|
|
2356
|
+
None,
|
|
2357
|
+
None,
|
|
2358
|
+
None,
|
|
2359
|
+
None,
|
|
2360
|
+
None,
|
|
2361
|
+
None,
|
|
2362
|
+
None,
|
|
2363
|
+
None,
|
|
2364
|
+
util.to_timestamp(datetime(2020, 11, 15, 0, 0)),
|
|
2365
|
+
None,
|
|
2366
|
+
],
|
|
2367
|
+
"2020-11-15|b": [
|
|
2368
|
+
None,
|
|
2369
|
+
None,
|
|
2370
|
+
None,
|
|
2371
|
+
None,
|
|
2372
|
+
None,
|
|
2373
|
+
None,
|
|
2374
|
+
None,
|
|
2375
|
+
None,
|
|
2376
|
+
None,
|
|
2377
|
+
None,
|
|
2378
|
+
11,
|
|
2379
|
+
None,
|
|
2380
|
+
],
|
|
2381
|
+
"2020-12-15|a": [
|
|
2382
|
+
None,
|
|
2383
|
+
None,
|
|
2384
|
+
None,
|
|
2385
|
+
None,
|
|
2386
|
+
None,
|
|
2387
|
+
None,
|
|
2388
|
+
None,
|
|
2389
|
+
None,
|
|
2390
|
+
None,
|
|
2391
|
+
None,
|
|
2392
|
+
None,
|
|
2393
|
+
util.to_timestamp(datetime(2020, 12, 15, 0, 0)),
|
|
2394
|
+
],
|
|
2395
|
+
"2020-12-15|b": [
|
|
2396
|
+
None,
|
|
2397
|
+
None,
|
|
2398
|
+
None,
|
|
2399
|
+
None,
|
|
2400
|
+
None,
|
|
2401
|
+
None,
|
|
2402
|
+
None,
|
|
2403
|
+
None,
|
|
2404
|
+
None,
|
|
2405
|
+
None,
|
|
2406
|
+
None,
|
|
2407
|
+
12,
|
|
2408
|
+
],
|
|
2409
|
+
}
|