@@ -713,6 +713,11 @@ def dt64(self, reso):
713
713
def ts (self , dt64 ):
714
714
return Timestamp ._from_dt64 (dt64 )
715
715
716
+ @pytest .fixture
717
+ def ts_tz (self , ts , tz_aware_fixture ):
718
+ tz = maybe_get_tz (tz_aware_fixture )
719
+ return Timestamp ._from_value_and_reso (ts .value , ts ._reso , tz )
720
+
716
721
def test_non_nano_construction (self , dt64 , ts , reso ):
717
722
assert ts .value == dt64 .view ("i8" )
718
723
@@ -897,6 +902,70 @@ def test_addsub_timedeltalike_non_nano(self, dt64, ts, td):
897
902
assert result ._reso == ts ._reso
898
903
assert result == expected
899
904
905
+ @pytest .mark .xfail (reason = "tz_localize not yet implemented for non-nano" )
906
+ def test_addsub_offset (self , ts_tz ):
907
+ # specifically non-Tick offset
908
+ off = offsets .YearBegin (1 )
909
+ result = ts_tz + off
910
+
911
+ assert isinstance (result , Timestamp )
912
+ assert result ._reso == ts_tz ._reso
913
+ # If ts_tz is ever on the last day of the year, the year would be
914
+ # incremented by one
915
+ assert result .year == ts_tz .year
916
+ assert result .day == 31
917
+ assert result .month == 12
918
+ assert tz_compare (result .tz , ts_tz .tz )
919
+
920
+ result = ts_tz - off
921
+
922
+ assert isinstance (result , Timestamp )
923
+ assert result ._reso == ts_tz ._reso
924
+ assert result .year == ts_tz .year - 1
925
+ assert result .day == 31
926
+ assert result .month == 12
927
+ assert tz_compare (result .tz , ts_tz .tz )
928
+
929
+ def test_sub_datetimelike_mismatched_reso (self , ts_tz ):
930
+ # case with non-lossy rounding
931
+ ts = ts_tz
932
+
933
+ # choose a unit for `other` that doesn't match ts_tz's;
934
+ # this construction ensures we get cases with other._reso < ts._reso
935
+ # and cases with other._reso > ts._reso
936
+ unit = {
937
+ NpyDatetimeUnit .NPY_FR_us .value : "ms" ,
938
+ NpyDatetimeUnit .NPY_FR_ms .value : "s" ,
939
+ NpyDatetimeUnit .NPY_FR_s .value : "us" ,
940
+ }[ts ._reso ]
941
+ other = ts ._as_unit (unit )
942
+ assert other ._reso != ts ._reso
943
+
944
+ result = ts - other
945
+ assert isinstance (result , Timedelta )
946
+ assert result .value == 0
947
+ assert result ._reso == min (ts ._reso , other ._reso )
948
+
949
+ result = other - ts
950
+ assert isinstance (result , Timedelta )
951
+ assert result .value == 0
952
+ assert result ._reso == min (ts ._reso , other ._reso )
953
+
954
+ msg = "Timestamp subtraction with mismatched resolutions"
955
+ if ts ._reso < other ._reso :
956
+ # Case where rounding is lossy
957
+ other2 = other + Timedelta ._from_value_and_reso (1 , other ._reso )
958
+ with pytest .raises (ValueError , match = msg ):
959
+ ts - other2
960
+ with pytest .raises (ValueError , match = msg ):
961
+ other2 - ts
962
+ else :
963
+ ts2 = ts + Timedelta ._from_value_and_reso (1 , ts ._reso )
964
+ with pytest .raises (ValueError , match = msg ):
965
+ ts2 - other
966
+ with pytest .raises (ValueError , match = msg ):
967
+ other - ts2
968
+
900
969
901
970
class TestAsUnit :
902
971
def test_as_unit (self ):
0 commit comments