opendate 0.1.1__tar.gz
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.
Potentially problematic release.
This version of opendate might be problematic. Click here for more details.
- opendate-0.1.1/LICENSE +23 -0
- opendate-0.1.1/PKG-INFO +61 -0
- opendate-0.1.1/README.md +36 -0
- opendate-0.1.1/pyproject.toml +34 -0
- opendate-0.1.1/src/date/__init__.py +109 -0
- opendate-0.1.1/src/date/business.py +42 -0
- opendate-0.1.1/src/date/date.py +1702 -0
opendate-0.1.1/LICENSE
ADDED
|
@@ -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.
|
opendate-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: opendate
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary:
|
|
5
|
+
Author: bissli
|
|
6
|
+
Author-email: bissli.xyz@protonmail.com
|
|
7
|
+
Requires-Python: >=3.9,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Provides-Extra: test
|
|
14
|
+
Requires-Dist: asserts ; extra == "test"
|
|
15
|
+
Requires-Dist: bump2version ; extra == "test"
|
|
16
|
+
Requires-Dist: pandas-market-calendars
|
|
17
|
+
Requires-Dist: pdbpp ; extra == "test"
|
|
18
|
+
Requires-Dist: pendulum
|
|
19
|
+
Requires-Dist: pytest ; extra == "test"
|
|
20
|
+
Requires-Dist: regex
|
|
21
|
+
Requires-Dist: typing-extensions
|
|
22
|
+
Requires-Dist: wrapt
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
opendate
|
|
26
|
+
========
|
|
27
|
+
|
|
28
|
+
A wrapper around [Pendulum](https://github.com/sdispater/pendulum) with business (NYSE default, extendable) days/hours awareness.
|
|
29
|
+
|
|
30
|
+
Documentation pending, see tests for examples. Functionality is near-identical to Pendulum with the exception of a business modifier.
|
|
31
|
+
|
|
32
|
+
The main module is named `date` rather than `pendulum`
|
|
33
|
+
|
|
34
|
+
Ex:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
|
|
38
|
+
from date import Date, DateTime, Time, Interval
|
|
39
|
+
|
|
40
|
+
thedate = Date.today()
|
|
41
|
+
|
|
42
|
+
# add days
|
|
43
|
+
thedate.add(days=5)
|
|
44
|
+
thedate.business().add(days=5) # add 5 business day
|
|
45
|
+
|
|
46
|
+
# subtract days
|
|
47
|
+
thedate.subtract(days=5)
|
|
48
|
+
thedate.business().subtrat(days=5) # subtract 5 business day
|
|
49
|
+
|
|
50
|
+
# start of month
|
|
51
|
+
thedate.start_of('month')
|
|
52
|
+
thedate.business().start_of('month') # end of month + N days until valid business day
|
|
53
|
+
|
|
54
|
+
# end of month
|
|
55
|
+
thedate.end_of('month')
|
|
56
|
+
thedate.business().end_of('month') # end of month - N days until valid business day
|
|
57
|
+
|
|
58
|
+
# ...
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
|
opendate-0.1.1/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
opendate
|
|
2
|
+
========
|
|
3
|
+
|
|
4
|
+
A wrapper around [Pendulum](https://github.com/sdispater/pendulum) with business (NYSE default, extendable) days/hours awareness.
|
|
5
|
+
|
|
6
|
+
Documentation pending, see tests for examples. Functionality is near-identical to Pendulum with the exception of a business modifier.
|
|
7
|
+
|
|
8
|
+
The main module is named `date` rather than `pendulum`
|
|
9
|
+
|
|
10
|
+
Ex:
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
|
|
14
|
+
from date import Date, DateTime, Time, Interval
|
|
15
|
+
|
|
16
|
+
thedate = Date.today()
|
|
17
|
+
|
|
18
|
+
# add days
|
|
19
|
+
thedate.add(days=5)
|
|
20
|
+
thedate.business().add(days=5) # add 5 business day
|
|
21
|
+
|
|
22
|
+
# subtract days
|
|
23
|
+
thedate.subtract(days=5)
|
|
24
|
+
thedate.business().subtrat(days=5) # subtract 5 business day
|
|
25
|
+
|
|
26
|
+
# start of month
|
|
27
|
+
thedate.start_of('month')
|
|
28
|
+
thedate.business().start_of('month') # end of month + N days until valid business day
|
|
29
|
+
|
|
30
|
+
# end of month
|
|
31
|
+
thedate.end_of('month')
|
|
32
|
+
thedate.business().end_of('month') # end of month - N days until valid business day
|
|
33
|
+
|
|
34
|
+
# ...
|
|
35
|
+
|
|
36
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "opendate"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = ["bissli <bissli.xyz@protonmail.com>"]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
packages = [{ include = "date", from = "src" }]
|
|
8
|
+
|
|
9
|
+
[tool.poetry.dependencies]
|
|
10
|
+
python = "^3.9"
|
|
11
|
+
|
|
12
|
+
pandas-market-calendars = "*"
|
|
13
|
+
pendulum = "*"
|
|
14
|
+
wrapt = "*"
|
|
15
|
+
typing-extensions = "*"
|
|
16
|
+
regex = "*"
|
|
17
|
+
|
|
18
|
+
# = test
|
|
19
|
+
asserts = { version = "*", optional = true }
|
|
20
|
+
pytest = { version = "*", optional = true }
|
|
21
|
+
pdbpp = { version = "*", optional = true }
|
|
22
|
+
bump2version = { version = "*", optional = true }
|
|
23
|
+
|
|
24
|
+
[tool.poetry.extras]
|
|
25
|
+
test = [
|
|
26
|
+
"asserts",
|
|
27
|
+
"pdbpp",
|
|
28
|
+
"pytest",
|
|
29
|
+
"bump2version",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[build-system]
|
|
33
|
+
requires = ["poetry-core"]
|
|
34
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
__version__ = '0.1.1'
|
|
2
|
+
|
|
3
|
+
import datetime as _datetime
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import pendulum as _pendulum
|
|
8
|
+
import zoneinfo as _zoneinfo
|
|
9
|
+
|
|
10
|
+
from typing_extensions import Optional
|
|
11
|
+
from typing_extensions import Union
|
|
12
|
+
from typing_extensions import overload
|
|
13
|
+
|
|
14
|
+
from date.date import Date
|
|
15
|
+
from date.date import DateTime
|
|
16
|
+
from date.date import Entity
|
|
17
|
+
from date.date import Interval
|
|
18
|
+
from date.date import IntervalError
|
|
19
|
+
from date.date import LCL
|
|
20
|
+
from date.date import EST
|
|
21
|
+
from date.date import GMT
|
|
22
|
+
from date.date import UTC
|
|
23
|
+
from date.date import NYSE
|
|
24
|
+
from date.date import Time
|
|
25
|
+
from date.date import WeekDay
|
|
26
|
+
from date.date import WEEKDAY_SHORTNAME
|
|
27
|
+
from date.date import expect_date
|
|
28
|
+
from date.date import expect_datetime
|
|
29
|
+
from date.date import expect_native_timezone
|
|
30
|
+
from date.date import expect_utc_timezone
|
|
31
|
+
from date.date import prefer_native_timezone
|
|
32
|
+
from date.date import prefer_utc_timezone
|
|
33
|
+
from date.date import Timezone
|
|
34
|
+
from date.business import *
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
timezone = Timezone
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def date(*args, **kwargs):
|
|
41
|
+
return Date(*args, **kwargs)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def datetime(*args, **kwargs):
|
|
45
|
+
return DateTime(*args, **kwargs)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def time(*args, **kwargs):
|
|
49
|
+
return Time(*args, **kwargs)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def parse():
|
|
53
|
+
"""Generic parser that guesses type"""
|
|
54
|
+
raise NotImplementedError(
|
|
55
|
+
'Generic parser not implemented, use Date or DateTime parsers'
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def instance(obj: _datetime.date | _datetime.datetime | _datetime.time) -> DateTime | Date | Time:
|
|
60
|
+
"""
|
|
61
|
+
Create a DateTime/Date/Time instance from a datetime/date/time native one.
|
|
62
|
+
"""
|
|
63
|
+
if isinstance(obj, DateTime | Date | Time):
|
|
64
|
+
return obj
|
|
65
|
+
if isinstance(obj, _datetime.date) and not isinstance(obj, _datetime.datetime):
|
|
66
|
+
return Date.instance(obj)
|
|
67
|
+
if isinstance(obj, _datetime.time):
|
|
68
|
+
return Time.instance(obj)
|
|
69
|
+
if isinstance(obj, _datetime.datetime):
|
|
70
|
+
return DateTime.instance(obj)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def now(tz: str | _zoneinfo.ZoneInfo | None = None) -> DateTime:
|
|
74
|
+
"""Get current datetime
|
|
75
|
+
"""
|
|
76
|
+
return DateTime.now(tz)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def today(tz: str | _zoneinfo.ZoneInfo = None) -> DateTime:
|
|
80
|
+
"""Get current date
|
|
81
|
+
"""
|
|
82
|
+
return DateTime.today(tz)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
__all__ = [
|
|
86
|
+
'Date',
|
|
87
|
+
'DateTime',
|
|
88
|
+
'Interval',
|
|
89
|
+
'IntervalError',
|
|
90
|
+
'Time',
|
|
91
|
+
'WeekDay',
|
|
92
|
+
'now',
|
|
93
|
+
'today',
|
|
94
|
+
'parse',
|
|
95
|
+
'LCL',
|
|
96
|
+
'timezone',
|
|
97
|
+
'expect_native_timezone',
|
|
98
|
+
'expect_utc_timezone',
|
|
99
|
+
'prefer_native_timezone',
|
|
100
|
+
'prefer_utc_timezone',
|
|
101
|
+
'expect_date',
|
|
102
|
+
'expect_datetime',
|
|
103
|
+
'Entity',
|
|
104
|
+
'NYSE',
|
|
105
|
+
'date',
|
|
106
|
+
'datetime',
|
|
107
|
+
'time'
|
|
108
|
+
'within_business_hours'
|
|
109
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from date import NYSE, DateTime, Entity
|
|
2
|
+
|
|
3
|
+
__all__ = ['is_within_business_hours', 'is_business_day']
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def is_within_business_hours(entity: Entity = NYSE) -> bool:
|
|
7
|
+
"""Return whether the current native datetime is between
|
|
8
|
+
open and close of business hours.
|
|
9
|
+
|
|
10
|
+
>>> from unittest.mock import patch
|
|
11
|
+
>>> tz = NYSE.tz
|
|
12
|
+
|
|
13
|
+
>>> with patch('date.DateTime.now') as mock:
|
|
14
|
+
... mock.return_value = DateTime(2000, 5, 1, 12, 30, 0, 0, tzinfo=tz)
|
|
15
|
+
... is_within_business_hours()
|
|
16
|
+
True
|
|
17
|
+
|
|
18
|
+
>>> with patch('date.DateTime.now') as mock:
|
|
19
|
+
... mock.return_value = DateTime(2000, 7, 2, 12, 15, 0, 0, tzinfo=tz) # Sunday
|
|
20
|
+
... is_within_business_hours()
|
|
21
|
+
False
|
|
22
|
+
|
|
23
|
+
>>> with patch('date.DateTime.now') as mock:
|
|
24
|
+
... mock.return_value = DateTime(2000, 11, 1, 1, 15, 0, 0, tzinfo=tz)
|
|
25
|
+
... is_within_business_hours()
|
|
26
|
+
False
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
this = DateTime.now()
|
|
30
|
+
this_entity = DateTime.now(tz=entity.tz).entity(entity)
|
|
31
|
+
bounds = this_entity.business_hours()
|
|
32
|
+
return this_entity.business_open() and (bounds[0] <= this.astimezone(entity.tz) <= bounds[1])
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def is_business_day(entity: Entity = NYSE) -> bool:
|
|
36
|
+
"""Return whether the current native datetime is a business day.
|
|
37
|
+
"""
|
|
38
|
+
return DateTime.now(tz=entity.tz).entity(entity).is_business_day()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == '__main__':
|
|
42
|
+
__import__('doctest').testmod(optionflags=4 | 8 | 32)
|