opendate 0.1.34__cp39-cp39-win_amd64.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.
@@ -0,0 +1,469 @@
1
+ Metadata-Version: 2.4
2
+ Name: opendate
3
+ Version: 0.1.34
4
+ Classifier: License :: OSI Approved :: MIT License
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: Programming Language :: Python :: 3.9
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Requires-Dist: pandas-market-calendars
11
+ Requires-Dist: pendulum
12
+ Requires-Dist: wrapt
13
+ Requires-Dist: typing-extensions
14
+ Requires-Dist: asserts ; extra == 'test'
15
+ Requires-Dist: pdbpp ; extra == 'test'
16
+ Requires-Dist: pytest ; extra == 'test'
17
+ Requires-Dist: bump2version ; extra == 'test'
18
+ Provides-Extra: test
19
+ License-File: LICENSE
20
+ Summary: Python business datetimes
21
+ Author-email: bissli <bissli.xyz@protonmail.com>
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
24
+ Project-URL: Repository, https://github.com/bissli/opendate
25
+
26
+ # OpenDate
27
+
28
+ Date/time library built on [Pendulum](https://github.com/sdispater/pendulum) with business day support and financial calculations. Parsing is 1.2-6x faster than pendulum thanks to a Rust-based dateutil port.
29
+
30
+ ```bash
31
+ pip install opendate
32
+ ```
33
+
34
+ ## Quick Reference
35
+
36
+ ```python
37
+ # Preferred import (using canonical module name)
38
+ import opendate
39
+ from opendate import Date, DateTime, Time, Interval
40
+ from opendate import EST, UTC, LCL, WeekDay
41
+ from opendate import get_calendar, set_default_calendar
42
+
43
+ # Basics
44
+ today = Date.today()
45
+ now = DateTime.now()
46
+ parsed = Date.parse('T-3b') # 3 business days ago
47
+
48
+ # Business days
49
+ today.b.add(days=5) # 5 business days forward
50
+ today.calendar('LSE').b.subtract(days=3) # Using London calendar
51
+
52
+ # Change default calendar globally
53
+ set_default_calendar('LSE')
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Module Functions
59
+
60
+ | Function | Description |
61
+ |----------|-------------|
62
+ | `date(y, m, d)` | Create Date |
63
+ | `datetime(y, m, d, h, m, s, tz=UTC)` | Create DateTime (defaults to UTC) |
64
+ | `time(h, m, s, tz=UTC)` | Create Time (defaults to UTC) |
65
+ | `interval(start, end)` | Create Interval |
66
+ | `parse(s, calendar=None)` | Parse to DateTime (calendar optional, uses module default) |
67
+ | `instance(obj)` | Convert datetime/date/time (preserves obj's tz if present, else UTC) |
68
+ | `now(tz=None)` | Current DateTime (local tz if None) |
69
+ | `today(tz=None)` | Today at 00:00:00 (local tz if None) |
70
+ | `get_calendar(name)` | Get calendar instance |
71
+ | `set_default_calendar(name)` | Set module default calendar |
72
+ | `get_default_calendar()` | Get current default calendar name |
73
+ | `available_calendars()` | List available calendars |
74
+
75
+ ---
76
+
77
+ ## Date
78
+
79
+ ### Constructors
80
+
81
+ | Method | Description |
82
+ |--------|-------------|
83
+ | `Date(y, m, d)` | Create from components |
84
+ | `Date.today()` | Current date (uses local tz for current day) |
85
+ | `Date.parse(s, calendar='NYSE')` | Parse string. Calendar used for business day codes (T-3b, P), defaults to NYSE |
86
+ | `Date.instance(obj)` | From datetime.date, Timestamp, datetime64 |
87
+ | `Date.fromordinal(n)` | From ordinal |
88
+ | `Date.fromtimestamp(ts, tz=None)` | From Unix timestamp (UTC if None) |
89
+
90
+ ### Properties
91
+
92
+ Inherited from pendulum: `year`, `month`, `day`, `day_of_week`, `day_of_year`, `week_of_month`, `week_of_year`, `days_in_month`, `quarter`
93
+
94
+ ### Arithmetic
95
+
96
+ | Method | Description |
97
+ |--------|-------------|
98
+ | `add(years, months, weeks, days)` | Add time units |
99
+ | `subtract(years, months, weeks, days)` | Subtract time units |
100
+ | `diff(other)` | Get Interval between dates |
101
+
102
+ ### Period Boundaries
103
+
104
+ | Method | Description |
105
+ |--------|-------------|
106
+ | `start_of(unit)` | Start of day/week/month/quarter/year |
107
+ | `end_of(unit)` | End of day/week/month/quarter/year |
108
+ | `first_of(unit, day_of_week=None)` | First (or first weekday) of period |
109
+ | `last_of(unit, day_of_week=None)` | Last (or last weekday) of period |
110
+ | `nth_of(unit, n, day_of_week)` | Nth occurrence of weekday in period |
111
+
112
+ ### Navigation
113
+
114
+ | Method | Description |
115
+ |--------|-------------|
116
+ | `next(day_of_week=None)` | Next occurrence of weekday |
117
+ | `previous(day_of_week=None)` | Previous occurrence of weekday |
118
+ | `closest(d1, d2)` | Closer of two dates |
119
+ | `farthest(d1, d2)` | Further of two dates |
120
+ | `average(other=None)` | Midpoint between dates |
121
+ | `lookback(unit)` | Go back by unit: day/week/month/quarter/year |
122
+
123
+ ### Business Day
124
+
125
+ | Method | Description |
126
+ |--------|-------------|
127
+ | `business()` or `.b` | Enable business day mode |
128
+ | `calendar(name)` | Set calendar (NYSE, LSE, etc.) |
129
+ | `is_business_day()` | Check if business day |
130
+ | `business_hours()` | Returns `(open, close)` or `(None, None)` |
131
+
132
+ ### Extras
133
+
134
+ | Method | Description |
135
+ |--------|-------------|
136
+ | `isoweek()` | ISO week number (1-53) |
137
+ | `nearest_start_of_month()` | Nearest month start (threshold: day 15) |
138
+ | `nearest_end_of_month()` | Nearest month end (threshold: day 15) |
139
+ | `weekday_or_previous_friday()` | Snap weekend to Friday |
140
+ | `to_string(fmt)` | Format (handles Windows `%-` → `%#`) |
141
+
142
+ ---
143
+
144
+ ## DateTime
145
+
146
+ ### Constructors
147
+
148
+ | Method | Description |
149
+ |--------|-------------|
150
+ | `DateTime(y, m, d, h, m, s, us, tzinfo)` | Create from components |
151
+ | `DateTime.now(tz=None)` | Current time (local tz if None) |
152
+ | `DateTime.today(tz=None)` | Today at 00:00:00 (local tz if None, **differs from pendulum**) |
153
+ | `DateTime.parse(s, calendar='NYSE')` | Parse string or timestamp. Strings: preserve explicit tz, else naive. Timestamps: local tz. Calendar used for business day codes, defaults to NYSE |
154
+ | `DateTime.instance(obj, tz=None)` | From datetime, Timestamp, datetime64. Preserves obj's tz if present, else uses `tz` param, else UTC |
155
+ | `DateTime.combine(date, time, tzinfo=None)` | Combine Date and Time (uses time's tz if tzinfo=None) |
156
+ | `DateTime.fromtimestamp(ts, tz=None)` | From Unix timestamp (UTC if None) |
157
+ | `DateTime.utcfromtimestamp(ts)` | From timestamp as UTC |
158
+ | `DateTime.utcnow()` | Current UTC time |
159
+ | `DateTime.strptime(s, fmt)` | Parse with format |
160
+ | `DateTime.fromordinal(n)` | From ordinal |
161
+
162
+ ### Properties
163
+
164
+ Inherited from pendulum: `year`, `month`, `day`, `hour`, `minute`, `second`, `microsecond`, `day_of_week`, `day_of_year`, `week_of_month`, `week_of_year`, `days_in_month`, `quarter`, `timestamp`, `timezone`, `tz`, `timezone_name`, `offset`, `offset_hours`
165
+
166
+ ### Extraction
167
+
168
+ | Method | Description |
169
+ |--------|-------------|
170
+ | `date()` | Extract Date |
171
+ | `time()` | Extract Time (preserves tz) |
172
+ | `epoch()` | Unix timestamp (alias for `timestamp()`) |
173
+
174
+ ### Timezone
175
+
176
+ | Method | Description |
177
+ |--------|-------------|
178
+ | `in_timezone(tz)` | Convert to timezone |
179
+ | `in_tz(tz)` | Alias for `in_timezone` |
180
+ | `astimezone(tz)` | Alias for `in_timezone` |
181
+
182
+ ### Arithmetic & Navigation
183
+
184
+ Same as Date: `add`, `subtract`, `diff`, `start_of`, `end_of`, `first_of`, `last_of`, `nth_of`, `next`, `previous`
185
+
186
+ ### Business Day
187
+
188
+ Same as Date: `business()`, `.b`, `calendar(name)`, `is_business_day()`, `business_hours()`
189
+
190
+ ### Formatting
191
+
192
+ | Method | Description |
193
+ |--------|-------------|
194
+ | `format(fmt, locale=None)` | Format with tokens |
195
+ | `isoformat()` | ISO 8601 string |
196
+ | `rfc3339()` | RFC 3339 (same as isoformat) |
197
+ | `to_date_string()` | YYYY-MM-DD |
198
+ | `to_datetime_string()` | YYYY-MM-DD HH:MM:SS |
199
+ | `to_time_string()` | HH:MM:SS |
200
+ | `to_iso8601_string()` | Full ISO 8601 |
201
+
202
+ ---
203
+
204
+ ## Time
205
+
206
+ ### Constructors
207
+
208
+ | Method | Description |
209
+ |--------|-------------|
210
+ | `Time(h, m, s, us, tzinfo)` | Create from components |
211
+ | `Time.parse(s, fmt=None)` | Parse string (always UTC) |
212
+ | `Time.instance(obj, tz=None)` | From datetime.time, datetime. Preserves obj's tz if present, else uses `tz` param, else UTC |
213
+
214
+ ### Properties
215
+
216
+ `hour`, `minute`, `second`, `microsecond`, `tzinfo`
217
+
218
+ ### Methods
219
+
220
+ | Method | Description |
221
+ |--------|-------------|
222
+ | `in_timezone(tz)` | Convert to timezone |
223
+ | `in_tz(tz)` | Alias |
224
+
225
+ ---
226
+
227
+ ## Interval
228
+
229
+ ### Constructor
230
+
231
+ ```python
232
+ Interval(start, end) # start/end are Date or DateTime
233
+ ```
234
+
235
+ ### Properties
236
+
237
+ | Property | Description |
238
+ |----------|-------------|
239
+ | `days` | Calendar days (business days if `.b`) |
240
+ | `months` | Float with fractional months (**differs from pendulum**) |
241
+ | `years` | Complete years (floors) |
242
+ | `quarters` | Approximate (days/365*4) |
243
+ | `start` | Start date |
244
+ | `end` | End date |
245
+
246
+ ### Methods
247
+
248
+ | Method | Description |
249
+ |--------|-------------|
250
+ | `business()` or `.b` | Enable business day mode |
251
+ | `calendar(name)` | Set calendar |
252
+ | `range(unit, amount=1)` | Iterate by unit (days/weeks/months/years) |
253
+ | `is_business_day_range()` | Yields bool for each day |
254
+ | `start_of(unit)` | List of period starts in interval |
255
+ | `end_of(unit)` | List of period ends in interval |
256
+ | `yearfrac(basis)` | Year fraction (Excel-compatible) |
257
+
258
+ ### yearfrac Basis
259
+
260
+ | Basis | Convention | Use |
261
+ |-------|------------|-----|
262
+ | 0 | US (NASD) 30/360 | Corporate bonds |
263
+ | 1 | Actual/actual | Treasury bonds |
264
+ | 2 | Actual/360 | Money market |
265
+ | 3 | Actual/365 | Some bonds |
266
+ | 4 | European 30/360 | Eurobonds |
267
+
268
+ ---
269
+
270
+ ## Parsing
271
+
272
+ OpenDate uses a dateutil-compatible Rust parser that handles virtually any date/time format. The parser supports fuzzy matching, multiple locales, and automatic format detection.
273
+
274
+ ### Special Codes
275
+
276
+ | Code | Meaning |
277
+ |------|---------|
278
+ | `T` or `N` | Today |
279
+ | `Y` | Yesterday |
280
+ | `P` | Previous business day |
281
+ | `M` | Last day of previous month |
282
+
283
+ ### Business Day Offsets
284
+
285
+ | Pattern | Example | Meaning |
286
+ |---------|---------|---------|
287
+ | `{code}±{n}` | `T-5` | 5 calendar days ago |
288
+ | `{code}±{n}b` | `T-3b` | 3 business days ago |
289
+
290
+ ### Parser Capabilities
291
+
292
+ - **Dates**: ISO 8601, US/European formats, compact, natural language
293
+ - **Times**: 12/24-hour, with/without seconds, AM/PM, timezones
294
+ - **Combined**: Any date + time combination, Unix timestamps (auto-detects ms/s)
295
+ - **Fuzzy**: Extracts dates from text containing other content
296
+
297
+ ```python
298
+ # All of these work
299
+ Date.parse('2024-01-15')
300
+ Date.parse('Jan 15, 2024')
301
+ Date.parse('15/01/2024')
302
+ DateTime.parse('2024-01-15T09:30:00Z')
303
+ DateTime.parse(1640995200) # Unix timestamp
304
+ DateTime.parse('meeting on Jan 15 at 3pm') # Fuzzy
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Business Days
310
+
311
+ ### Default Calendar
312
+
313
+ ```python
314
+ from opendate import set_default_calendar, get_default_calendar
315
+
316
+ get_default_calendar() # 'NYSE' initially
317
+ set_default_calendar('LSE') # Change globally
318
+ ```
319
+
320
+ ### Per-Operation Calendar
321
+
322
+ ```python
323
+ date.calendar('NYSE').b.add(days=5)
324
+ date.calendar('LSE').is_business_day()
325
+ ```
326
+
327
+ ### Available Calendars
328
+
329
+ All calendars from [exchange-calendars](https://github.com/gerrymanoim/exchange_calendars): NYSE, LSE, XLON, XPAR, XFRA, XJPX, XHKG, etc.
330
+
331
+ ```python
332
+ from opendate import available_calendars
333
+ print(available_calendars())
334
+ ```
335
+
336
+ ### Business Day Examples
337
+
338
+ ```python
339
+ # Add/subtract business days
340
+ Date(2024, 3, 29).b.add(days=1) # Skips Good Friday + weekend
341
+
342
+ # Period boundaries
343
+ Date(2024, 7, 1).b.start_of('month') # First business day of July
344
+ Date(2024, 4, 30).b.end_of('month') # Last business day of April
345
+
346
+ # Iterate business days only
347
+ for d in Interval(start, end).b.range('days'):
348
+ print(d)
349
+
350
+ # Count business days
351
+ Interval(start, end).b.days
352
+ ```
353
+
354
+ ---
355
+
356
+ ## Timezones
357
+
358
+ ### Built-in
359
+
360
+ | Constant | Zone |
361
+ |----------|------|
362
+ | `UTC` | UTC |
363
+ | `GMT` | GMT |
364
+ | `EST` | America/New_York |
365
+ | `LCL` | System local |
366
+
367
+ ### Custom
368
+
369
+ ```python
370
+ from opendate import Timezone
371
+ tokyo = Timezone('Asia/Tokyo')
372
+ dt = DateTime(2024, 1, 15, 9, 30, tzinfo=tokyo)
373
+ ```
374
+
375
+ ### Conversion
376
+
377
+ ```python
378
+ dt.in_timezone(UTC) # or in_tz() or astimezone()
379
+ ```
380
+
381
+ ---
382
+
383
+ ## Decorators
384
+
385
+ | Decorator | Effect |
386
+ |-----------|--------|
387
+ | `@expect_date` | Converts arg to Date |
388
+ | `@expect_datetime` | Converts arg to DateTime |
389
+ | `@expect_time` | Converts arg to Time |
390
+ | `@expect_date_or_datetime` | Converts to Date or DateTime |
391
+ | `@prefer_utc_timezone` | Adds UTC if no tz |
392
+ | `@expect_utc_timezone` | Converts result to UTC |
393
+ | `@prefer_native_timezone` | Adds local tz if no tz |
394
+ | `@expect_native_timezone` | Converts result to local |
395
+
396
+ ---
397
+
398
+ ## Extras Module
399
+
400
+ Legacy standalone functions:
401
+
402
+ ```python
403
+ from opendate import is_business_day, is_within_business_hours, overlap_days
404
+
405
+ is_business_day() # Is today a business day?
406
+ is_within_business_hours() # Is current time in market hours?
407
+
408
+ overlap_days(int1, int2) # Do intervals overlap? (bool)
409
+ overlap_days(int1, int2, days=True) # Day count of overlap (int)
410
+ ```
411
+
412
+ ---
413
+
414
+ ## Pendulum Differences
415
+
416
+ | Feature | Pendulum | OpenDate |
417
+ |---------|----------|----------|
418
+ | `DateTime.today()` | Current time | Start of day (00:00:00) |
419
+ | `DateTime.instance()` default tz | None | Preserves obj's tz if present, else UTC |
420
+ | `Time.parse()` default tz | None | UTC |
421
+ | `Interval.months` | int | float (fractional) |
422
+ | Business day support | No | Yes |
423
+ | Default calendar | N/A | `set_default_calendar()` |
424
+
425
+ ---
426
+
427
+ ## Examples
428
+
429
+ ### Month-End Dates
430
+
431
+ ```python
432
+ interval = Interval(Date(2024, 1, 1), Date(2024, 12, 31))
433
+ month_ends = interval.end_of('month')
434
+ business_month_ends = interval.b.end_of('month')
435
+ ```
436
+
437
+ ### Third Friday (Options Expiration)
438
+
439
+ ```python
440
+ Date.today().add(months=1).start_of('month').nth_of('month', 3, WeekDay.FRIDAY)
441
+ ```
442
+
443
+ ### Interest Accrual
444
+
445
+ ```python
446
+ days_fraction = Interval(issue_date, settlement_date).yearfrac(2) # Actual/360
447
+ accrued = coupon_rate * days_fraction
448
+ ```
449
+
450
+ ### Market Hours Check
451
+
452
+ ```python
453
+ now = DateTime.now(tz=get_calendar('NYSE').tz)
454
+ if now.calendar('NYSE').is_business_day():
455
+ open_time, close_time = now.business_hours()
456
+ if open_time and open_time <= now <= close_time:
457
+ print("Market open")
458
+ ```
459
+
460
+ ---
461
+
462
+ ## Development
463
+
464
+ See [docs/developer-guide.md](docs/developer-guide.md)
465
+
466
+ ## License
467
+
468
+ MIT - Built on [Pendulum](https://github.com/sdispater/pendulum) and [pandas-market-calendars](https://github.com/rsheftel/pandas_market_calendars)
469
+
@@ -0,0 +1,20 @@
1
+ date/__init__.py,sha256=SMKZpdDq9392ptGPzN3nRhVy0ayQiBlJbSy0W9kvgDE,147
2
+ opendate-0.1.34.dist-info/METADATA,sha256=rzeKxX9RA2WIyyFTB3WHaqjHCgOEqOsUHRnushqJ450,14135
3
+ opendate-0.1.34.dist-info/WHEEL,sha256=cJkMTYTklyOQ5jua9KOOIaaSma7Th-zqFU6TpVB6bCU,95
4
+ opendate-0.1.34.dist-info/licenses/LICENSE,sha256=jwru1C59PAcdH1Lw83OwnZU2JOtOw4bN67LYHVpbpc4,1134
5
+ opendate/__init__.py,sha256=17B63P-F8xH7R-J8ZAfW8B4zh4kchGNQarRiXppt3vk,4146
6
+ opendate/_opendate.cp39-win_amd64.pyd,sha256=RTowRVIcW2-UDk64pxXnJBNP4rRZbHUDTrQAaDKssr0,441344
7
+ opendate/calendars.py,sha256=vxe1-zsqRcfDPF8_wxwsyK-eTOxmnlUop78kEPmgxlE,12428
8
+ opendate/constants.py,sha256=F9Ro0nbImVv-1llrvkXSW3qki152pEH6fMQIVAYfrpw,1263
9
+ opendate/date_.py,sha256=dPrrpdz8NJfGGKY-JOFoVJgE4Ig0OZDk8c637sMLrJM,8678
10
+ opendate/datetime_.py,sha256=Jm4fhiVEj13ZuvIB6-NzowQ9AaGARVlsGpFByKjU_wU,11970
11
+ opendate/decorators.py,sha256=Len-sCOJi6p4tnYgATyrUw-GwdIqjmxxRRoeUSIunKk,6430
12
+ opendate/extras.py,sha256=U6rRWCyRYuLIQ-vvD3_J8sEWz4vv8LBXGAEuz3FtF9Q,3125
13
+ opendate/helpers.py,sha256=RDmBaw35I5OD05cJ45HhGNlCiw3FtxJxwA-h5PY-nIM,6156
14
+ opendate/interval.py,sha256=8Dk0FNfmU24blmJ8-xjDG4CHMi4ThOlpW00XUCu7G4A,15817
15
+ opendate/metaclass.py,sha256=C35SZE710cKyjy8ECqUuh71JWB9mLchG0wmvNJ-NCqQ,4109
16
+ opendate/mixins/__init__.py,sha256=WjHOErYs20RWa4I8Ha2lrJKxuzxVy1u2YeEmqtpTAec,163
17
+ opendate/mixins/business.py,sha256=rb1lEC4AyfX2IzUgbEOA3cPWfS5_8imyxR9KxfDi6RU,10677
18
+ opendate/mixins/extras_.py,sha256=bzJ5uct6ofdBVEvaTkHEYTtFcnGkAjSqYiL5qhdnVRk,3360
19
+ opendate/time_.py,sha256=crQr6ndRzAb7zL8RjM5lmi00JFz5bk3gF4tqhJqcQGk,4637
20
+ opendate-0.1.34.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.10.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp39-cp39-win_amd64
@@ -0,0 +1,23 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 bissli
4
+ Copyright (c) 2015 Sébastien Eustace
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.