diff --git a/plotly_resampler/aggregation/plotly_aggregator_parser.py b/plotly_resampler/aggregation/plotly_aggregator_parser.py index c359aa29..4f0b7c98 100644 --- a/plotly_resampler/aggregation/plotly_aggregator_parser.py +++ b/plotly_resampler/aggregation/plotly_aggregator_parser.py @@ -38,7 +38,11 @@ def to_same_tz( return None elif reference_tz is not None: if ts.tz is not None: - assert ts.tz.__str__() == reference_tz.__str__() + # compare if these two have the same timezone / offset + try: + assert ts.tz.__str__() == reference_tz.__str__() + except AssertionError: + assert ts.utcoffset() == reference_tz.utcoffset(ts.tz_convert(None)) return ts else: # localize -> time remains the same return ts.tz_localize(reference_tz) @@ -78,7 +82,8 @@ def get_start_end_indices(hf_trace_data, axis_type, start, end) -> Tuple[int, in # convert start & end to the same timezone if isinstance(hf_trace_data["x"], pd.DatetimeIndex): tz = hf_trace_data["x"].tz - assert start.tz == end.tz + # print(start.tz.__str__(), end.tz.__str__()) + assert start.tz.__str__() == end.tz.__str__() start = PlotlyAggregatorParser.to_same_tz(start, tz) end = PlotlyAggregatorParser.to_same_tz(end, tz) diff --git a/tests/test_figure_resampler.py b/tests/test_figure_resampler.py index 640914ec..205f5a6e 100644 --- a/tests/test_figure_resampler.py +++ b/tests/test_figure_resampler.py @@ -758,6 +758,53 @@ def test_tz_xaxis_range(): assert len(out[2]["x"]) == 2000 +def test_compare_tz_with_fixed_offset(): + # related: https://github.com/predict-idlab/plotly-resampler/issues/305 + fig = FigureResampler() + + x = pd.date_range("2024-04-01T00:00:00", "2025-01-01T00:00:00", freq="H") + x = x.tz_localize("Asia/Taipei") + y = np.random.randn(len(x)) + + fig.add_trace( + go.Scattergl(x=x, y=y, name="demo", mode="lines+markers"), + max_n_samples=int(len(x) * 0.2), + ) + + relayout_data = { + "xaxis.range[0]": "2024-04-27T08:00:00+08:00", + "xaxis.range[1]": "2024-05-04T17:15:39.491031+08:00", + } + + fig.construct_update_data_patch(relayout_data) + + +def test_compare_tz_with_fixed_offset_2(): + # related: https://github.com/predict-idlab/plotly-resampler/issues/305 + fig = FigureResampler() + + x = pd.date_range("2024-04-01T00:00:00", "2025-01-01T00:00:00", freq="H") + x = x.tz_localize("UTC") + x = x.tz_convert("Canada/Pacific") + y = np.random.randn(len(x)) + + fig.add_trace( + go.Scattergl(x=x, y=y, name="demo", mode="lines+markers"), + max_n_samples=int(len(x) * 0.2), + ) + + relayout_data = { + "xaxis.range[0]": pd.Timestamp("2024-03-01T00:00:00").tz_localize( + "Canada/Pacific" + ), + "xaxis.range[1]": pd.Timestamp("2024-03-31T00:00:00").tz_localize( + "Canada/Pacific" + ), + } + + fig.construct_update_data_patch(relayout_data) + + def test_datetime_hf_x_no_index(): df = pd.DataFrame( {"timestamp": pd.date_range("2020-01-01", "2020-01-02", freq="1s")} @@ -1013,7 +1060,7 @@ def test_time_tz_slicing_different_timestamp(): cs = [ dr, dr.tz_localize(None).tz_localize("Europe/Amsterdam"), - dr.tz_convert("Europe/Brussels"), + dr.tz_convert("Europe/Lisbon"), dr.tz_convert("Australia/Perth"), dr.tz_convert("Australia/Canberra"), ] @@ -1031,6 +1078,25 @@ def test_time_tz_slicing_different_timestamp(): hf_data_dict, hf_data_dict["axis_type"], t_start, t_stop ) + # THESE have the same timezone offset -> no AssertionError should be raised + cs = [ + dr.tz_localize(None).tz_localize("Europe/Amsterdam"), + dr.tz_convert("Europe/Brussels"), + dr.tz_convert("Europe/Oslo"), + dr.tz_convert("Europe/Paris"), + dr.tz_convert("Europe/Rome"), + ] + + for i, s in enumerate(cs): + t_start, t_stop = sorted(s.iloc[np.random.randint(0, n, 2)].index) + t_start = t_start.tz_convert(cs[(i + 1) % len(cs)].index.tz) + t_stop = t_stop.tz_convert(cs[(i + 1) % len(cs)].index.tz) + + hf_data_dict = construct_hf_data_dict(s.index, s.values) + start_idx, end_idx = PlotlyAggregatorParser.get_start_end_indices( + hf_data_dict, hf_data_dict["axis_type"], t_start, t_stop + ) + def test_different_tz_no_tz_series_slicing(): n = 60 * 60 * 24 * 3