pandas-market-calendars 5.0.0__py3-none-any.whl → 5.1.1__py3-none-any.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.
Files changed (48) hide show
  1. pandas_market_calendars/__init__.py +39 -39
  2. pandas_market_calendars/calendar_registry.py +57 -57
  3. pandas_market_calendars/calendar_utils.py +1151 -1147
  4. pandas_market_calendars/calendars/asx.py +77 -70
  5. pandas_market_calendars/calendars/bmf.py +226 -219
  6. pandas_market_calendars/calendars/bse.py +432 -425
  7. pandas_market_calendars/calendars/cboe.py +156 -149
  8. pandas_market_calendars/calendars/cme.py +412 -405
  9. pandas_market_calendars/calendars/cme_globex_agriculture.py +172 -172
  10. pandas_market_calendars/calendars/cme_globex_base.py +126 -119
  11. pandas_market_calendars/calendars/cme_globex_crypto.py +165 -158
  12. pandas_market_calendars/calendars/cme_globex_energy_and_metals.py +223 -216
  13. pandas_market_calendars/calendars/cme_globex_equities.py +130 -123
  14. pandas_market_calendars/calendars/cme_globex_fixed_income.py +136 -136
  15. pandas_market_calendars/calendars/cme_globex_fx.py +101 -101
  16. pandas_market_calendars/calendars/eurex.py +138 -131
  17. pandas_market_calendars/calendars/eurex_fixed_income.py +105 -98
  18. pandas_market_calendars/calendars/hkex.py +438 -431
  19. pandas_market_calendars/calendars/ice.py +88 -81
  20. pandas_market_calendars/calendars/iex.py +162 -155
  21. pandas_market_calendars/calendars/jpx.py +124 -117
  22. pandas_market_calendars/calendars/lse.py +125 -118
  23. pandas_market_calendars/calendars/mirror.py +144 -144
  24. pandas_market_calendars/calendars/nyse.py +1472 -1466
  25. pandas_market_calendars/calendars/ose.py +125 -118
  26. pandas_market_calendars/calendars/sifma.py +390 -356
  27. pandas_market_calendars/calendars/six.py +143 -136
  28. pandas_market_calendars/calendars/sse.py +322 -315
  29. pandas_market_calendars/calendars/tase.py +231 -224
  30. pandas_market_calendars/calendars/tsx.py +192 -185
  31. pandas_market_calendars/class_registry.py +115 -115
  32. pandas_market_calendars/holidays/cme.py +385 -385
  33. pandas_market_calendars/holidays/cme_globex.py +214 -214
  34. pandas_market_calendars/holidays/cn.py +1476 -1476
  35. pandas_market_calendars/holidays/jp.py +401 -401
  36. pandas_market_calendars/holidays/jpx_equinox.py +506 -506
  37. pandas_market_calendars/holidays/nyse.py +1536 -1536
  38. pandas_market_calendars/holidays/oz.py +63 -63
  39. pandas_market_calendars/holidays/sifma.py +350 -350
  40. pandas_market_calendars/holidays/us.py +376 -376
  41. pandas_market_calendars/market_calendar.py +1008 -1008
  42. {pandas_market_calendars-5.0.0.dist-info → pandas_market_calendars-5.1.1.dist-info}/METADATA +3 -1
  43. pandas_market_calendars-5.1.1.dist-info/RECORD +50 -0
  44. {pandas_market_calendars-5.0.0.dist-info → pandas_market_calendars-5.1.1.dist-info}/WHEEL +1 -1
  45. pandas_market_calendars-5.0.0.dist-info/RECORD +0 -50
  46. {pandas_market_calendars-5.0.0.dist-info → pandas_market_calendars-5.1.1.dist-info}/licenses/LICENSE +0 -0
  47. {pandas_market_calendars-5.0.0.dist-info → pandas_market_calendars-5.1.1.dist-info}/licenses/NOTICE +0 -0
  48. {pandas_market_calendars-5.0.0.dist-info → pandas_market_calendars-5.1.1.dist-info}/top_level.txt +0 -0
@@ -1,315 +1,322 @@
1
- from datetime import time, timedelta
2
- from functools import partial
3
-
4
- from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, next_monday
5
- from zoneinfo import ZoneInfo
6
-
7
- from pandas_market_calendars.holidays.cn import *
8
- from pandas_market_calendars.market_calendar import MarketCalendar
9
-
10
-
11
- class SSEExchangeCalendar(MarketCalendar):
12
- """
13
- Exchange calendar for Shanghai Stock Exchange
14
-
15
- Open Time: 9:30 AM, Asia/Shanghai
16
- LUNCH BREAK :facepalm: : 11:30 AM - 1:00 PM Asia/Shanghai
17
- Close Time: 3:00 PM, Asia/Shanghai
18
- """
19
-
20
- aliases = ["SSE"]
21
- regular_market_times = {
22
- "market_open": ((None, time(9, 30)),),
23
- "market_close": ((None, time(15)),),
24
- "break_start": ((None, time(11, 30)),),
25
- "break_end": ((None, time(13)),),
26
- }
27
-
28
- @property
29
- def name(self):
30
- return "SSE"
31
-
32
- @property
33
- def full_name(self):
34
- return "Shanghai Stock Exchange"
35
-
36
- @property
37
- def tz(self):
38
- return ZoneInfo("Asia/Shanghai")
39
-
40
- @property
41
- def regular_holidays(self):
42
- """
43
- Rules are guesses based on observations of recent year.
44
- Rectify accordingly once the next year's holidays arrangement is published by the government.
45
- """
46
- # Since all past holidays are adhoc, start_year should always be a year in the future.
47
- # For example: Holiday arrangements for 2022 are now included,
48
- # then our guesswork starts from the next year so start_year = 2023
49
- start_year = 2026
50
-
51
- return AbstractHolidayCalendar(
52
- rules=[
53
- Holiday(
54
- name="New Year's Day",
55
- month=1,
56
- day=1,
57
- observance=next_monday,
58
- start_date=Timestamp(start_year, 1, 1),
59
- ),
60
- Holiday(
61
- name="New Year's Day",
62
- month=1,
63
- day=2,
64
- observance=partial(second_day_in_lieu),
65
- start_date=Timestamp(start_year, 1, 2),
66
- ),
67
- Holiday(
68
- name="New Year's Day",
69
- month=1,
70
- day=3,
71
- observance=partial(third_day_in_lieu),
72
- start_date=Timestamp(start_year, 1, 3),
73
- ),
74
- Holiday(
75
- name="Spring Festival",
76
- month=1,
77
- day=20,
78
- observance=partial(lunisolar, mapping=sf_mapping, delta=-1),
79
- start_date=Timestamp(start_year, 1, 20),
80
- ),
81
- Holiday(
82
- name="Spring Festival",
83
- month=1,
84
- day=21,
85
- observance=partial(lunisolar, mapping=sf_mapping, delta=0),
86
- start_date=Timestamp(start_year, 1, 21),
87
- ),
88
- Holiday(
89
- name="Spring Festival",
90
- month=1,
91
- day=21,
92
- observance=partial(lunisolar, mapping=sf_mapping, delta=1),
93
- start_date=Timestamp(start_year, 1, 22),
94
- ),
95
- Holiday(
96
- name="Spring Festival",
97
- month=1,
98
- day=21,
99
- observance=partial(lunisolar, mapping=sf_mapping, delta=2),
100
- start_date=Timestamp(start_year, 1, 23),
101
- ),
102
- Holiday(
103
- name="Spring Festival",
104
- month=1,
105
- day=21,
106
- observance=partial(lunisolar, mapping=sf_mapping, delta=3),
107
- start_date=Timestamp(start_year, 1, 24),
108
- ),
109
- Holiday(
110
- name="Spring Festival",
111
- month=1,
112
- day=21,
113
- observance=partial(lunisolar, mapping=sf_mapping, delta=4),
114
- start_date=Timestamp(start_year, 1, 25),
115
- ),
116
- Holiday(
117
- name="Spring Festival",
118
- month=1,
119
- day=21,
120
- observance=partial(lunisolar, mapping=sf_mapping, delta=5),
121
- start_date=Timestamp(start_year, 1, 26),
122
- ),
123
- Holiday(
124
- name="Labour Day",
125
- month=5,
126
- day=1,
127
- observance=next_monday,
128
- start_date=Timestamp(start_year, 5, 1),
129
- ),
130
- Holiday(
131
- name="Labour Day",
132
- month=5,
133
- day=2,
134
- observance=second_day_in_lieu,
135
- start_date=Timestamp(start_year, 5, 2),
136
- ),
137
- Holiday(
138
- name="Labour Day",
139
- month=5,
140
- day=3,
141
- observance=third_day_in_lieu,
142
- start_date=Timestamp(start_year, 5, 3),
143
- ),
144
- Holiday(
145
- name="Tomb-sweeping Day",
146
- month=4,
147
- day=4,
148
- observance=partial(
149
- lunisolar, mapping=tsd_mapping, func=next_monday
150
- ),
151
- start_date=Timestamp(start_year, 4, 4),
152
- ),
153
- Holiday(
154
- name="Tomb-sweeping Day",
155
- month=4,
156
- day=5,
157
- observance=partial(
158
- lunisolar, mapping=tsd_mapping, func=second_day_in_lieu, delta=1
159
- ),
160
- start_date=Timestamp(start_year, 4, 4),
161
- ),
162
- Holiday(
163
- name="Tomb-sweeping Day",
164
- month=4,
165
- day=6,
166
- observance=partial(
167
- lunisolar, mapping=tsd_mapping, func=third_day_in_lieu, delta=2
168
- ),
169
- start_date=Timestamp(start_year, 4, 4),
170
- ),
171
- Holiday(
172
- name="Dragon Boat Festival",
173
- month=5,
174
- day=27,
175
- observance=partial(
176
- lunisolar, mapping=dbf_mapping, func=next_monday
177
- ),
178
- start_date=Timestamp(start_year, 5, 27),
179
- ),
180
- Holiday(
181
- name="Dragon Boat Festival",
182
- month=5,
183
- day=28,
184
- observance=partial(
185
- lunisolar, mapping=dbf_mapping, func=second_day_in_lieu, delta=1
186
- ),
187
- start_date=Timestamp(start_year, 5, 27),
188
- ),
189
- Holiday(
190
- name="Dragon Boat Festival",
191
- month=5,
192
- day=29,
193
- observance=partial(
194
- lunisolar, mapping=dbf_mapping, func=third_day_in_lieu, delta=2
195
- ),
196
- start_date=Timestamp(start_year, 5, 27),
197
- ),
198
- Holiday(
199
- name="Mid-autumn Festival",
200
- month=9,
201
- day=7,
202
- observance=partial(
203
- lunisolar, mapping=maf_mapping, func=next_monday
204
- ),
205
- start_date=Timestamp(start_year, 9, 7),
206
- ),
207
- Holiday(
208
- name="Mid-autumn Festival",
209
- month=9,
210
- day=8,
211
- observance=partial(
212
- lunisolar, mapping=maf_mapping, func=second_day_in_lieu, delta=1
213
- ),
214
- start_date=Timestamp(start_year, 9, 7),
215
- ),
216
- Holiday(
217
- name="Mid-autumn Festival",
218
- month=9,
219
- day=9,
220
- observance=partial(
221
- lunisolar, mapping=maf_mapping, func=third_day_in_lieu, delta=2
222
- ),
223
- start_date=Timestamp(start_year, 9, 7),
224
- ),
225
- Holiday(
226
- name="National Day",
227
- month=10,
228
- day=1,
229
- start_date=Timestamp(start_year, 10, 1),
230
- ),
231
- Holiday(
232
- name="National Day",
233
- month=10,
234
- day=2,
235
- start_date=Timestamp(start_year, 10, 2),
236
- ),
237
- Holiday(
238
- name="National Day",
239
- month=10,
240
- day=3,
241
- start_date=Timestamp(start_year, 10, 3),
242
- ),
243
- Holiday(
244
- name="National Day",
245
- month=10,
246
- day=4,
247
- start_date=Timestamp(start_year, 10, 4),
248
- ),
249
- Holiday(
250
- name="National Day",
251
- month=10,
252
- day=5,
253
- start_date=Timestamp(start_year, 10, 5),
254
- ),
255
- Holiday(
256
- name="National Day",
257
- month=10,
258
- day=6,
259
- start_date=Timestamp(start_year, 10, 6),
260
- ),
261
- Holiday(
262
- name="National Day",
263
- month=10,
264
- day=7,
265
- start_date=Timestamp(start_year, 10, 7),
266
- ),
267
- ]
268
- )
269
-
270
- @property
271
- def adhoc_holidays(self):
272
- return all_holidays
273
-
274
-
275
- def second_day_in_lieu(dt):
276
- dow = dt.weekday()
277
- if dow == 0: # Holiday is Sunday, use Saturday
278
- return dt - timedelta(2)
279
- elif dow == 1: # Holiday is Monday, use Saturday
280
- return dt - timedelta(3)
281
- elif dow == 2: # Holiday is Tuesday, use Sunday
282
- return dt - timedelta(3)
283
- elif dow == 3: # Holiday is Wednesday, use Saturday
284
- return dt - timedelta(5)
285
-
286
- return dt
287
-
288
-
289
- def third_day_in_lieu(dt):
290
- dow = dt.weekday()
291
- if dow == 0: # Holiday is Saturday, use Sunday
292
- return dt - timedelta(1)
293
- elif dow == 1: # Holiday is Sunday, use Sunday
294
- return dt - timedelta(2)
295
- elif dow == 2: # Holiday is Monday, use Sunday
296
- return dt - timedelta(3)
297
- elif dow == 3: # Holiday is Tuesday, use Monday
298
- return dt - timedelta(3)
299
- elif dow == 4: # Holiday is Wednesday, use Sunday
300
- return dt - timedelta(5)
301
-
302
- return dt
303
-
304
-
305
- def lunisolar(dt, mapping, func=None, delta=None):
306
- if mapping and (dt.year in mapping):
307
- new_dt = mapping[dt.year]
308
- else:
309
- new_dt = dt
310
- if delta:
311
- new_dt = new_dt + timedelta(delta)
312
- if func:
313
- return func(new_dt)
314
- else:
315
- return new_dt
1
+ from datetime import time, timedelta
2
+ from functools import partial
3
+
4
+ from pandas.tseries.holiday import AbstractHolidayCalendar, Holiday, next_monday
5
+ import sys
6
+ # check python versiOn aNd import accordingly
7
+ if sys.version_info >= (3, 9):
8
+ # For Python 3.9 and later, import directly
9
+ from zoneinfo import ZoneInfo
10
+ else:
11
+ # For Python 3.8 and earlier, import from backports
12
+ from backports.zoneinfo import ZoneInfo
13
+
14
+ from pandas_market_calendars.holidays.cn import *
15
+ from pandas_market_calendars.market_calendar import MarketCalendar
16
+
17
+
18
+ class SSEExchangeCalendar(MarketCalendar):
19
+ """
20
+ Exchange calendar for Shanghai Stock Exchange
21
+
22
+ Open Time: 9:30 AM, Asia/Shanghai
23
+ LUNCH BREAK :facepalm: : 11:30 AM - 1:00 PM Asia/Shanghai
24
+ Close Time: 3:00 PM, Asia/Shanghai
25
+ """
26
+
27
+ aliases = ["SSE"]
28
+ regular_market_times = {
29
+ "market_open": ((None, time(9, 30)),),
30
+ "market_close": ((None, time(15)),),
31
+ "break_start": ((None, time(11, 30)),),
32
+ "break_end": ((None, time(13)),),
33
+ }
34
+
35
+ @property
36
+ def name(self):
37
+ return "SSE"
38
+
39
+ @property
40
+ def full_name(self):
41
+ return "Shanghai Stock Exchange"
42
+
43
+ @property
44
+ def tz(self):
45
+ return ZoneInfo("Asia/Shanghai")
46
+
47
+ @property
48
+ def regular_holidays(self):
49
+ """
50
+ Rules are guesses based on observations of recent year.
51
+ Rectify accordingly once the next year's holidays arrangement is published by the government.
52
+ """
53
+ # Since all past holidays are adhoc, start_year should always be a year in the future.
54
+ # For example: Holiday arrangements for 2022 are now included,
55
+ # then our guesswork starts from the next year so start_year = 2023
56
+ start_year = 2026
57
+
58
+ return AbstractHolidayCalendar(
59
+ rules=[
60
+ Holiday(
61
+ name="New Year's Day",
62
+ month=1,
63
+ day=1,
64
+ observance=next_monday,
65
+ start_date=Timestamp(start_year, 1, 1),
66
+ ),
67
+ Holiday(
68
+ name="New Year's Day",
69
+ month=1,
70
+ day=2,
71
+ observance=partial(second_day_in_lieu),
72
+ start_date=Timestamp(start_year, 1, 2),
73
+ ),
74
+ Holiday(
75
+ name="New Year's Day",
76
+ month=1,
77
+ day=3,
78
+ observance=partial(third_day_in_lieu),
79
+ start_date=Timestamp(start_year, 1, 3),
80
+ ),
81
+ Holiday(
82
+ name="Spring Festival",
83
+ month=1,
84
+ day=20,
85
+ observance=partial(lunisolar, mapping=sf_mapping, delta=-1),
86
+ start_date=Timestamp(start_year, 1, 20),
87
+ ),
88
+ Holiday(
89
+ name="Spring Festival",
90
+ month=1,
91
+ day=21,
92
+ observance=partial(lunisolar, mapping=sf_mapping, delta=0),
93
+ start_date=Timestamp(start_year, 1, 21),
94
+ ),
95
+ Holiday(
96
+ name="Spring Festival",
97
+ month=1,
98
+ day=21,
99
+ observance=partial(lunisolar, mapping=sf_mapping, delta=1),
100
+ start_date=Timestamp(start_year, 1, 22),
101
+ ),
102
+ Holiday(
103
+ name="Spring Festival",
104
+ month=1,
105
+ day=21,
106
+ observance=partial(lunisolar, mapping=sf_mapping, delta=2),
107
+ start_date=Timestamp(start_year, 1, 23),
108
+ ),
109
+ Holiday(
110
+ name="Spring Festival",
111
+ month=1,
112
+ day=21,
113
+ observance=partial(lunisolar, mapping=sf_mapping, delta=3),
114
+ start_date=Timestamp(start_year, 1, 24),
115
+ ),
116
+ Holiday(
117
+ name="Spring Festival",
118
+ month=1,
119
+ day=21,
120
+ observance=partial(lunisolar, mapping=sf_mapping, delta=4),
121
+ start_date=Timestamp(start_year, 1, 25),
122
+ ),
123
+ Holiday(
124
+ name="Spring Festival",
125
+ month=1,
126
+ day=21,
127
+ observance=partial(lunisolar, mapping=sf_mapping, delta=5),
128
+ start_date=Timestamp(start_year, 1, 26),
129
+ ),
130
+ Holiday(
131
+ name="Labour Day",
132
+ month=5,
133
+ day=1,
134
+ observance=next_monday,
135
+ start_date=Timestamp(start_year, 5, 1),
136
+ ),
137
+ Holiday(
138
+ name="Labour Day",
139
+ month=5,
140
+ day=2,
141
+ observance=second_day_in_lieu,
142
+ start_date=Timestamp(start_year, 5, 2),
143
+ ),
144
+ Holiday(
145
+ name="Labour Day",
146
+ month=5,
147
+ day=3,
148
+ observance=third_day_in_lieu,
149
+ start_date=Timestamp(start_year, 5, 3),
150
+ ),
151
+ Holiday(
152
+ name="Tomb-sweeping Day",
153
+ month=4,
154
+ day=4,
155
+ observance=partial(
156
+ lunisolar, mapping=tsd_mapping, func=next_monday
157
+ ),
158
+ start_date=Timestamp(start_year, 4, 4),
159
+ ),
160
+ Holiday(
161
+ name="Tomb-sweeping Day",
162
+ month=4,
163
+ day=5,
164
+ observance=partial(
165
+ lunisolar, mapping=tsd_mapping, func=second_day_in_lieu, delta=1
166
+ ),
167
+ start_date=Timestamp(start_year, 4, 4),
168
+ ),
169
+ Holiday(
170
+ name="Tomb-sweeping Day",
171
+ month=4,
172
+ day=6,
173
+ observance=partial(
174
+ lunisolar, mapping=tsd_mapping, func=third_day_in_lieu, delta=2
175
+ ),
176
+ start_date=Timestamp(start_year, 4, 4),
177
+ ),
178
+ Holiday(
179
+ name="Dragon Boat Festival",
180
+ month=5,
181
+ day=27,
182
+ observance=partial(
183
+ lunisolar, mapping=dbf_mapping, func=next_monday
184
+ ),
185
+ start_date=Timestamp(start_year, 5, 27),
186
+ ),
187
+ Holiday(
188
+ name="Dragon Boat Festival",
189
+ month=5,
190
+ day=28,
191
+ observance=partial(
192
+ lunisolar, mapping=dbf_mapping, func=second_day_in_lieu, delta=1
193
+ ),
194
+ start_date=Timestamp(start_year, 5, 27),
195
+ ),
196
+ Holiday(
197
+ name="Dragon Boat Festival",
198
+ month=5,
199
+ day=29,
200
+ observance=partial(
201
+ lunisolar, mapping=dbf_mapping, func=third_day_in_lieu, delta=2
202
+ ),
203
+ start_date=Timestamp(start_year, 5, 27),
204
+ ),
205
+ Holiday(
206
+ name="Mid-autumn Festival",
207
+ month=9,
208
+ day=7,
209
+ observance=partial(
210
+ lunisolar, mapping=maf_mapping, func=next_monday
211
+ ),
212
+ start_date=Timestamp(start_year, 9, 7),
213
+ ),
214
+ Holiday(
215
+ name="Mid-autumn Festival",
216
+ month=9,
217
+ day=8,
218
+ observance=partial(
219
+ lunisolar, mapping=maf_mapping, func=second_day_in_lieu, delta=1
220
+ ),
221
+ start_date=Timestamp(start_year, 9, 7),
222
+ ),
223
+ Holiday(
224
+ name="Mid-autumn Festival",
225
+ month=9,
226
+ day=9,
227
+ observance=partial(
228
+ lunisolar, mapping=maf_mapping, func=third_day_in_lieu, delta=2
229
+ ),
230
+ start_date=Timestamp(start_year, 9, 7),
231
+ ),
232
+ Holiday(
233
+ name="National Day",
234
+ month=10,
235
+ day=1,
236
+ start_date=Timestamp(start_year, 10, 1),
237
+ ),
238
+ Holiday(
239
+ name="National Day",
240
+ month=10,
241
+ day=2,
242
+ start_date=Timestamp(start_year, 10, 2),
243
+ ),
244
+ Holiday(
245
+ name="National Day",
246
+ month=10,
247
+ day=3,
248
+ start_date=Timestamp(start_year, 10, 3),
249
+ ),
250
+ Holiday(
251
+ name="National Day",
252
+ month=10,
253
+ day=4,
254
+ start_date=Timestamp(start_year, 10, 4),
255
+ ),
256
+ Holiday(
257
+ name="National Day",
258
+ month=10,
259
+ day=5,
260
+ start_date=Timestamp(start_year, 10, 5),
261
+ ),
262
+ Holiday(
263
+ name="National Day",
264
+ month=10,
265
+ day=6,
266
+ start_date=Timestamp(start_year, 10, 6),
267
+ ),
268
+ Holiday(
269
+ name="National Day",
270
+ month=10,
271
+ day=7,
272
+ start_date=Timestamp(start_year, 10, 7),
273
+ ),
274
+ ]
275
+ )
276
+
277
+ @property
278
+ def adhoc_holidays(self):
279
+ return all_holidays
280
+
281
+
282
+ def second_day_in_lieu(dt):
283
+ dow = dt.weekday()
284
+ if dow == 0: # Holiday is Sunday, use Saturday
285
+ return dt - timedelta(2)
286
+ elif dow == 1: # Holiday is Monday, use Saturday
287
+ return dt - timedelta(3)
288
+ elif dow == 2: # Holiday is Tuesday, use Sunday
289
+ return dt - timedelta(3)
290
+ elif dow == 3: # Holiday is Wednesday, use Saturday
291
+ return dt - timedelta(5)
292
+
293
+ return dt
294
+
295
+
296
+ def third_day_in_lieu(dt):
297
+ dow = dt.weekday()
298
+ if dow == 0: # Holiday is Saturday, use Sunday
299
+ return dt - timedelta(1)
300
+ elif dow == 1: # Holiday is Sunday, use Sunday
301
+ return dt - timedelta(2)
302
+ elif dow == 2: # Holiday is Monday, use Sunday
303
+ return dt - timedelta(3)
304
+ elif dow == 3: # Holiday is Tuesday, use Monday
305
+ return dt - timedelta(3)
306
+ elif dow == 4: # Holiday is Wednesday, use Sunday
307
+ return dt - timedelta(5)
308
+
309
+ return dt
310
+
311
+
312
+ def lunisolar(dt, mapping, func=None, delta=None):
313
+ if mapping and (dt.year in mapping):
314
+ new_dt = mapping[dt.year]
315
+ else:
316
+ new_dt = dt
317
+ if delta:
318
+ new_dt = new_dt + timedelta(delta)
319
+ if func:
320
+ return func(new_dt)
321
+ else:
322
+ return new_dt