@@ -48,13 +48,20 @@ def wrapper(self, other):
48
48
elif isinstance (other , np .datetime64 ):
49
49
other = as_timestamp (other )
50
50
51
+ tz = getattr (other , 'tzinfo' , None )
51
52
result = func (self , other )
52
53
53
54
if self .normalize :
54
55
result = tslib .normalize_date (result )
55
56
56
57
if isinstance (other , Timestamp ) and not isinstance (result , Timestamp ):
57
58
result = as_timestamp (result )
59
+
60
+ if tz is not None :
61
+ if isinstance (result , Timestamp ) and result .tzinfo is None :
62
+ result = result .tz_localize (tz )
63
+ elif isinstance (result , datetime ) and result .tzinfo is None :
64
+ result = tz .localize (result )
58
65
return result
59
66
return wrapper
60
67
@@ -570,6 +577,11 @@ def _to_dt64(dt, dtype='datetime64'):
570
577
# > np.datetime64(dt.datetime(2013,5,1),dtype='datetime64[D]')
571
578
# numpy.datetime64('2013-05-01T02:00:00.000000+0200')
572
579
# Thus astype is needed to cast datetime to datetime64[D]
580
+
581
+ if getattr (dt , 'tzinfo' , None ) is not None :
582
+ i8 = tslib .pydt_to_i8 (dt )
583
+ dt = tslib .tz_convert_single (i8 , 'UTC' , dt .tzinfo )
584
+ dt = Timestamp (dt )
573
585
dt = np .datetime64 (dt )
574
586
if dt .dtype .name != dtype :
575
587
dt = dt .astype (dtype )
@@ -966,13 +978,18 @@ def apply(self, other):
966
978
months = self .n + 1
967
979
968
980
other = self .getOffsetOfMonth (as_datetime (other ) + relativedelta (months = months , day = 1 ))
969
- other = datetime (other .year , other .month , other .day ,
970
- base .hour , base .minute , base .second , base .microsecond )
981
+ other = datetime (other .year , other .month , other .day , base .hour ,
982
+ base .minute , base .second , base .microsecond )
983
+ if getattr (other , 'tzinfo' , None ) is not None :
984
+ other = other .tzinfo .localize (other )
971
985
return other
972
986
973
987
def getOffsetOfMonth (self , dt ):
974
988
w = Week (weekday = self .weekday )
989
+
975
990
d = datetime (dt .year , dt .month , 1 )
991
+ if getattr (dt , 'tzinfo' , None ) is not None :
992
+ d = dt .tzinfo .localize (d )
976
993
977
994
d = w .rollforward (d )
978
995
@@ -985,6 +1002,8 @@ def onOffset(self, dt):
985
1002
if self .normalize and not _is_normalized (dt ):
986
1003
return False
987
1004
d = datetime (dt .year , dt .month , dt .day )
1005
+ if getattr (dt , 'tzinfo' , None ) is not None :
1006
+ d = dt .tzinfo .localize (d )
988
1007
return d == self .getOffsetOfMonth (dt )
989
1008
990
1009
@property
@@ -1056,6 +1075,8 @@ def apply(self, other):
1056
1075
def getOffsetOfMonth (self , dt ):
1057
1076
m = MonthEnd ()
1058
1077
d = datetime (dt .year , dt .month , 1 , dt .hour , dt .minute , dt .second , dt .microsecond )
1078
+ if getattr (dt , 'tzinfo' , None ) is not None :
1079
+ d = dt .tzinfo .localize (d )
1059
1080
1060
1081
eom = m .rollforward (d )
1061
1082
@@ -1134,6 +1155,10 @@ class BQuarterEnd(QuarterOffset):
1134
1155
@apply_wraps
1135
1156
def apply (self , other ):
1136
1157
n = self .n
1158
+ base = other
1159
+ other = datetime (other .year , other .month , other .day ,
1160
+ other .hour , other .minute , other .second ,
1161
+ other .microsecond )
1137
1162
1138
1163
wkday , days_in_month = tslib .monthrange (other .year , other .month )
1139
1164
lastBDay = days_in_month - max (((wkday + days_in_month - 1 )
@@ -1149,7 +1174,8 @@ def apply(self, other):
1149
1174
n = n + 1
1150
1175
1151
1176
other = as_datetime (other ) + relativedelta (months = monthsToGo + 3 * n , day = 31 )
1152
-
1177
+ if getattr (base , 'tzinfo' , None ) is not None :
1178
+ other = base .tzinfo .localize (other )
1153
1179
if other .weekday () > 4 :
1154
1180
other = other - BDay ()
1155
1181
@@ -1216,6 +1242,8 @@ def apply(self, other):
1216
1242
result = datetime (other .year , other .month , first ,
1217
1243
other .hour , other .minute , other .second ,
1218
1244
other .microsecond )
1245
+ if getattr (other , 'tzinfo' , None ) is not None :
1246
+ result = other .tzinfo .localize (result )
1219
1247
return as_timestamp (result )
1220
1248
1221
1249
@@ -1242,6 +1270,10 @@ def isAnchored(self):
1242
1270
@apply_wraps
1243
1271
def apply (self , other ):
1244
1272
n = self .n
1273
+ base = other
1274
+ other = datetime (other .year , other .month , other .day ,
1275
+ other .hour , other .minute , other .second ,
1276
+ other .microsecond )
1245
1277
other = as_datetime (other )
1246
1278
1247
1279
wkday , days_in_month = tslib .monthrange (other .year , other .month )
@@ -1254,7 +1286,8 @@ def apply(self, other):
1254
1286
n = n - 1
1255
1287
1256
1288
other = other + relativedelta (months = monthsToGo + 3 * n , day = 31 )
1257
-
1289
+ if getattr (base , 'tzinfo' , None ) is not None :
1290
+ other = base .tzinfo .localize (other )
1258
1291
return as_timestamp (other )
1259
1292
1260
1293
def onOffset (self , dt ):
@@ -1589,6 +1622,10 @@ def apply(self, other):
1589
1622
datetime (other .year , self .startingMonth , 1 ))
1590
1623
next_year = self .get_year_end (
1591
1624
datetime (other .year + 1 , self .startingMonth , 1 ))
1625
+ if getattr (other , 'tzinfo' , None ) is not None :
1626
+ prev_year = other .tzinfo .localize (prev_year )
1627
+ cur_year = other .tzinfo .localize (cur_year )
1628
+ next_year = other .tzinfo .localize (next_year )
1592
1629
1593
1630
if n > 0 :
1594
1631
if other == prev_year :
@@ -1647,7 +1684,9 @@ def get_year_end(self, dt):
1647
1684
return self ._get_year_end_last (dt )
1648
1685
1649
1686
def get_target_month_end (self , dt ):
1650
- target_month = datetime (year = dt .year , month = self .startingMonth , day = 1 )
1687
+ target_month = datetime (dt .year , self .startingMonth , 1 )
1688
+ if getattr (dt , 'tzinfo' , None ) is not None :
1689
+ target_month = dt .tzinfo .localize (target_month )
1651
1690
next_month_first_of = target_month + relativedelta (months = + 1 )
1652
1691
return next_month_first_of + relativedelta (days = - 1 )
1653
1692
@@ -1665,7 +1704,9 @@ def _get_year_end_nearest(self, dt):
1665
1704
return backward
1666
1705
1667
1706
def _get_year_end_last (self , dt ):
1668
- current_year = datetime (year = dt .year , month = self .startingMonth , day = 1 )
1707
+ current_year = datetime (dt .year , self .startingMonth , 1 )
1708
+ if getattr (dt , 'tzinfo' , None ) is not None :
1709
+ current_year = dt .tzinfo .localize (current_year )
1669
1710
return current_year + self ._offset_lwom
1670
1711
1671
1712
@property
@@ -1878,13 +1919,14 @@ class Easter(DateOffset):
1878
1919
'''
1879
1920
def __init__ (self , n = 1 , ** kwds ):
1880
1921
super (Easter , self ).__init__ (n , ** kwds )
1881
-
1922
+
1882
1923
@apply_wraps
1883
1924
def apply (self , other ):
1884
-
1885
1925
currentEaster = easter (other .year )
1886
1926
currentEaster = datetime (currentEaster .year , currentEaster .month , currentEaster .day )
1887
-
1927
+ if getattr (other , 'tzinfo' , None ) is not None :
1928
+ currentEaster = other .tzinfo .localize (currentEaster )
1929
+
1888
1930
# NOTE: easter returns a datetime.date so we have to convert to type of other
1889
1931
if self .n >= 0 :
1890
1932
if other >= currentEaster :
@@ -1905,6 +1947,7 @@ def onOffset(self, dt):
1905
1947
if self .normalize and not _is_normalized (dt ):
1906
1948
return False
1907
1949
return date (dt .year , dt .month , dt .day ) == easter (dt .year )
1950
+
1908
1951
#----------------------------------------------------------------------
1909
1952
# Ticks
1910
1953
0 commit comments