Initial Debugging Completed and Execution Successful
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,86 @@
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
|
||||
from pandas.errors import OutOfBoundsDatetime
|
||||
|
||||
from pandas import Timestamp
|
||||
|
||||
|
||||
class TestTimestampAsUnit:
|
||||
def test_as_unit(self):
|
||||
ts = Timestamp("1970-01-01").as_unit("ns")
|
||||
assert ts.unit == "ns"
|
||||
|
||||
assert ts.as_unit("ns") is ts
|
||||
|
||||
res = ts.as_unit("us")
|
||||
assert res._value == ts._value // 1000
|
||||
assert res._creso == NpyDatetimeUnit.NPY_FR_us.value
|
||||
|
||||
rt = res.as_unit("ns")
|
||||
assert rt._value == ts._value
|
||||
assert rt._creso == ts._creso
|
||||
|
||||
res = ts.as_unit("ms")
|
||||
assert res._value == ts._value // 1_000_000
|
||||
assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
|
||||
|
||||
rt = res.as_unit("ns")
|
||||
assert rt._value == ts._value
|
||||
assert rt._creso == ts._creso
|
||||
|
||||
res = ts.as_unit("s")
|
||||
assert res._value == ts._value // 1_000_000_000
|
||||
assert res._creso == NpyDatetimeUnit.NPY_FR_s.value
|
||||
|
||||
rt = res.as_unit("ns")
|
||||
assert rt._value == ts._value
|
||||
assert rt._creso == ts._creso
|
||||
|
||||
def test_as_unit_overflows(self):
|
||||
# microsecond that would be just out of bounds for nano
|
||||
us = 9223372800000000
|
||||
ts = Timestamp._from_value_and_reso(us, NpyDatetimeUnit.NPY_FR_us.value, None)
|
||||
|
||||
msg = "Cannot cast 2262-04-12 00:00:00 to unit='ns' without overflow"
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
ts.as_unit("ns")
|
||||
|
||||
res = ts.as_unit("ms")
|
||||
assert res._value == us // 1000
|
||||
assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
|
||||
|
||||
def test_as_unit_rounding(self):
|
||||
ts = Timestamp(1_500_000) # i.e. 1500 microseconds
|
||||
res = ts.as_unit("ms")
|
||||
|
||||
expected = Timestamp(1_000_000) # i.e. 1 millisecond
|
||||
assert res == expected
|
||||
|
||||
assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
|
||||
assert res._value == 1
|
||||
|
||||
with pytest.raises(ValueError, match="Cannot losslessly convert units"):
|
||||
ts.as_unit("ms", round_ok=False)
|
||||
|
||||
def test_as_unit_non_nano(self):
|
||||
# case where we are going neither to nor from nano
|
||||
ts = Timestamp("1970-01-02").as_unit("ms")
|
||||
assert ts.year == 1970
|
||||
assert ts.month == 1
|
||||
assert ts.day == 2
|
||||
assert ts.hour == ts.minute == ts.second == ts.microsecond == ts.nanosecond == 0
|
||||
|
||||
res = ts.as_unit("s")
|
||||
assert res._value == 24 * 3600
|
||||
assert res.year == 1970
|
||||
assert res.month == 1
|
||||
assert res.day == 2
|
||||
assert (
|
||||
res.hour
|
||||
== res.minute
|
||||
== res.second
|
||||
== res.microsecond
|
||||
== res.nanosecond
|
||||
== 0
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs import Timestamp
|
||||
from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
|
||||
|
||||
|
||||
class TestTimestampNormalize:
|
||||
@pytest.mark.parametrize("arg", ["2013-11-30", "2013-11-30 12:00:00"])
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_normalize(self, tz_naive_fixture, arg, unit):
|
||||
tz = tz_naive_fixture
|
||||
ts = Timestamp(arg, tz=tz).as_unit(unit)
|
||||
result = ts.normalize()
|
||||
expected = Timestamp("2013-11-30", tz=tz)
|
||||
assert result == expected
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
def test_normalize_pre_epoch_dates(self):
|
||||
# GH: 36294
|
||||
result = Timestamp("1969-01-01 09:00:00").normalize()
|
||||
expected = Timestamp("1969-01-01 00:00:00")
|
||||
assert result == expected
|
||||
@@ -0,0 +1,193 @@
|
||||
from datetime import datetime
|
||||
|
||||
from dateutil.tz import gettz
|
||||
import numpy as np
|
||||
import pytest
|
||||
import pytz
|
||||
|
||||
from pandas._libs.tslibs import (
|
||||
OutOfBoundsDatetime,
|
||||
Timestamp,
|
||||
conversion,
|
||||
)
|
||||
from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
|
||||
import pandas.util._test_decorators as td
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestTimestampReplace:
|
||||
def test_replace_out_of_pydatetime_bounds(self):
|
||||
# GH#50348
|
||||
ts = Timestamp("2016-01-01").as_unit("ns")
|
||||
|
||||
msg = "Out of bounds timestamp: 99999-01-01 00:00:00 with frequency 'ns'"
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
ts.replace(year=99_999)
|
||||
|
||||
ts = ts.as_unit("ms")
|
||||
result = ts.replace(year=99_999)
|
||||
assert result.year == 99_999
|
||||
assert result._value == Timestamp(np.datetime64("99999-01-01", "ms"))._value
|
||||
|
||||
def test_replace_non_nano(self):
|
||||
ts = Timestamp._from_value_and_reso(
|
||||
91514880000000000, NpyDatetimeUnit.NPY_FR_us.value, None
|
||||
)
|
||||
assert ts.to_pydatetime() == datetime(4869, 12, 28)
|
||||
|
||||
result = ts.replace(year=4900)
|
||||
assert result._creso == ts._creso
|
||||
assert result.to_pydatetime() == datetime(4900, 12, 28)
|
||||
|
||||
def test_replace_naive(self):
|
||||
# GH#14621, GH#7825
|
||||
ts = Timestamp("2016-01-01 09:00:00")
|
||||
result = ts.replace(hour=0)
|
||||
expected = Timestamp("2016-01-01 00:00:00")
|
||||
assert result == expected
|
||||
|
||||
def test_replace_aware(self, tz_aware_fixture):
|
||||
tz = tz_aware_fixture
|
||||
# GH#14621, GH#7825
|
||||
# replacing datetime components with and w/o presence of a timezone
|
||||
ts = Timestamp("2016-01-01 09:00:00", tz=tz)
|
||||
result = ts.replace(hour=0)
|
||||
expected = Timestamp("2016-01-01 00:00:00", tz=tz)
|
||||
assert result == expected
|
||||
|
||||
def test_replace_preserves_nanos(self, tz_aware_fixture):
|
||||
tz = tz_aware_fixture
|
||||
# GH#14621, GH#7825
|
||||
ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
|
||||
result = ts.replace(hour=0)
|
||||
expected = Timestamp("2016-01-01 00:00:00.000000123", tz=tz)
|
||||
assert result == expected
|
||||
|
||||
def test_replace_multiple(self, tz_aware_fixture):
|
||||
tz = tz_aware_fixture
|
||||
# GH#14621, GH#7825
|
||||
# replacing datetime components with and w/o presence of a timezone
|
||||
# test all
|
||||
ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
|
||||
result = ts.replace(
|
||||
year=2015,
|
||||
month=2,
|
||||
day=2,
|
||||
hour=0,
|
||||
minute=5,
|
||||
second=5,
|
||||
microsecond=5,
|
||||
nanosecond=5,
|
||||
)
|
||||
expected = Timestamp("2015-02-02 00:05:05.000005005", tz=tz)
|
||||
assert result == expected
|
||||
|
||||
def test_replace_invalid_kwarg(self, tz_aware_fixture):
|
||||
tz = tz_aware_fixture
|
||||
# GH#14621, GH#7825
|
||||
ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
|
||||
msg = r"replace\(\) got an unexpected keyword argument"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
ts.replace(foo=5)
|
||||
|
||||
def test_replace_integer_args(self, tz_aware_fixture):
|
||||
tz = tz_aware_fixture
|
||||
# GH#14621, GH#7825
|
||||
ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
|
||||
msg = "value must be an integer, received <class 'float'> for hour"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
ts.replace(hour=0.1)
|
||||
|
||||
def test_replace_tzinfo_equiv_tz_localize_none(self):
|
||||
# GH#14621, GH#7825
|
||||
# assert conversion to naive is the same as replacing tzinfo with None
|
||||
ts = Timestamp("2013-11-03 01:59:59.999999-0400", tz="US/Eastern")
|
||||
assert ts.tz_localize(None) == ts.replace(tzinfo=None)
|
||||
|
||||
@td.skip_if_windows
|
||||
def test_replace_tzinfo(self):
|
||||
# GH#15683
|
||||
dt = datetime(2016, 3, 27, 1)
|
||||
tzinfo = pytz.timezone("CET").localize(dt, is_dst=False).tzinfo
|
||||
|
||||
result_dt = dt.replace(tzinfo=tzinfo)
|
||||
result_pd = Timestamp(dt).replace(tzinfo=tzinfo)
|
||||
|
||||
# datetime.timestamp() converts in the local timezone
|
||||
with tm.set_timezone("UTC"):
|
||||
assert result_dt.timestamp() == result_pd.timestamp()
|
||||
|
||||
assert result_dt == result_pd
|
||||
assert result_dt == result_pd.to_pydatetime()
|
||||
|
||||
result_dt = dt.replace(tzinfo=tzinfo).replace(tzinfo=None)
|
||||
result_pd = Timestamp(dt).replace(tzinfo=tzinfo).replace(tzinfo=None)
|
||||
|
||||
# datetime.timestamp() converts in the local timezone
|
||||
with tm.set_timezone("UTC"):
|
||||
assert result_dt.timestamp() == result_pd.timestamp()
|
||||
|
||||
assert result_dt == result_pd
|
||||
assert result_dt == result_pd.to_pydatetime()
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tz, normalize",
|
||||
[
|
||||
(pytz.timezone("US/Eastern"), lambda x: x.tzinfo.normalize(x)),
|
||||
(gettz("US/Eastern"), lambda x: x),
|
||||
],
|
||||
)
|
||||
def test_replace_across_dst(self, tz, normalize):
|
||||
# GH#18319 check that 1) timezone is correctly normalized and
|
||||
# 2) that hour is not incorrectly changed by this normalization
|
||||
ts_naive = Timestamp("2017-12-03 16:03:30")
|
||||
ts_aware = conversion.localize_pydatetime(ts_naive, tz)
|
||||
|
||||
# Preliminary sanity-check
|
||||
assert ts_aware == normalize(ts_aware)
|
||||
|
||||
# Replace across DST boundary
|
||||
ts2 = ts_aware.replace(month=6)
|
||||
|
||||
# Check that `replace` preserves hour literal
|
||||
assert (ts2.hour, ts2.minute) == (ts_aware.hour, ts_aware.minute)
|
||||
|
||||
# Check that post-replace object is appropriately normalized
|
||||
ts2b = normalize(ts2)
|
||||
assert ts2 == ts2b
|
||||
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_replace_dst_border(self, unit):
|
||||
# Gh 7825
|
||||
t = Timestamp("2013-11-3", tz="America/Chicago").as_unit(unit)
|
||||
result = t.replace(hour=3)
|
||||
expected = Timestamp("2013-11-3 03:00:00", tz="America/Chicago")
|
||||
assert result == expected
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
@pytest.mark.parametrize("fold", [0, 1])
|
||||
@pytest.mark.parametrize("tz", ["dateutil/Europe/London", "Europe/London"])
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_replace_dst_fold(self, fold, tz, unit):
|
||||
# GH 25017
|
||||
d = datetime(2019, 10, 27, 2, 30)
|
||||
ts = Timestamp(d, tz=tz).as_unit(unit)
|
||||
result = ts.replace(hour=1, fold=fold)
|
||||
expected = Timestamp(datetime(2019, 10, 27, 1, 30)).tz_localize(
|
||||
tz, ambiguous=not fold
|
||||
)
|
||||
assert result == expected
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
@pytest.mark.parametrize("fold", [0, 1])
|
||||
def test_replace_preserves_fold(self, fold):
|
||||
# GH#37610. Check that replace preserves Timestamp fold property
|
||||
tz = gettz("Europe/Moscow")
|
||||
|
||||
ts = Timestamp(
|
||||
year=2009, month=10, day=25, hour=2, minute=30, fold=fold, tzinfo=tz
|
||||
)
|
||||
ts_replaced = ts.replace(second=1)
|
||||
|
||||
assert ts_replaced.fold == fold
|
||||
@@ -0,0 +1,383 @@
|
||||
from hypothesis import (
|
||||
given,
|
||||
strategies as st,
|
||||
)
|
||||
import numpy as np
|
||||
import pytest
|
||||
import pytz
|
||||
|
||||
from pandas._libs import lib
|
||||
from pandas._libs.tslibs import (
|
||||
NaT,
|
||||
OutOfBoundsDatetime,
|
||||
Timedelta,
|
||||
Timestamp,
|
||||
iNaT,
|
||||
to_offset,
|
||||
)
|
||||
from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
|
||||
from pandas._libs.tslibs.period import INVALID_FREQ_ERR_MSG
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestTimestampRound:
|
||||
def test_round_division_by_zero_raises(self):
|
||||
ts = Timestamp("2016-01-01")
|
||||
|
||||
msg = "Division by zero in rounding"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
ts.round("0ns")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"timestamp, freq, expected",
|
||||
[
|
||||
("20130101 09:10:11", "D", "20130101"),
|
||||
("20130101 19:10:11", "D", "20130102"),
|
||||
("20130201 12:00:00", "D", "20130202"),
|
||||
("20130104 12:00:00", "D", "20130105"),
|
||||
("2000-01-05 05:09:15.13", "D", "2000-01-05 00:00:00"),
|
||||
("2000-01-05 05:09:15.13", "h", "2000-01-05 05:00:00"),
|
||||
("2000-01-05 05:09:15.13", "s", "2000-01-05 05:09:15"),
|
||||
],
|
||||
)
|
||||
def test_round_frequencies(self, timestamp, freq, expected):
|
||||
dt = Timestamp(timestamp)
|
||||
result = dt.round(freq)
|
||||
expected = Timestamp(expected)
|
||||
assert result == expected
|
||||
|
||||
def test_round_tzaware(self):
|
||||
dt = Timestamp("20130101 09:10:11", tz="US/Eastern")
|
||||
result = dt.round("D")
|
||||
expected = Timestamp("20130101", tz="US/Eastern")
|
||||
assert result == expected
|
||||
|
||||
dt = Timestamp("20130101 09:10:11", tz="US/Eastern")
|
||||
result = dt.round("s")
|
||||
assert result == dt
|
||||
|
||||
def test_round_30min(self):
|
||||
# round
|
||||
dt = Timestamp("20130104 12:32:00")
|
||||
result = dt.round("30Min")
|
||||
expected = Timestamp("20130104 12:30:00")
|
||||
assert result == expected
|
||||
|
||||
def test_round_subsecond(self):
|
||||
# GH#14440 & GH#15578
|
||||
result = Timestamp("2016-10-17 12:00:00.0015").round("ms")
|
||||
expected = Timestamp("2016-10-17 12:00:00.002000")
|
||||
assert result == expected
|
||||
|
||||
result = Timestamp("2016-10-17 12:00:00.00149").round("ms")
|
||||
expected = Timestamp("2016-10-17 12:00:00.001000")
|
||||
assert result == expected
|
||||
|
||||
ts = Timestamp("2016-10-17 12:00:00.0015")
|
||||
for freq in ["us", "ns"]:
|
||||
assert ts == ts.round(freq)
|
||||
|
||||
result = Timestamp("2016-10-17 12:00:00.001501031").round("10ns")
|
||||
expected = Timestamp("2016-10-17 12:00:00.001501030")
|
||||
assert result == expected
|
||||
|
||||
def test_round_nonstandard_freq(self):
|
||||
with tm.assert_produces_warning(False):
|
||||
Timestamp("2016-10-17 12:00:00.001501031").round("1010ns")
|
||||
|
||||
def test_round_invalid_arg(self):
|
||||
stamp = Timestamp("2000-01-05 05:09:15.13")
|
||||
with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
|
||||
stamp.round("foo")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_input, rounder, freq, expected",
|
||||
[
|
||||
("2117-01-01 00:00:45", "floor", "15s", "2117-01-01 00:00:45"),
|
||||
("2117-01-01 00:00:45", "ceil", "15s", "2117-01-01 00:00:45"),
|
||||
(
|
||||
"2117-01-01 00:00:45.000000012",
|
||||
"floor",
|
||||
"10ns",
|
||||
"2117-01-01 00:00:45.000000010",
|
||||
),
|
||||
(
|
||||
"1823-01-01 00:00:01.000000012",
|
||||
"ceil",
|
||||
"10ns",
|
||||
"1823-01-01 00:00:01.000000020",
|
||||
),
|
||||
("1823-01-01 00:00:01", "floor", "1s", "1823-01-01 00:00:01"),
|
||||
("1823-01-01 00:00:01", "ceil", "1s", "1823-01-01 00:00:01"),
|
||||
("NaT", "floor", "1s", "NaT"),
|
||||
("NaT", "ceil", "1s", "NaT"),
|
||||
],
|
||||
)
|
||||
def test_ceil_floor_edge(self, test_input, rounder, freq, expected):
|
||||
dt = Timestamp(test_input)
|
||||
func = getattr(dt, rounder)
|
||||
result = func(freq)
|
||||
|
||||
if dt is NaT:
|
||||
assert result is NaT
|
||||
else:
|
||||
expected = Timestamp(expected)
|
||||
assert result == expected
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_input, freq, expected",
|
||||
[
|
||||
("2018-01-01 00:02:06", "2s", "2018-01-01 00:02:06"),
|
||||
("2018-01-01 00:02:00", "2min", "2018-01-01 00:02:00"),
|
||||
("2018-01-01 00:04:00", "4min", "2018-01-01 00:04:00"),
|
||||
("2018-01-01 00:15:00", "15min", "2018-01-01 00:15:00"),
|
||||
("2018-01-01 00:20:00", "20min", "2018-01-01 00:20:00"),
|
||||
("2018-01-01 03:00:00", "3h", "2018-01-01 03:00:00"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("rounder", ["ceil", "floor", "round"])
|
||||
def test_round_minute_freq(self, test_input, freq, expected, rounder):
|
||||
# Ensure timestamps that shouldn't round dont!
|
||||
# GH#21262
|
||||
|
||||
dt = Timestamp(test_input)
|
||||
expected = Timestamp(expected)
|
||||
func = getattr(dt, rounder)
|
||||
result = func(freq)
|
||||
assert result == expected
|
||||
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_ceil(self, unit):
|
||||
dt = Timestamp("20130101 09:10:11").as_unit(unit)
|
||||
result = dt.ceil("D")
|
||||
expected = Timestamp("20130102")
|
||||
assert result == expected
|
||||
assert result._creso == dt._creso
|
||||
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_floor(self, unit):
|
||||
dt = Timestamp("20130101 09:10:11").as_unit(unit)
|
||||
result = dt.floor("D")
|
||||
expected = Timestamp("20130101")
|
||||
assert result == expected
|
||||
assert result._creso == dt._creso
|
||||
|
||||
@pytest.mark.parametrize("method", ["ceil", "round", "floor"])
|
||||
@pytest.mark.parametrize(
|
||||
"unit",
|
||||
["ns", "us", "ms", "s"],
|
||||
)
|
||||
def test_round_dst_border_ambiguous(self, method, unit):
|
||||
# GH 18946 round near "fall back" DST
|
||||
ts = Timestamp("2017-10-29 00:00:00", tz="UTC").tz_convert("Europe/Madrid")
|
||||
ts = ts.as_unit(unit)
|
||||
#
|
||||
result = getattr(ts, method)("h", ambiguous=True)
|
||||
assert result == ts
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
result = getattr(ts, method)("h", ambiguous=False)
|
||||
expected = Timestamp("2017-10-29 01:00:00", tz="UTC").tz_convert(
|
||||
"Europe/Madrid"
|
||||
)
|
||||
assert result == expected
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
result = getattr(ts, method)("h", ambiguous="NaT")
|
||||
assert result is NaT
|
||||
|
||||
msg = "Cannot infer dst time"
|
||||
with pytest.raises(pytz.AmbiguousTimeError, match=msg):
|
||||
getattr(ts, method)("h", ambiguous="raise")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"method, ts_str, freq",
|
||||
[
|
||||
["ceil", "2018-03-11 01:59:00-0600", "5min"],
|
||||
["round", "2018-03-11 01:59:00-0600", "5min"],
|
||||
["floor", "2018-03-11 03:01:00-0500", "2h"],
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"unit",
|
||||
["ns", "us", "ms", "s"],
|
||||
)
|
||||
def test_round_dst_border_nonexistent(self, method, ts_str, freq, unit):
|
||||
# GH 23324 round near "spring forward" DST
|
||||
ts = Timestamp(ts_str, tz="America/Chicago").as_unit(unit)
|
||||
result = getattr(ts, method)(freq, nonexistent="shift_forward")
|
||||
expected = Timestamp("2018-03-11 03:00:00", tz="America/Chicago")
|
||||
assert result == expected
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
result = getattr(ts, method)(freq, nonexistent="NaT")
|
||||
assert result is NaT
|
||||
|
||||
msg = "2018-03-11 02:00:00"
|
||||
with pytest.raises(pytz.NonExistentTimeError, match=msg):
|
||||
getattr(ts, method)(freq, nonexistent="raise")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"timestamp",
|
||||
[
|
||||
"2018-01-01 0:0:0.124999360",
|
||||
"2018-01-01 0:0:0.125000367",
|
||||
"2018-01-01 0:0:0.125500",
|
||||
"2018-01-01 0:0:0.126500",
|
||||
"2018-01-01 12:00:00",
|
||||
"2019-01-01 12:00:00",
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"freq",
|
||||
[
|
||||
"2ns",
|
||||
"3ns",
|
||||
"4ns",
|
||||
"5ns",
|
||||
"6ns",
|
||||
"7ns",
|
||||
"250ns",
|
||||
"500ns",
|
||||
"750ns",
|
||||
"1us",
|
||||
"19us",
|
||||
"250us",
|
||||
"500us",
|
||||
"750us",
|
||||
"1s",
|
||||
"2s",
|
||||
"3s",
|
||||
"1D",
|
||||
],
|
||||
)
|
||||
def test_round_int64(self, timestamp, freq):
|
||||
# check that all rounding modes are accurate to int64 precision
|
||||
# see GH#22591
|
||||
dt = Timestamp(timestamp).as_unit("ns")
|
||||
unit = to_offset(freq).nanos
|
||||
|
||||
# test floor
|
||||
result = dt.floor(freq)
|
||||
assert result._value % unit == 0, f"floor not a {freq} multiple"
|
||||
assert 0 <= dt._value - result._value < unit, "floor error"
|
||||
|
||||
# test ceil
|
||||
result = dt.ceil(freq)
|
||||
assert result._value % unit == 0, f"ceil not a {freq} multiple"
|
||||
assert 0 <= result._value - dt._value < unit, "ceil error"
|
||||
|
||||
# test round
|
||||
result = dt.round(freq)
|
||||
assert result._value % unit == 0, f"round not a {freq} multiple"
|
||||
assert abs(result._value - dt._value) <= unit // 2, "round error"
|
||||
if unit % 2 == 0 and abs(result._value - dt._value) == unit // 2:
|
||||
# round half to even
|
||||
assert result._value // unit % 2 == 0, "round half to even error"
|
||||
|
||||
def test_round_implementation_bounds(self):
|
||||
# See also: analogous test for Timedelta
|
||||
result = Timestamp.min.ceil("s")
|
||||
expected = Timestamp(1677, 9, 21, 0, 12, 44)
|
||||
assert result == expected
|
||||
|
||||
result = Timestamp.max.floor("s")
|
||||
expected = Timestamp.max - Timedelta(854775807)
|
||||
assert result == expected
|
||||
|
||||
msg = "Cannot round 1677-09-21 00:12:43.145224193 to freq=<Second>"
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
Timestamp.min.floor("s")
|
||||
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
Timestamp.min.round("s")
|
||||
|
||||
msg = "Cannot round 2262-04-11 23:47:16.854775807 to freq=<Second>"
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
Timestamp.max.ceil("s")
|
||||
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
Timestamp.max.round("s")
|
||||
|
||||
@given(val=st.integers(iNaT + 1, lib.i8max))
|
||||
@pytest.mark.parametrize(
|
||||
"method", [Timestamp.round, Timestamp.floor, Timestamp.ceil]
|
||||
)
|
||||
def test_round_sanity(self, val, method):
|
||||
cls = Timestamp
|
||||
err_cls = OutOfBoundsDatetime
|
||||
|
||||
val = np.int64(val)
|
||||
ts = cls(val)
|
||||
|
||||
def checker(ts, nanos, unit):
|
||||
# First check that we do raise in cases where we should
|
||||
if nanos == 1:
|
||||
pass
|
||||
else:
|
||||
div, mod = divmod(ts._value, nanos)
|
||||
diff = int(nanos - mod)
|
||||
lb = ts._value - mod
|
||||
assert lb <= ts._value # i.e. no overflows with python ints
|
||||
ub = ts._value + diff
|
||||
assert ub > ts._value # i.e. no overflows with python ints
|
||||
|
||||
msg = "without overflow"
|
||||
if mod == 0:
|
||||
# We should never be raising in this
|
||||
pass
|
||||
elif method is cls.ceil:
|
||||
if ub > cls.max._value:
|
||||
with pytest.raises(err_cls, match=msg):
|
||||
method(ts, unit)
|
||||
return
|
||||
elif method is cls.floor:
|
||||
if lb < cls.min._value:
|
||||
with pytest.raises(err_cls, match=msg):
|
||||
method(ts, unit)
|
||||
return
|
||||
elif mod >= diff:
|
||||
if ub > cls.max._value:
|
||||
with pytest.raises(err_cls, match=msg):
|
||||
method(ts, unit)
|
||||
return
|
||||
elif lb < cls.min._value:
|
||||
with pytest.raises(err_cls, match=msg):
|
||||
method(ts, unit)
|
||||
return
|
||||
|
||||
res = method(ts, unit)
|
||||
|
||||
td = res - ts
|
||||
diff = abs(td._value)
|
||||
assert diff < nanos
|
||||
assert res._value % nanos == 0
|
||||
|
||||
if method is cls.round:
|
||||
assert diff <= nanos / 2
|
||||
elif method is cls.floor:
|
||||
assert res <= ts
|
||||
elif method is cls.ceil:
|
||||
assert res >= ts
|
||||
|
||||
nanos = 1
|
||||
checker(ts, nanos, "ns")
|
||||
|
||||
nanos = 1000
|
||||
checker(ts, nanos, "us")
|
||||
|
||||
nanos = 1_000_000
|
||||
checker(ts, nanos, "ms")
|
||||
|
||||
nanos = 1_000_000_000
|
||||
checker(ts, nanos, "s")
|
||||
|
||||
nanos = 60 * 1_000_000_000
|
||||
checker(ts, nanos, "min")
|
||||
|
||||
nanos = 60 * 60 * 1_000_000_000
|
||||
checker(ts, nanos, "h")
|
||||
|
||||
nanos = 24 * 60 * 60 * 1_000_000_000
|
||||
checker(ts, nanos, "D")
|
||||
@@ -0,0 +1,31 @@
|
||||
# NB: This is for the Timestamp.timestamp *method* specifically, not
|
||||
# the Timestamp class in general.
|
||||
|
||||
from pytz import utc
|
||||
|
||||
from pandas._libs.tslibs import Timestamp
|
||||
import pandas.util._test_decorators as td
|
||||
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestTimestampMethod:
|
||||
@td.skip_if_windows
|
||||
def test_timestamp(self, fixed_now_ts):
|
||||
# GH#17329
|
||||
# tz-naive --> treat it as if it were UTC for purposes of timestamp()
|
||||
ts = fixed_now_ts
|
||||
uts = ts.replace(tzinfo=utc)
|
||||
assert ts.timestamp() == uts.timestamp()
|
||||
|
||||
tsc = Timestamp("2014-10-11 11:00:01.12345678", tz="US/Central")
|
||||
utsc = tsc.tz_convert("UTC")
|
||||
|
||||
# utsc is a different representation of the same time
|
||||
assert tsc.timestamp() == utsc.timestamp()
|
||||
|
||||
# datetime.timestamp() converts in the local timezone
|
||||
with tm.set_timezone("UTC"):
|
||||
# should agree with datetime.timestamp method
|
||||
dt = ts.to_pydatetime()
|
||||
assert dt.timestamp() == ts.timestamp()
|
||||
@@ -0,0 +1,28 @@
|
||||
from pandas import Timestamp
|
||||
|
||||
|
||||
class TestTimestampToJulianDate:
|
||||
def test_compare_1700(self):
|
||||
ts = Timestamp("1700-06-23")
|
||||
res = ts.to_julian_date()
|
||||
assert res == 2_342_145.5
|
||||
|
||||
def test_compare_2000(self):
|
||||
ts = Timestamp("2000-04-12")
|
||||
res = ts.to_julian_date()
|
||||
assert res == 2_451_646.5
|
||||
|
||||
def test_compare_2100(self):
|
||||
ts = Timestamp("2100-08-12")
|
||||
res = ts.to_julian_date()
|
||||
assert res == 2_488_292.5
|
||||
|
||||
def test_compare_hour01(self):
|
||||
ts = Timestamp("2000-08-12T01:00:00")
|
||||
res = ts.to_julian_date()
|
||||
assert res == 2_451_768.5416666666666666
|
||||
|
||||
def test_compare_hour13(self):
|
||||
ts = Timestamp("2000-08-12T13:00:00")
|
||||
res = ts.to_julian_date()
|
||||
assert res == 2_451_769.0416666666666666
|
||||
@@ -0,0 +1,81 @@
|
||||
from datetime import (
|
||||
datetime,
|
||||
timedelta,
|
||||
)
|
||||
|
||||
import pytz
|
||||
|
||||
from pandas._libs.tslibs.timezones import dateutil_gettz as gettz
|
||||
import pandas.util._test_decorators as td
|
||||
|
||||
from pandas import Timestamp
|
||||
import pandas._testing as tm
|
||||
|
||||
|
||||
class TestTimestampToPyDatetime:
|
||||
def test_to_pydatetime_fold(self):
|
||||
# GH#45087
|
||||
tzstr = "dateutil/usr/share/zoneinfo/America/Chicago"
|
||||
ts = Timestamp(year=2013, month=11, day=3, hour=1, minute=0, fold=1, tz=tzstr)
|
||||
dt = ts.to_pydatetime()
|
||||
assert dt.fold == 1
|
||||
|
||||
def test_to_pydatetime_nonzero_nano(self):
|
||||
ts = Timestamp("2011-01-01 9:00:00.123456789")
|
||||
|
||||
# Warn the user of data loss (nanoseconds).
|
||||
with tm.assert_produces_warning(UserWarning):
|
||||
expected = datetime(2011, 1, 1, 9, 0, 0, 123456)
|
||||
result = ts.to_pydatetime()
|
||||
assert result == expected
|
||||
|
||||
def test_timestamp_to_datetime(self):
|
||||
stamp = Timestamp("20090415", tz="US/Eastern")
|
||||
dtval = stamp.to_pydatetime()
|
||||
assert stamp == dtval
|
||||
assert stamp.tzinfo == dtval.tzinfo
|
||||
|
||||
def test_timestamp_to_pydatetime_dateutil(self):
|
||||
stamp = Timestamp("20090415", tz="dateutil/US/Eastern")
|
||||
dtval = stamp.to_pydatetime()
|
||||
assert stamp == dtval
|
||||
assert stamp.tzinfo == dtval.tzinfo
|
||||
|
||||
def test_timestamp_to_pydatetime_explicit_pytz(self):
|
||||
stamp = Timestamp("20090415", tz=pytz.timezone("US/Eastern"))
|
||||
dtval = stamp.to_pydatetime()
|
||||
assert stamp == dtval
|
||||
assert stamp.tzinfo == dtval.tzinfo
|
||||
|
||||
@td.skip_if_windows
|
||||
def test_timestamp_to_pydatetime_explicit_dateutil(self):
|
||||
stamp = Timestamp("20090415", tz=gettz("US/Eastern"))
|
||||
dtval = stamp.to_pydatetime()
|
||||
assert stamp == dtval
|
||||
assert stamp.tzinfo == dtval.tzinfo
|
||||
|
||||
def test_to_pydatetime_bijective(self):
|
||||
# Ensure that converting to datetime and back only loses precision
|
||||
# by going from nanoseconds to microseconds.
|
||||
exp_warning = None if Timestamp.max.nanosecond == 0 else UserWarning
|
||||
with tm.assert_produces_warning(exp_warning):
|
||||
pydt_max = Timestamp.max.to_pydatetime()
|
||||
|
||||
assert (
|
||||
Timestamp(pydt_max).as_unit("ns")._value / 1000
|
||||
== Timestamp.max._value / 1000
|
||||
)
|
||||
|
||||
exp_warning = None if Timestamp.min.nanosecond == 0 else UserWarning
|
||||
with tm.assert_produces_warning(exp_warning):
|
||||
pydt_min = Timestamp.min.to_pydatetime()
|
||||
|
||||
# The next assertion can be enabled once GH#39221 is merged
|
||||
# assert pydt_min < Timestamp.min # this is bc nanos are dropped
|
||||
tdus = timedelta(microseconds=1)
|
||||
assert pydt_min + tdus > Timestamp.min
|
||||
|
||||
assert (
|
||||
Timestamp(pydt_min + tdus).as_unit("ns")._value / 1000
|
||||
== Timestamp.min._value / 1000
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
import dateutil
|
||||
import pytest
|
||||
|
||||
from pandas._libs.tslibs import timezones
|
||||
import pandas.util._test_decorators as td
|
||||
|
||||
from pandas import Timestamp
|
||||
|
||||
|
||||
class TestTimestampTZConvert:
|
||||
@pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"])
|
||||
def test_astimezone(self, tzstr):
|
||||
# astimezone is an alias for tz_convert, so keep it with
|
||||
# the tz_convert tests
|
||||
utcdate = Timestamp("3/11/2012 22:00", tz="UTC")
|
||||
expected = utcdate.tz_convert(tzstr)
|
||||
result = utcdate.astimezone(tzstr)
|
||||
assert expected == result
|
||||
assert isinstance(result, Timestamp)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stamp",
|
||||
[
|
||||
"2014-02-01 09:00",
|
||||
"2014-07-08 09:00",
|
||||
"2014-11-01 17:00",
|
||||
"2014-11-05 00:00",
|
||||
],
|
||||
)
|
||||
def test_tz_convert_roundtrip(self, stamp, tz_aware_fixture):
|
||||
tz = tz_aware_fixture
|
||||
|
||||
ts = Timestamp(stamp, tz="UTC")
|
||||
converted = ts.tz_convert(tz)
|
||||
|
||||
reset = converted.tz_convert(None)
|
||||
assert reset == Timestamp(stamp)
|
||||
assert reset.tzinfo is None
|
||||
assert reset == converted.tz_convert("UTC").tz_localize(None)
|
||||
|
||||
@td.skip_if_windows
|
||||
def test_tz_convert_utc_with_system_utc(self):
|
||||
# from system utc to real utc
|
||||
ts = Timestamp("2001-01-05 11:56", tz=timezones.maybe_get_tz("dateutil/UTC"))
|
||||
# check that the time hasn't changed.
|
||||
assert ts == ts.tz_convert(dateutil.tz.tzutc())
|
||||
|
||||
# from system utc to real utc
|
||||
ts = Timestamp("2001-01-05 11:56", tz=timezones.maybe_get_tz("dateutil/UTC"))
|
||||
# check that the time hasn't changed.
|
||||
assert ts == ts.tz_convert(dateutil.tz.tzutc())
|
||||
@@ -0,0 +1,351 @@
|
||||
from datetime import timedelta
|
||||
import re
|
||||
|
||||
from dateutil.tz import gettz
|
||||
import pytest
|
||||
import pytz
|
||||
from pytz.exceptions import (
|
||||
AmbiguousTimeError,
|
||||
NonExistentTimeError,
|
||||
)
|
||||
|
||||
from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
|
||||
from pandas.errors import OutOfBoundsDatetime
|
||||
|
||||
from pandas import (
|
||||
NaT,
|
||||
Timestamp,
|
||||
)
|
||||
|
||||
try:
|
||||
from zoneinfo import ZoneInfo
|
||||
except ImportError:
|
||||
# Cannot assign to a type
|
||||
ZoneInfo = None # type: ignore[misc, assignment]
|
||||
|
||||
|
||||
class TestTimestampTZLocalize:
|
||||
@pytest.mark.skip_ubsan
|
||||
def test_tz_localize_pushes_out_of_bounds(self):
|
||||
# GH#12677
|
||||
# tz_localize that pushes away from the boundary is OK
|
||||
msg = (
|
||||
f"Converting {Timestamp.min.strftime('%Y-%m-%d %H:%M:%S')} "
|
||||
f"underflows past {Timestamp.min}"
|
||||
)
|
||||
pac = Timestamp.min.tz_localize("US/Pacific")
|
||||
assert pac._value > Timestamp.min._value
|
||||
pac.tz_convert("Asia/Tokyo") # tz_convert doesn't change value
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
Timestamp.min.tz_localize("Asia/Tokyo")
|
||||
|
||||
# tz_localize that pushes away from the boundary is OK
|
||||
msg = (
|
||||
f"Converting {Timestamp.max.strftime('%Y-%m-%d %H:%M:%S')} "
|
||||
f"overflows past {Timestamp.max}"
|
||||
)
|
||||
tokyo = Timestamp.max.tz_localize("Asia/Tokyo")
|
||||
assert tokyo._value < Timestamp.max._value
|
||||
tokyo.tz_convert("US/Pacific") # tz_convert doesn't change value
|
||||
with pytest.raises(OutOfBoundsDatetime, match=msg):
|
||||
Timestamp.max.tz_localize("US/Pacific")
|
||||
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_tz_localize_ambiguous_bool(self, unit):
|
||||
# make sure that we are correctly accepting bool values as ambiguous
|
||||
# GH#14402
|
||||
ts = Timestamp("2015-11-01 01:00:03").as_unit(unit)
|
||||
expected0 = Timestamp("2015-11-01 01:00:03-0500", tz="US/Central")
|
||||
expected1 = Timestamp("2015-11-01 01:00:03-0600", tz="US/Central")
|
||||
|
||||
msg = "Cannot infer dst time from 2015-11-01 01:00:03"
|
||||
with pytest.raises(pytz.AmbiguousTimeError, match=msg):
|
||||
ts.tz_localize("US/Central")
|
||||
|
||||
with pytest.raises(pytz.AmbiguousTimeError, match=msg):
|
||||
ts.tz_localize("dateutil/US/Central")
|
||||
|
||||
if ZoneInfo is not None:
|
||||
try:
|
||||
tz = ZoneInfo("US/Central")
|
||||
except KeyError:
|
||||
# no tzdata
|
||||
pass
|
||||
else:
|
||||
with pytest.raises(pytz.AmbiguousTimeError, match=msg):
|
||||
ts.tz_localize(tz)
|
||||
|
||||
result = ts.tz_localize("US/Central", ambiguous=True)
|
||||
assert result == expected0
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
result = ts.tz_localize("US/Central", ambiguous=False)
|
||||
assert result == expected1
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
def test_tz_localize_ambiguous(self):
|
||||
ts = Timestamp("2014-11-02 01:00")
|
||||
ts_dst = ts.tz_localize("US/Eastern", ambiguous=True)
|
||||
ts_no_dst = ts.tz_localize("US/Eastern", ambiguous=False)
|
||||
|
||||
assert ts_no_dst._value - ts_dst._value == 3600
|
||||
msg = re.escape(
|
||||
"'ambiguous' parameter must be one of: "
|
||||
"True, False, 'NaT', 'raise' (default)"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
ts.tz_localize("US/Eastern", ambiguous="infer")
|
||||
|
||||
# GH#8025
|
||||
msg = "Cannot localize tz-aware Timestamp, use tz_convert for conversions"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
Timestamp("2011-01-01", tz="US/Eastern").tz_localize("Asia/Tokyo")
|
||||
|
||||
msg = "Cannot convert tz-naive Timestamp, use tz_localize to localize"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
Timestamp("2011-01-01").tz_convert("Asia/Tokyo")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stamp, tz",
|
||||
[
|
||||
("2015-03-08 02:00", "US/Eastern"),
|
||||
("2015-03-08 02:30", "US/Pacific"),
|
||||
("2015-03-29 02:00", "Europe/Paris"),
|
||||
("2015-03-29 02:30", "Europe/Belgrade"),
|
||||
],
|
||||
)
|
||||
def test_tz_localize_nonexistent(self, stamp, tz):
|
||||
# GH#13057
|
||||
ts = Timestamp(stamp)
|
||||
with pytest.raises(NonExistentTimeError, match=stamp):
|
||||
ts.tz_localize(tz)
|
||||
# GH 22644
|
||||
with pytest.raises(NonExistentTimeError, match=stamp):
|
||||
ts.tz_localize(tz, nonexistent="raise")
|
||||
assert ts.tz_localize(tz, nonexistent="NaT") is NaT
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stamp, tz, forward_expected, backward_expected",
|
||||
[
|
||||
(
|
||||
"2015-03-29 02:00:00",
|
||||
"Europe/Warsaw",
|
||||
"2015-03-29 03:00:00",
|
||||
"2015-03-29 01:59:59",
|
||||
), # utc+1 -> utc+2
|
||||
(
|
||||
"2023-03-12 02:00:00",
|
||||
"America/Los_Angeles",
|
||||
"2023-03-12 03:00:00",
|
||||
"2023-03-12 01:59:59",
|
||||
), # utc-8 -> utc-7
|
||||
(
|
||||
"2023-03-26 01:00:00",
|
||||
"Europe/London",
|
||||
"2023-03-26 02:00:00",
|
||||
"2023-03-26 00:59:59",
|
||||
), # utc+0 -> utc+1
|
||||
(
|
||||
"2023-03-26 00:00:00",
|
||||
"Atlantic/Azores",
|
||||
"2023-03-26 01:00:00",
|
||||
"2023-03-25 23:59:59",
|
||||
), # utc-1 -> utc+0
|
||||
],
|
||||
)
|
||||
def test_tz_localize_nonexistent_shift(
|
||||
self, stamp, tz, forward_expected, backward_expected
|
||||
):
|
||||
ts = Timestamp(stamp)
|
||||
forward_ts = ts.tz_localize(tz, nonexistent="shift_forward")
|
||||
assert forward_ts == Timestamp(forward_expected, tz=tz)
|
||||
backward_ts = ts.tz_localize(tz, nonexistent="shift_backward")
|
||||
assert backward_ts == Timestamp(backward_expected, tz=tz)
|
||||
|
||||
def test_tz_localize_ambiguous_raise(self):
|
||||
# GH#13057
|
||||
ts = Timestamp("2015-11-1 01:00")
|
||||
msg = "Cannot infer dst time from 2015-11-01 01:00:00,"
|
||||
with pytest.raises(AmbiguousTimeError, match=msg):
|
||||
ts.tz_localize("US/Pacific", ambiguous="raise")
|
||||
|
||||
def test_tz_localize_nonexistent_invalid_arg(self, warsaw):
|
||||
# GH 22644
|
||||
tz = warsaw
|
||||
ts = Timestamp("2015-03-29 02:00:00")
|
||||
msg = (
|
||||
"The nonexistent argument must be one of 'raise', 'NaT', "
|
||||
"'shift_forward', 'shift_backward' or a timedelta object"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
ts.tz_localize(tz, nonexistent="foo")
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"stamp",
|
||||
[
|
||||
"2014-02-01 09:00",
|
||||
"2014-07-08 09:00",
|
||||
"2014-11-01 17:00",
|
||||
"2014-11-05 00:00",
|
||||
],
|
||||
)
|
||||
def test_tz_localize_roundtrip(self, stamp, tz_aware_fixture):
|
||||
tz = tz_aware_fixture
|
||||
ts = Timestamp(stamp)
|
||||
localized = ts.tz_localize(tz)
|
||||
assert localized == Timestamp(stamp, tz=tz)
|
||||
|
||||
msg = "Cannot localize tz-aware Timestamp"
|
||||
with pytest.raises(TypeError, match=msg):
|
||||
localized.tz_localize(tz)
|
||||
|
||||
reset = localized.tz_localize(None)
|
||||
assert reset == ts
|
||||
assert reset.tzinfo is None
|
||||
|
||||
def test_tz_localize_ambiguous_compat(self):
|
||||
# validate that pytz and dateutil are compat for dst
|
||||
# when the transition happens
|
||||
naive = Timestamp("2013-10-27 01:00:00")
|
||||
|
||||
pytz_zone = "Europe/London"
|
||||
dateutil_zone = "dateutil/Europe/London"
|
||||
result_pytz = naive.tz_localize(pytz_zone, ambiguous=False)
|
||||
result_dateutil = naive.tz_localize(dateutil_zone, ambiguous=False)
|
||||
assert result_pytz._value == result_dateutil._value
|
||||
assert result_pytz._value == 1382835600
|
||||
|
||||
# fixed ambiguous behavior
|
||||
# see gh-14621, GH#45087
|
||||
assert result_pytz.to_pydatetime().tzname() == "GMT"
|
||||
assert result_dateutil.to_pydatetime().tzname() == "GMT"
|
||||
assert str(result_pytz) == str(result_dateutil)
|
||||
|
||||
# 1 hour difference
|
||||
result_pytz = naive.tz_localize(pytz_zone, ambiguous=True)
|
||||
result_dateutil = naive.tz_localize(dateutil_zone, ambiguous=True)
|
||||
assert result_pytz._value == result_dateutil._value
|
||||
assert result_pytz._value == 1382832000
|
||||
|
||||
# see gh-14621
|
||||
assert str(result_pytz) == str(result_dateutil)
|
||||
assert (
|
||||
result_pytz.to_pydatetime().tzname()
|
||||
== result_dateutil.to_pydatetime().tzname()
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tz",
|
||||
[
|
||||
pytz.timezone("US/Eastern"),
|
||||
gettz("US/Eastern"),
|
||||
"US/Eastern",
|
||||
"dateutil/US/Eastern",
|
||||
],
|
||||
)
|
||||
def test_timestamp_tz_localize(self, tz):
|
||||
stamp = Timestamp("3/11/2012 04:00")
|
||||
|
||||
result = stamp.tz_localize(tz)
|
||||
expected = Timestamp("3/11/2012 04:00", tz=tz)
|
||||
assert result.hour == expected.hour
|
||||
assert result == expected
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"start_ts, tz, end_ts, shift",
|
||||
[
|
||||
["2015-03-29 02:20:00", "Europe/Warsaw", "2015-03-29 03:00:00", "forward"],
|
||||
[
|
||||
"2015-03-29 02:20:00",
|
||||
"Europe/Warsaw",
|
||||
"2015-03-29 01:59:59.999999999",
|
||||
"backward",
|
||||
],
|
||||
[
|
||||
"2015-03-29 02:20:00",
|
||||
"Europe/Warsaw",
|
||||
"2015-03-29 03:20:00",
|
||||
timedelta(hours=1),
|
||||
],
|
||||
[
|
||||
"2015-03-29 02:20:00",
|
||||
"Europe/Warsaw",
|
||||
"2015-03-29 01:20:00",
|
||||
timedelta(hours=-1),
|
||||
],
|
||||
["2018-03-11 02:33:00", "US/Pacific", "2018-03-11 03:00:00", "forward"],
|
||||
[
|
||||
"2018-03-11 02:33:00",
|
||||
"US/Pacific",
|
||||
"2018-03-11 01:59:59.999999999",
|
||||
"backward",
|
||||
],
|
||||
[
|
||||
"2018-03-11 02:33:00",
|
||||
"US/Pacific",
|
||||
"2018-03-11 03:33:00",
|
||||
timedelta(hours=1),
|
||||
],
|
||||
[
|
||||
"2018-03-11 02:33:00",
|
||||
"US/Pacific",
|
||||
"2018-03-11 01:33:00",
|
||||
timedelta(hours=-1),
|
||||
],
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize("tz_type", ["", "dateutil/"])
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_timestamp_tz_localize_nonexistent_shift(
|
||||
self, start_ts, tz, end_ts, shift, tz_type, unit
|
||||
):
|
||||
# GH 8917, 24466
|
||||
tz = tz_type + tz
|
||||
if isinstance(shift, str):
|
||||
shift = "shift_" + shift
|
||||
ts = Timestamp(start_ts).as_unit(unit)
|
||||
result = ts.tz_localize(tz, nonexistent=shift)
|
||||
expected = Timestamp(end_ts).tz_localize(tz)
|
||||
|
||||
if unit == "us":
|
||||
assert result == expected.replace(nanosecond=0)
|
||||
elif unit == "ms":
|
||||
micros = expected.microsecond - expected.microsecond % 1000
|
||||
assert result == expected.replace(microsecond=micros, nanosecond=0)
|
||||
elif unit == "s":
|
||||
assert result == expected.replace(microsecond=0, nanosecond=0)
|
||||
else:
|
||||
assert result == expected
|
||||
assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
|
||||
|
||||
@pytest.mark.parametrize("offset", [-1, 1])
|
||||
def test_timestamp_tz_localize_nonexistent_shift_invalid(self, offset, warsaw):
|
||||
# GH 8917, 24466
|
||||
tz = warsaw
|
||||
ts = Timestamp("2015-03-29 02:20:00")
|
||||
msg = "The provided timedelta will relocalize on a nonexistent time"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
ts.tz_localize(tz, nonexistent=timedelta(seconds=offset))
|
||||
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_timestamp_tz_localize_nonexistent_NaT(self, warsaw, unit):
|
||||
# GH 8917
|
||||
tz = warsaw
|
||||
ts = Timestamp("2015-03-29 02:20:00").as_unit(unit)
|
||||
result = ts.tz_localize(tz, nonexistent="NaT")
|
||||
assert result is NaT
|
||||
|
||||
@pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
|
||||
def test_timestamp_tz_localize_nonexistent_raise(self, warsaw, unit):
|
||||
# GH 8917
|
||||
tz = warsaw
|
||||
ts = Timestamp("2015-03-29 02:20:00").as_unit(unit)
|
||||
msg = "2015-03-29 02:20:00"
|
||||
with pytest.raises(pytz.NonExistentTimeError, match=msg):
|
||||
ts.tz_localize(tz, nonexistent="raise")
|
||||
msg = (
|
||||
"The nonexistent argument must be one of 'raise', 'NaT', "
|
||||
"'shift_forward', 'shift_backward' or a timedelta object"
|
||||
)
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
ts.tz_localize(tz, nonexistent="foo")
|
||||
Reference in New Issue
Block a user