dycw-utilities 0.118.0__py3-none-any.whl → 0.119.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dycw-utilities
3
- Version: 0.118.0
3
+ Version: 0.119.0
4
4
  Author-email: Derek Wan <d.wan@icloud.com>
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -26,7 +26,7 @@ Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-altair'
26
26
  Requires-Dist: img2pdf<0.7,>=0.6.0; extra == 'zzz-test-altair'
27
27
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-altair'
28
28
  Requires-Dist: vl-convert-python<1.8,>=1.7.0; extra == 'zzz-test-altair'
29
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-altair'
29
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-altair'
30
30
  Provides-Extra: zzz-test-astor
31
31
  Requires-Dist: astor<0.9,>=0.8.1; extra == 'zzz-test-astor'
32
32
  Provides-Extra: zzz-test-asyncio
@@ -39,20 +39,20 @@ Requires-Dist: cachetools<5.6,>=5.5.2; extra == 'zzz-test-cachetools'
39
39
  Provides-Extra: zzz-test-click
40
40
  Requires-Dist: click<8.3,>=8.2.0; extra == 'zzz-test-click'
41
41
  Requires-Dist: sqlalchemy<2.1,>=2.0.41; extra == 'zzz-test-click'
42
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-click'
42
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-click'
43
43
  Provides-Extra: zzz-test-contextlib
44
44
  Provides-Extra: zzz-test-contextvars
45
45
  Provides-Extra: zzz-test-cryptography
46
- Requires-Dist: cryptography<46.0,>=45.0.2; extra == 'zzz-test-cryptography'
46
+ Requires-Dist: cryptography<45.1,>=45.0.2; extra == 'zzz-test-cryptography'
47
47
  Provides-Extra: zzz-test-cvxpy
48
48
  Requires-Dist: cvxpy<1.7,>=1.6.5; extra == 'zzz-test-cvxpy'
49
49
  Provides-Extra: zzz-test-dataclasses
50
50
  Requires-Dist: orjson<3.11,>=3.10.15; extra == 'zzz-test-dataclasses'
51
51
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-dataclasses'
52
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-dataclasses'
52
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-dataclasses'
53
53
  Provides-Extra: zzz-test-datetime
54
54
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-datetime'
55
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-datetime'
55
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-datetime'
56
56
  Provides-Extra: zzz-test-enum
57
57
  Provides-Extra: zzz-test-errors
58
58
  Provides-Extra: zzz-test-eventkit
@@ -71,29 +71,29 @@ Provides-Extra: zzz-test-git
71
71
  Provides-Extra: zzz-test-hashlib
72
72
  Requires-Dist: orjson<3.11,>=3.10.15; extra == 'zzz-test-hashlib'
73
73
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-hashlib'
74
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-hashlib'
74
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-hashlib'
75
75
  Provides-Extra: zzz-test-http
76
76
  Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-http'
77
77
  Requires-Dist: orjson<3.11,>=3.10.18; extra == 'zzz-test-http'
78
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-http'
78
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-http'
79
79
  Provides-Extra: zzz-test-hypothesis
80
80
  Requires-Dist: aiosqlite<0.22,>=0.21.0; extra == 'zzz-test-hypothesis'
81
81
  Requires-Dist: asyncpg<0.31,>=0.30.0; extra == 'zzz-test-hypothesis'
82
82
  Requires-Dist: greenlet<3.3,>=3.2.0; extra == 'zzz-test-hypothesis'
83
83
  Requires-Dist: hypothesis<6.132,>=6.131.19; extra == 'zzz-test-hypothesis'
84
84
  Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-hypothesis'
85
- Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-hypothesis'
85
+ Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-hypothesis'
86
86
  Requires-Dist: pathvalidate<3.3,>=3.2.3; extra == 'zzz-test-hypothesis'
87
87
  Requires-Dist: redis<6.2,>=6.1.0; extra == 'zzz-test-hypothesis'
88
88
  Requires-Dist: sqlalchemy<2.1,>=2.0.41; extra == 'zzz-test-hypothesis'
89
89
  Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-hypothesis'
90
90
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-hypothesis'
91
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-hypothesis'
91
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-hypothesis'
92
92
  Provides-Extra: zzz-test-ipython
93
93
  Requires-Dist: ipython<9.1,>=9.0.1; extra == 'zzz-test-ipython'
94
94
  Provides-Extra: zzz-test-iterables
95
95
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-iterables'
96
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-iterables'
96
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-iterables'
97
97
  Provides-Extra: zzz-test-jupyter
98
98
  Requires-Dist: jupyterlab<4.3,>=4.2.0; extra == 'zzz-test-jupyter'
99
99
  Requires-Dist: pandas<2.3,>=2.2.2; extra == 'zzz-test-jupyter'
@@ -105,24 +105,24 @@ Requires-Dist: concurrent-log-handler<0.10,>=0.9.26; extra == 'zzz-test-logging'
105
105
  Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-logging'
106
106
  Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-logging'
107
107
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-logging'
108
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-logging'
108
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-logging'
109
109
  Provides-Extra: zzz-test-loguru
110
110
  Requires-Dist: loguru<0.8,>=0.7.3; extra == 'zzz-test-loguru'
111
111
  Provides-Extra: zzz-test-luigi
112
112
  Requires-Dist: luigi<3.7,>=3.6.0; extra == 'zzz-test-luigi'
113
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-luigi'
113
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-luigi'
114
114
  Provides-Extra: zzz-test-math
115
- Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-math'
115
+ Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-math'
116
116
  Provides-Extra: zzz-test-memory-profiler
117
117
  Requires-Dist: memory-profiler<0.62,>=0.61.0; extra == 'zzz-test-memory-profiler'
118
118
  Provides-Extra: zzz-test-modules
119
119
  Provides-Extra: zzz-test-more-itertools
120
120
  Requires-Dist: more-itertools<10.8,>=10.7.0; extra == 'zzz-test-more-itertools'
121
121
  Provides-Extra: zzz-test-numpy
122
- Requires-Dist: numpy<2.3,>=2.2.5; extra == 'zzz-test-numpy'
122
+ Requires-Dist: numpy<2.3,>=2.2.6; extra == 'zzz-test-numpy'
123
123
  Provides-Extra: zzz-test-operator
124
124
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-operator'
125
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-operator'
125
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-operator'
126
126
  Provides-Extra: zzz-test-optuna
127
127
  Requires-Dist: optuna<4.4,>=4.3.0; extra == 'zzz-test-optuna'
128
128
  Provides-Extra: zzz-test-orjson
@@ -130,7 +130,7 @@ Requires-Dist: orjson<3.11,>=3.10.15; extra == 'zzz-test-orjson'
130
130
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-orjson'
131
131
  Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-orjson'
132
132
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-orjson'
133
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-orjson'
133
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-orjson'
134
134
  Provides-Extra: zzz-test-os
135
135
  Provides-Extra: zzz-test-pathlib
136
136
  Provides-Extra: zzz-test-pickle
@@ -138,7 +138,7 @@ Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-pickle'
138
138
  Provides-Extra: zzz-test-platform
139
139
  Provides-Extra: zzz-test-polars
140
140
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-polars'
141
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-polars'
141
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-polars'
142
142
  Provides-Extra: zzz-test-pqdm
143
143
  Requires-Dist: pqdm<0.3,>=0.2.0; extra == 'zzz-test-pqdm'
144
144
  Provides-Extra: zzz-test-pydantic
@@ -153,12 +153,12 @@ Requires-Dist: pyrsistent<0.21,>=0.20.0; extra == 'zzz-test-pyrsistent'
153
153
  Provides-Extra: zzz-test-pytest
154
154
  Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-pytest'
155
155
  Requires-Dist: orjson<3.11,>=3.10.18; extra == 'zzz-test-pytest'
156
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-pytest'
156
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-pytest'
157
157
  Provides-Extra: zzz-test-pytest-regressions
158
158
  Requires-Dist: pytest-regressions<2.8,>=2.7.0; extra == 'zzz-test-pytest-regressions'
159
159
  Provides-Extra: zzz-test-python-dotenv
160
160
  Requires-Dist: python-dotenv<1.2,>=1.1.0; extra == 'zzz-test-python-dotenv'
161
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-python-dotenv'
161
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-python-dotenv'
162
162
  Provides-Extra: zzz-test-random
163
163
  Provides-Extra: zzz-test-re
164
164
  Provides-Extra: zzz-test-redis
@@ -168,7 +168,7 @@ Requires-Dist: redis<6.2,>=6.1.0; extra == 'zzz-test-redis'
168
168
  Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-redis'
169
169
  Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-redis'
170
170
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-redis'
171
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-redis'
171
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-redis'
172
172
  Provides-Extra: zzz-test-rich
173
173
  Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-rich'
174
174
  Provides-Extra: zzz-test-scipy
@@ -194,7 +194,7 @@ Requires-Dist: nest-asyncio<1.7,>=1.6.0; extra == 'zzz-test-sqlalchemy-polars'
194
194
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-sqlalchemy-polars'
195
195
  Requires-Dist: sqlalchemy<2.1,>=2.0.41; extra == 'zzz-test-sqlalchemy-polars'
196
196
  Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-sqlalchemy-polars'
197
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-sqlalchemy-polars'
197
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-sqlalchemy-polars'
198
198
  Provides-Extra: zzz-test-streamlit
199
199
  Requires-Dist: streamlit<1.46,>=1.45.0; extra == 'zzz-test-streamlit'
200
200
  Provides-Extra: zzz-test-sys
@@ -202,7 +202,7 @@ Requires-Dist: atomicwrites<1.5,>=1.4.1; extra == 'zzz-test-sys'
202
202
  Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-sys'
203
203
  Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-sys'
204
204
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-sys'
205
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-sys'
205
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-sys'
206
206
  Provides-Extra: zzz-test-tempfile
207
207
  Provides-Extra: zzz-test-tenacity
208
208
  Requires-Dist: tenacity<9.0,>=8.5.0; extra == 'zzz-test-tenacity'
@@ -213,11 +213,11 @@ Provides-Extra: zzz-test-traceback
213
213
  Requires-Dist: rich<14.1,>=14.0.0; extra == 'zzz-test-traceback'
214
214
  Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-traceback'
215
215
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-traceback'
216
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-traceback'
216
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-traceback'
217
217
  Provides-Extra: zzz-test-types
218
218
  Provides-Extra: zzz-test-typing
219
219
  Requires-Dist: polars-lts-cpu<1.30,>=1.29.0; extra == 'zzz-test-typing'
220
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-typing'
220
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-typing'
221
221
  Provides-Extra: zzz-test-tzlocal
222
222
  Requires-Dist: tzlocal<5.4,>=5.3.1; extra == 'zzz-test-tzlocal'
223
223
  Provides-Extra: zzz-test-uuid
@@ -225,11 +225,11 @@ Provides-Extra: zzz-test-version
225
225
  Requires-Dist: tomlkit<0.14,>=0.13.2; extra == 'zzz-test-version'
226
226
  Provides-Extra: zzz-test-warnings
227
227
  Provides-Extra: zzz-test-whenever
228
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-whenever'
228
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-whenever'
229
229
  Provides-Extra: zzz-test-zipfile
230
230
  Provides-Extra: zzz-test-zoneinfo
231
231
  Requires-Dist: tzdata<2025.3,>=2025.2; extra == 'zzz-test-zoneinfo'
232
- Requires-Dist: whenever<0.8,>=0.7.3; extra == 'zzz-test-zoneinfo'
232
+ Requires-Dist: whenever<0.9,>=0.8.0; extra == 'zzz-test-zoneinfo'
233
233
  Description-Content-Type: text/markdown
234
234
 
235
235
  [![PyPI version](https://badge.fury.io/py/dycw-utilities.svg)](https://badge.fury.io/py/dycw-utilities)
@@ -1,18 +1,18 @@
1
- utilities/__init__.py,sha256=m9DsK8iICHcyqc8Uf9izHc2F4wKsVwGwOOvxhVTp46A,60
1
+ utilities/__init__.py,sha256=ayFWZ1qOKB0Lqd63WRIXSBg4vZDal1xvPPVJr5LEPEA,60
2
2
  utilities/altair.py,sha256=Gpja-flOo-Db0PIPJLJsgzAlXWoKUjPU1qY-DQ829ek,9156
3
3
  utilities/astor.py,sha256=xuDUkjq0-b6fhtwjhbnebzbqQZAjMSHR1IIS5uOodVg,777
4
4
  utilities/asyncio.py,sha256=HGX79AKzpQbbDBW3paxAXrhWYeudcJjiO1ETU40d_-8,18463
5
5
  utilities/atomicwrites.py,sha256=geFjn9Pwn-tTrtoGjDDxWli9NqbYfy3gGL6ZBctiqSo,5393
6
6
  utilities/atools.py,sha256=IYMuFSFGSKyuQmqD6v5IUtDlz8PPw0Sr87Cub_gRU3M,1168
7
7
  utilities/cachetools.py,sha256=C1zqOg7BYz0IfQFK8e3qaDDgEZxDpo47F15RTfJM37Q,2910
8
- utilities/click.py,sha256=Jzm7DOI3rH-WLOTh1UHOfxkFhHU4_GJH60seLV0A-OI,14311
8
+ utilities/click.py,sha256=SRVkUkWxyO_7AaYvvDl0hNCzdpneX04lf1O97i9MfPw,14311
9
9
  utilities/concurrent.py,sha256=s2scTEd2AhXVTW4hpASU2qxV_DiVLALfms55cCQzCvM,2886
10
10
  utilities/contextlib.py,sha256=OOIIEa5lXKGzFAnauaul40nlQnQko6Na4ryiMJcHkIg,478
11
11
  utilities/contextvars.py,sha256=RsSGGrbQqqZ67rOydnM7WWIsM2lIE31UHJLejnHJPWY,505
12
12
  utilities/cryptography.py,sha256=_CiK_K6c_-uQuUhsUNjNjTL-nqxAh4_1zTfS11Xe120,972
13
13
  utilities/cvxpy.py,sha256=Rv1-fD-XYerosCavRF8Pohop2DBkU3AlFaGTfD8AEAA,13776
14
14
  utilities/dataclasses.py,sha256=iiC1wpGXWhaocIikzwBt8bbLWyImoUlOlcDZJGejaIg,33011
15
- utilities/datetime.py,sha256=VOwjPibw63Myv-CRYhT2eEHpz277GqUiEDEaI7p-nQw,38985
15
+ utilities/datetime.py,sha256=uYoaOi_C1YtNXGfTN9xlTrW62Re2b1_4Skuv14_MeYQ,38985
16
16
  utilities/enum.py,sha256=HoRwVCWzsnH0vpO9ZEcAAIZLMv0Sn2vJxxA4sYMQgDs,5793
17
17
  utilities/errors.py,sha256=gxsaa7eq7jbYl41Of40-ivjXqJB5gt4QAcJ0smZZMJE,829
18
18
  utilities/eventkit.py,sha256=6M5Xu1SzN-juk9PqBHwy5dS-ta7T0qA6SMpDsakOJ0E,13039
@@ -24,7 +24,7 @@ utilities/getpass.py,sha256=DfN5UgMAtFCqS3dSfFHUfqIMZX2shXvwphOz_6J6f6A,103
24
24
  utilities/git.py,sha256=wpt5dZ5Oi5931pN24_VLZYaQOvmR0OcQuVtgHzFUN1k,2359
25
25
  utilities/hashlib.py,sha256=SVTgtguur0P4elppvzOBbLEjVM3Pea0eWB61yg2ilxo,309
26
26
  utilities/http.py,sha256=WcahTcKYRtZ04WXQoWt5EGCgFPcyHD3EJdlMfxvDt-0,946
27
- utilities/hypothesis.py,sha256=OpZhPdPmsYWvqMytFDc-G196eODosUzxQSuo-LfMYmM,46262
27
+ utilities/hypothesis.py,sha256=a75izXg9aCBhhDkj_ZgK3TDzlzk38evP8TO7JbYYQvg,46264
28
28
  utilities/importlib.py,sha256=ueY3R39hWrUtrVXs39utM2xDig-eyJfYn1FBVxWb3_w,368
29
29
  utilities/ipython.py,sha256=V2oMYHvEKvlNBzxDXdLvKi48oUq2SclRg5xasjaXStw,763
30
30
  utilities/iterables.py,sha256=prKXBdF5QfLTGC-q4567DwO8xzUng_Z-2a4wBkMqyDo,45360
@@ -40,11 +40,11 @@ utilities/more_itertools.py,sha256=6T0225gBFZtv47-B0JRFOKMz836Wg3Hct79ePPLGpuo,5
40
40
  utilities/numpy.py,sha256=Xn23sA2ZbVNqwUYEgNJD3XBYH6IbCri_WkHSNhg3NkY,26122
41
41
  utilities/operator.py,sha256=0M2yZJ0PODH47ogFEnkGMBe_cfxwZR02T_92LZVZvHo,3715
42
42
  utilities/optuna.py,sha256=loyJGWTzljgdJaoLhP09PT8Jz6o_pwBOwehY33lHkhw,1923
43
- utilities/orjson.py,sha256=DBm2zPP04kcHpY3l1etL24ksNynu-R3duFyx3U-RjqQ,36948
43
+ utilities/orjson.py,sha256=AvPFxzJdxC-3PBID3cqdiMyN8FeC7aW9QUgGwbvKuAM,36948
44
44
  utilities/os.py,sha256=D_FyyT-6TtqiN9KSS7c9g1fnUtgxmyMtzAjmYLkk46A,3587
45
45
  utilities/parse.py,sha256=vsZ2jf_ceSI_Kta9titixufysJaVXh0Whjz1T4awJZw,18938
46
46
  utilities/pathlib.py,sha256=31WPMXdLIyXgYOMMl_HOI2wlo66MGSE-cgeelk-Lias,1410
47
- utilities/period.py,sha256=RWfcNVoNlW07RNdU47g_zuLZMKbtgfK4bE6G-9tVjY8,11024
47
+ utilities/period.py,sha256=o4wXYEXVlFomop4-Ra4L0yRP4i99NZFjIe_fa7NdZck,11024
48
48
  utilities/pickle.py,sha256=Bhvd7cZl-zQKQDFjUerqGuSKlHvnW1K2QXeU5UZibtg,657
49
49
  utilities/platform.py,sha256=NU7ycTvAXAG-fdYmDXaM1m4EOml2cGiaYwaUzfzSqyU,1767
50
50
  utilities/polars.py,sha256=fxfSm4xVHwKvRxu50IhYNKCKOagp12FdwsVf04ARKpk,63692
@@ -85,10 +85,10 @@ utilities/tzlocal.py,sha256=3upDNFBvGh1l9njmLR2z2S6K6VxQSb7QizYGUbAH3JU,960
85
85
  utilities/uuid.py,sha256=jJTFxz-CWgltqNuzmythB7iEQ-Q1mCwPevUfKthZT3c,611
86
86
  utilities/version.py,sha256=QFuyEeQA6jI0ruBEcmhqG36f-etg1AEiD1drBBqhQrs,5358
87
87
  utilities/warnings.py,sha256=un1LvHv70PU-LLv8RxPVmugTzDJkkGXRMZTE2-fTQHw,1771
88
- utilities/whenever.py,sha256=fC0ZtnO0AyFHsxP4SWj0POI1bf4BIL3Hh4rR51BHfaw,17803
88
+ utilities/whenever.py,sha256=jS31ZAY5OMxFxLja_Yo5Fidi87Pd-GoVZ7Vi_teqVDA,16743
89
89
  utilities/zipfile.py,sha256=24lQc9ATcJxHXBPc_tBDiJk48pWyRrlxO2fIsFxU0A8,699
90
- utilities/zoneinfo.py,sha256=-Xm57PMMwDTYpxJdkiJG13wnbwK--I7XItBh5WVhD-o,1874
91
- dycw_utilities-0.118.0.dist-info/METADATA,sha256=5nkN-STFMRlbctAGspdNN6t3wanBvmbU4JY8eBG3KVg,12943
92
- dycw_utilities-0.118.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- dycw_utilities-0.118.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
- dycw_utilities-0.118.0.dist-info/RECORD,,
90
+ utilities/zoneinfo.py,sha256=-5j7IQ9nb7gR43rdgA7ms05im-XuqhAk9EJnQBXxCoQ,1874
91
+ dycw_utilities-0.119.0.dist-info/METADATA,sha256=XG8mqNyIqDEemm7CPwNSAdYJS_z_rsP8SqlYoT-DEAY,12943
92
+ dycw_utilities-0.119.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
+ dycw_utilities-0.119.0.dist-info/licenses/LICENSE,sha256=gppZp16M6nSVpBbUBrNL6JuYfvKwZiKgV7XoKKsHzqo,1066
94
+ dycw_utilities-0.119.0.dist-info/RECORD,,
utilities/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  from __future__ import annotations
2
2
 
3
- __version__ = "0.118.0"
3
+ __version__ = "0.119.0"
utilities/click.py CHANGED
@@ -131,10 +131,10 @@ class Enum(ParamType, Generic[TEnum]):
131
131
  return _make_metavar(param, desc)
132
132
 
133
133
 
134
- class LocalDateTime(ParamType):
135
- """A local-datetime-valued parameter."""
134
+ class Month(ParamType):
135
+ """A month-valued parameter."""
136
136
 
137
- name = "local datetime"
137
+ name = "month"
138
138
 
139
139
  @override
140
140
  def __repr__(self) -> str:
@@ -142,21 +142,19 @@ class LocalDateTime(ParamType):
142
142
 
143
143
  @override
144
144
  def convert(
145
- self, value: DateTimeLike, param: Parameter | None, ctx: Context | None
146
- ) -> dt.date:
147
- """Convert a value into the `LocalDateTime` type."""
148
- from utilities.whenever import EnsureLocalDateTimeError, ensure_local_datetime
149
-
145
+ self, value: MonthLike, param: Parameter | None, ctx: Context | None
146
+ ) -> utilities.datetime.Month:
147
+ """Convert a value into the `Month` type."""
150
148
  try:
151
- return ensure_local_datetime(value)
152
- except EnsureLocalDateTimeError as error:
149
+ return ensure_month(value)
150
+ except EnsureMonthError as error:
153
151
  self.fail(str(error), param, ctx)
154
152
 
155
153
 
156
- class Month(ParamType):
157
- """A month-valued parameter."""
154
+ class PlainDateTime(ParamType):
155
+ """A local-datetime-valued parameter."""
158
156
 
159
- name = "month"
157
+ name = "plain datetime"
160
158
 
161
159
  @override
162
160
  def __repr__(self) -> str:
@@ -164,12 +162,14 @@ class Month(ParamType):
164
162
 
165
163
  @override
166
164
  def convert(
167
- self, value: MonthLike, param: Parameter | None, ctx: Context | None
168
- ) -> utilities.datetime.Month:
169
- """Convert a value into the `Month` type."""
165
+ self, value: DateTimeLike, param: Parameter | None, ctx: Context | None
166
+ ) -> dt.date:
167
+ """Convert a value into the `LocalDateTime` type."""
168
+ from utilities.whenever import EnsurePlainDateTimeError, ensure_plain_datetime
169
+
170
170
  try:
171
- return ensure_month(value)
172
- except EnsureMonthError as error:
171
+ return ensure_plain_datetime(value)
172
+ except EnsurePlainDateTimeError as error:
173
173
  self.fail(str(error), param, ctx)
174
174
 
175
175
 
@@ -506,8 +506,8 @@ __all__ = [
506
506
  "ListParameter",
507
507
  "ListStrs",
508
508
  "ListUUIDs",
509
- "LocalDateTime",
510
509
  "Month",
510
+ "PlainDateTime",
511
511
  "Time",
512
512
  "Timedelta",
513
513
  "ZonedDateTime",
utilities/datetime.py CHANGED
@@ -457,7 +457,7 @@ class EnsureMonthError(Exception):
457
457
 
458
458
 
459
459
  def format_datetime_local_and_utc(datetime: dt.datetime, /) -> str:
460
- """Format a local datetime locally & in UTC."""
460
+ """Format a plain datetime locally & in UTC."""
461
461
  time_zone = ensure_time_zone(datetime)
462
462
  if time_zone is UTC:
463
463
  return datetime.strftime("%Y-%m-%d %H:%M:%S (%a, UTC)")
@@ -706,8 +706,8 @@ def is_integral_timedelta(duration: Duration, /) -> bool:
706
706
  ##
707
707
 
708
708
 
709
- def is_local_datetime(obj: Any, /) -> TypeGuard[dt.datetime]:
710
- """Check if an object is a local datetime."""
709
+ def is_plain_datetime(obj: Any, /) -> TypeGuard[dt.datetime]:
710
+ """Check if an object is a plain datetime."""
711
711
  return isinstance(obj, dt.datetime) and (obj.tzinfo is None)
712
712
 
713
713
 
@@ -1105,7 +1105,7 @@ class SerializeCompactError(Exception):
1105
1105
 
1106
1106
  @override
1107
1107
  def __str__(self) -> str:
1108
- return f"Unable to serialize local datetime {self.datetime}"
1108
+ return f"Unable to serialize plain datetime {self.datetime}"
1109
1109
 
1110
1110
 
1111
1111
  def parse_date_compact(text: str, /) -> dt.date:
@@ -1388,7 +1388,7 @@ __all__ = [
1388
1388
  "get_today",
1389
1389
  "get_years",
1390
1390
  "is_integral_timedelta",
1391
- "is_local_datetime",
1391
+ "is_plain_datetime",
1392
1392
  "is_weekday",
1393
1393
  "is_zero_time",
1394
1394
  "is_zoned_datetime",
utilities/hypothesis.py CHANGED
@@ -642,43 +642,6 @@ def lists_fixed_length(
642
642
  ##
643
643
 
644
644
 
645
- @composite
646
- def local_datetimes(
647
- draw: DrawFn,
648
- /,
649
- *,
650
- min_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MIN_NAIVE,
651
- max_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MAX_NAIVE,
652
- round_: RoundMode | None = None,
653
- timedelta: dt.timedelta | None = None,
654
- rel_tol: float | None = None,
655
- abs_tol: float | None = None,
656
- ) -> dt.datetime:
657
- """Strategy for generating local datetimes."""
658
- min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
659
- datetime = draw(datetimes(min_value=min_value_, max_value=max_value_))
660
- if round_ is not None:
661
- if timedelta is None:
662
- raise LocalDateTimesError(round_=round_)
663
- datetime = round_datetime(
664
- datetime, timedelta, mode=round_, rel_tol=rel_tol, abs_tol=abs_tol
665
- )
666
- _ = assume(min_value_ <= datetime <= max_value_)
667
- return datetime
668
-
669
-
670
- @dataclass(kw_only=True, slots=True)
671
- class LocalDateTimesError(Exception):
672
- round_: RoundMode
673
-
674
- @override
675
- def __str__(self) -> str:
676
- return "Rounding requires a timedelta; got None"
677
-
678
-
679
- ##
680
-
681
-
682
645
  @composite
683
646
  def min_and_max_datetimes(
684
647
  draw: DrawFn,
@@ -991,6 +954,43 @@ def paths() -> SearchStrategy[Path]:
991
954
  ##
992
955
 
993
956
 
957
+ @composite
958
+ def plain_datetimes(
959
+ draw: DrawFn,
960
+ /,
961
+ *,
962
+ min_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MIN_NAIVE,
963
+ max_value: MaybeSearchStrategy[dt.datetime] = DATETIME_MAX_NAIVE,
964
+ round_: RoundMode | None = None,
965
+ timedelta: dt.timedelta | None = None,
966
+ rel_tol: float | None = None,
967
+ abs_tol: float | None = None,
968
+ ) -> dt.datetime:
969
+ """Strategy for generating plain datetimes."""
970
+ min_value_, max_value_ = [draw2(draw, v) for v in [min_value, max_value]]
971
+ datetime = draw(datetimes(min_value=min_value_, max_value=max_value_))
972
+ if round_ is not None:
973
+ if timedelta is None:
974
+ raise PlainDateTimesError(round_=round_)
975
+ datetime = round_datetime(
976
+ datetime, timedelta, mode=round_, rel_tol=rel_tol, abs_tol=abs_tol
977
+ )
978
+ _ = assume(min_value_ <= datetime <= max_value_)
979
+ return datetime
980
+
981
+
982
+ @dataclass(kw_only=True, slots=True)
983
+ class PlainDateTimesError(Exception):
984
+ round_: RoundMode
985
+
986
+ @override
987
+ def __str__(self) -> str:
988
+ return "Rounding requires a timedelta; got None"
989
+
990
+
991
+ ##
992
+
993
+
994
994
  @composite
995
995
  def random_states(
996
996
  draw: DrawFn, /, *, seed: MaybeSearchStrategy[int | None] = None
@@ -1478,7 +1478,7 @@ def zoned_datetimes(
1478
1478
  ) -> dt.datetime:
1479
1479
  """Strategy for generating zoned datetimes."""
1480
1480
  from utilities.whenever import (
1481
- CheckValidZonedDateimeError,
1481
+ CheckValidZonedDateTimeError,
1482
1482
  check_valid_zoned_datetime,
1483
1483
  )
1484
1484
 
@@ -1496,7 +1496,7 @@ def zoned_datetimes(
1496
1496
  max_value_ = max_value_.astimezone(time_zone_)
1497
1497
  try:
1498
1498
  datetime = draw(
1499
- local_datetimes(
1499
+ plain_datetimes(
1500
1500
  min_value=min_value_.replace(tzinfo=None),
1501
1501
  max_value=max_value_.replace(tzinfo=None),
1502
1502
  round_=round_,
@@ -1505,13 +1505,13 @@ def zoned_datetimes(
1505
1505
  abs_tol=abs_tol,
1506
1506
  )
1507
1507
  )
1508
- except LocalDateTimesError as error:
1508
+ except PlainDateTimesError as error:
1509
1509
  raise ZonedDateTimesError(round_=error.round_) from None
1510
1510
  datetime = datetime.replace(tzinfo=time_zone_)
1511
1511
  _ = assume(min_value_ <= datetime <= max_value_)
1512
1512
  if valid:
1513
1513
  with assume_does_not_raise( # skipif-ci-and-windows
1514
- CheckValidZonedDateimeError
1514
+ CheckValidZonedDateTimeError
1515
1515
  ):
1516
1516
  check_valid_zoned_datetime(datetime)
1517
1517
  return datetime
@@ -1528,8 +1528,8 @@ class ZonedDateTimesError(Exception):
1528
1528
 
1529
1529
  __all__ = [
1530
1530
  "Draw2Error",
1531
- "LocalDateTimesError",
1532
1531
  "MaybeSearchStrategy",
1532
+ "PlainDateTimesError",
1533
1533
  "Shape",
1534
1534
  "ZonedDateTimesError",
1535
1535
  "assume_does_not_raise",
@@ -1548,8 +1548,6 @@ __all__ = [
1548
1548
  "int64s",
1549
1549
  "int_arrays",
1550
1550
  "lists_fixed_length",
1551
- "local_datetimes",
1552
- "local_datetimes",
1553
1551
  "min_and_max_datetimes",
1554
1552
  "min_and_maybe_max_datetimes",
1555
1553
  "min_and_maybe_max_sizes",
@@ -1559,6 +1557,8 @@ __all__ = [
1559
1557
  "numbers",
1560
1558
  "pairs",
1561
1559
  "paths",
1560
+ "plain_datetimes",
1561
+ "plain_datetimes",
1562
1562
  "random_states",
1563
1563
  "sentinels",
1564
1564
  "sets_fixed_length",
utilities/orjson.py CHANGED
@@ -48,7 +48,7 @@ from utilities.uuid import UUID_PATTERN
48
48
  from utilities.version import Version, parse_version
49
49
  from utilities.whenever import (
50
50
  parse_date,
51
- parse_local_datetime,
51
+ parse_plain_datetime,
52
52
  parse_time,
53
53
  parse_timedelta,
54
54
  parse_zoned_datetime,
@@ -424,7 +424,7 @@ def _object_hook(
424
424
  if match := _FLOAT_PATTERN.search(text):
425
425
  return float(match.group(1))
426
426
  if match := _LOCAL_DATETIME_PATTERN.search(text):
427
- return parse_local_datetime(match.group(1))
427
+ return parse_plain_datetime(match.group(1))
428
428
  if match := _PATH_PATTERN.search(text):
429
429
  return Path(match.group(1))
430
430
  if match := _TIME_PATTERN.search(text):
utilities/period.py CHANGED
@@ -23,7 +23,7 @@ from utilities.sentinel import Sentinel, sentinel
23
23
  from utilities.typing import is_instance_gen
24
24
  from utilities.whenever import (
25
25
  serialize_date,
26
- serialize_local_datetime,
26
+ serialize_plain_datetime,
27
27
  serialize_zoned_datetime,
28
28
  )
29
29
  from utilities.zoneinfo import EnsureTimeZoneError, ensure_time_zone
@@ -137,7 +137,7 @@ class Period(Generic[_TPeriod]):
137
137
  )
138
138
  return f"{cls}({start}, {end})"
139
139
  start, end = (
140
- serialize_local_datetime(t.replace(tzinfo=None))
140
+ serialize_plain_datetime(t.replace(tzinfo=None))
141
141
  for t in [result.start, result.end]
142
142
  )
143
143
  return f"{cls}({start}, {end}, {time_zone})"
utilities/whenever.py CHANGED
@@ -5,9 +5,15 @@ import re
5
5
  from contextlib import suppress
6
6
  from dataclasses import dataclass
7
7
  from typing import TYPE_CHECKING, override
8
- from zoneinfo import ZoneInfo
9
8
 
10
- from whenever import Date, DateTimeDelta, LocalDateTime, Time, ZonedDateTime
9
+ from whenever import (
10
+ Date,
11
+ DateTimeDelta,
12
+ PlainDateTime,
13
+ Time,
14
+ TimeZoneNotFoundError,
15
+ ZonedDateTime,
16
+ )
11
17
 
12
18
  from utilities.datetime import (
13
19
  _MICROSECONDS_PER_DAY,
@@ -37,7 +43,7 @@ if TYPE_CHECKING:
37
43
  )
38
44
 
39
45
 
40
- MAX_SERIALIZABLE_TIMEDELTA = dt.timedelta(days=3659635, microseconds=-1)
46
+ MAX_SERIALIZABLE_TIMEDELTA = dt.timedelta(days=3652060, microseconds=-1)
41
47
  MIN_SERIALIZABLE_TIMEDELTA = -MAX_SERIALIZABLE_TIMEDELTA
42
48
 
43
49
 
@@ -48,19 +54,33 @@ def check_valid_zoned_datetime(datetime: dt.datetime, /) -> None:
48
54
  """Check if a zoned datetime is valid."""
49
55
  time_zone = ensure_time_zone(datetime) # skipif-ci-and-windows
50
56
  datetime2 = datetime.replace(tzinfo=time_zone) # skipif-ci-and-windows
51
- result = ( # skipif-ci-and-windows
52
- ZonedDateTime.from_py_datetime(datetime2)
53
- .to_tz(get_time_zone_name(UTC))
54
- .to_tz(get_time_zone_name(time_zone))
55
- .py_datetime()
56
- )
57
+ try: # skipif-ci-and-windows
58
+ result = (
59
+ ZonedDateTime.from_py_datetime(datetime2)
60
+ .to_tz(get_time_zone_name(UTC))
61
+ .to_tz(get_time_zone_name(time_zone))
62
+ .py_datetime()
63
+ )
64
+ except TimeZoneNotFoundError: # pragma: no cover
65
+ raise _CheckValidZonedDateTimeInvalidTimeZoneError(datetime=datetime) from None
57
66
  if result != datetime2: # skipif-ci-and-windows
58
- raise CheckValidZonedDateimeError(datetime=datetime, result=result)
67
+ raise _CheckValidZonedDateTimeUnequalError(datetime=datetime, result=result)
59
68
 
60
69
 
61
70
  @dataclass(kw_only=True, slots=True)
62
- class CheckValidZonedDateimeError(Exception):
71
+ class CheckValidZonedDateTimeError(Exception):
63
72
  datetime: dt.datetime
73
+
74
+
75
+ @dataclass(kw_only=True, slots=True)
76
+ class _CheckValidZonedDateTimeInvalidTimeZoneError(CheckValidZonedDateTimeError):
77
+ @override
78
+ def __str__(self) -> str:
79
+ return f"Invalid timezone; got {self.datetime.tzinfo}" # pragma: no cover
80
+
81
+
82
+ @dataclass(kw_only=True, slots=True)
83
+ class _CheckValidZonedDateTimeUnequalError(CheckValidZonedDateTimeError):
64
84
  result: dt.datetime
65
85
 
66
86
  @override
@@ -138,23 +158,23 @@ class EnsureDurationError(Exception):
138
158
  ##
139
159
 
140
160
 
141
- def ensure_local_datetime(datetime: DateTimeLike, /) -> dt.datetime:
142
- """Ensure the object is a local datetime."""
161
+ def ensure_plain_datetime(datetime: DateTimeLike, /) -> dt.datetime:
162
+ """Ensure the object is a plain datetime."""
143
163
  if isinstance(datetime, dt.datetime):
144
164
  return datetime
145
165
  try:
146
- return parse_local_datetime(datetime)
147
- except ParseLocalDateTimeError as error:
148
- raise EnsureLocalDateTimeError(datetime=error.datetime) from None
166
+ return parse_plain_datetime(datetime)
167
+ except ParsePlainDateTimeError as error:
168
+ raise EnsurePlainDateTimeError(datetime=error.datetime) from None
149
169
 
150
170
 
151
171
  @dataclass(kw_only=True, slots=True)
152
- class EnsureLocalDateTimeError(Exception):
172
+ class EnsurePlainDateTimeError(Exception):
153
173
  datetime: str
154
174
 
155
175
  @override
156
176
  def __str__(self) -> str:
157
- return f"Unable to ensure local datetime; got {self.datetime!r}"
177
+ return f"Unable to ensure plain datetime; got {self.datetime!r}"
158
178
 
159
179
 
160
180
  ##
@@ -242,7 +262,6 @@ class EnsureZonedDateTimeError(Exception):
242
262
  ##
243
263
 
244
264
 
245
- _PARSE_DATE_YYYYMMDD_REGEX = re.compile(r"^(\d{4})(\d{2})(\d{2})$")
246
265
  _PARSE_DATE_YYMMDD_REGEX = re.compile(r"^(\d{2})(\d{2})(\d{2})$")
247
266
 
248
267
 
@@ -250,19 +269,14 @@ def parse_date(date: str, /) -> dt.date:
250
269
  """Parse a string into a date."""
251
270
  try:
252
271
  w_date = Date.parse_common_iso(date)
253
- except ValueError:
254
- pass
255
- else:
256
- return w_date.py_date()
257
- try:
258
- ((year, month, day),) = _PARSE_DATE_YYYYMMDD_REGEX.findall(date)
259
272
  except ValueError:
260
273
  try:
261
274
  ((year2, month, day),) = _PARSE_DATE_YYMMDD_REGEX.findall(date)
262
275
  except ValueError:
263
276
  raise ParseDateError(date=date) from None
264
277
  year = parse_two_digit_year(year2)
265
- return dt.date(year=int(year), month=int(month), day=int(day))
278
+ return dt.date(year=int(year), month=int(month), day=int(day))
279
+ return w_date.py_date()
266
280
 
267
281
 
268
282
  @dataclass(kw_only=True, slots=True)
@@ -279,8 +293,8 @@ class ParseDateError(Exception):
279
293
 
280
294
  def parse_datetime(datetime: str, /) -> dt.datetime:
281
295
  """Parse a string into a datetime."""
282
- with suppress(ParseLocalDateTimeError):
283
- return parse_local_datetime(datetime)
296
+ with suppress(ParsePlainDateTimeError):
297
+ return parse_plain_datetime(datetime)
284
298
  with suppress(ParseZonedDateTimeError):
285
299
  return parse_zoned_datetime(datetime)
286
300
  raise ParseDateTimeError(datetime=datetime) from None
@@ -320,48 +334,22 @@ class ParseDurationError(Exception):
320
334
  ##
321
335
 
322
336
 
323
- _PARSE_LOCAL_DATETIME_REGEX = re.compile(
324
- r"^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})\.?(\d{6})?$"
325
- )
326
-
327
-
328
- def parse_local_datetime(datetime: str, /) -> dt.datetime:
329
- """Parse a string into a local datetime."""
330
- try:
331
- ldt = LocalDateTime.parse_common_iso(datetime)
332
- except ValueError:
333
- pass
334
- else:
335
- return ldt.py_datetime()
337
+ def parse_plain_datetime(datetime: str, /) -> dt.datetime:
338
+ """Parse a string into a plain datetime."""
336
339
  try:
337
- ((year, month, day, hour, minute, second, microsecond),) = (
338
- _PARSE_LOCAL_DATETIME_REGEX.findall(datetime)
339
- )
340
- except ValueError:
341
- raise ParseLocalDateTimeError(datetime=datetime) from None
342
- try:
343
- microsecond_use = int(microsecond)
340
+ ldt = PlainDateTime.parse_common_iso(datetime)
344
341
  except ValueError:
345
- microsecond_use = 0
346
- return dt.datetime(
347
- year=int(year),
348
- month=int(month),
349
- day=int(day),
350
- hour=int(hour),
351
- minute=int(minute),
352
- second=int(second),
353
- microsecond=microsecond_use,
354
- tzinfo=UTC,
355
- ).replace(tzinfo=None)
342
+ raise ParsePlainDateTimeError(datetime=datetime) from None
343
+ return ldt.py_datetime()
356
344
 
357
345
 
358
346
  @dataclass(kw_only=True, slots=True)
359
- class ParseLocalDateTimeError(Exception):
347
+ class ParsePlainDateTimeError(Exception):
360
348
  datetime: str
361
349
 
362
350
  @override
363
351
  def __str__(self) -> str:
364
- return f"Unable to parse local datetime; got {self.datetime!r}"
352
+ return f"Unable to parse plain datetime; got {self.datetime!r}"
365
353
 
366
354
 
367
355
  ##
@@ -435,39 +423,13 @@ class _ParseTimedeltaNanosecondError(ParseTimedeltaError):
435
423
  ##
436
424
 
437
425
 
438
- _PARSE_ZONED_DATETIME_REGEX = re.compile(
439
- r"^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})\.?(\d{6})?\[([\w\+\-/]+)\]$"
440
- )
441
-
442
-
443
426
  def parse_zoned_datetime(datetime: str, /) -> dt.datetime:
444
427
  """Parse a string into a zoned datetime."""
445
428
  try:
446
429
  zdt = ZonedDateTime.parse_common_iso(datetime)
447
- except ValueError:
448
- pass
449
- else:
450
- return zdt.py_datetime()
451
- try:
452
- ((year, month, day, hour, minute, second, microsecond, timezone),) = (
453
- _PARSE_ZONED_DATETIME_REGEX.findall(datetime)
454
- )
455
430
  except ValueError:
456
431
  raise ParseZonedDateTimeError(datetime=datetime) from None
457
- try: # skipif-ci-and-windows
458
- microsecond_use = int(microsecond)
459
- except ValueError: # skipif-ci-and-windows
460
- microsecond_use = 0
461
- return dt.datetime( # skipif-ci-and-windows
462
- year=int(year),
463
- month=int(month),
464
- day=int(day),
465
- hour=int(hour),
466
- minute=int(minute),
467
- second=int(second),
468
- microsecond=microsecond_use,
469
- tzinfo=ZoneInfo(timezone),
470
- )
432
+ return zdt.py_datetime()
471
433
 
472
434
 
473
435
  @dataclass(kw_only=True, slots=True)
@@ -494,8 +456,8 @@ def serialize_date(date: dt.date, /) -> str:
494
456
  def serialize_datetime(datetime: dt.datetime, /) -> str:
495
457
  """Serialize a datetime."""
496
458
  try:
497
- return serialize_local_datetime(datetime)
498
- except SerializeLocalDateTimeError:
459
+ return serialize_plain_datetime(datetime)
460
+ except SerializePlainDateTimeError:
499
461
  return serialize_zoned_datetime(datetime)
500
462
 
501
463
 
@@ -524,22 +486,22 @@ class SerializeDurationError(Exception):
524
486
  ##
525
487
 
526
488
 
527
- def serialize_local_datetime(datetime: dt.datetime, /) -> str:
528
- """Serialize a local datetime."""
489
+ def serialize_plain_datetime(datetime: dt.datetime, /) -> str:
490
+ """Serialize a plain datetime."""
529
491
  try:
530
- ldt = LocalDateTime.from_py_datetime(datetime)
492
+ pdt = PlainDateTime.from_py_datetime(datetime)
531
493
  except ValueError:
532
- raise SerializeLocalDateTimeError(datetime=datetime) from None
533
- return ldt.format_common_iso()
494
+ raise SerializePlainDateTimeError(datetime=datetime) from None
495
+ return pdt.format_common_iso()
534
496
 
535
497
 
536
498
  @dataclass(kw_only=True, slots=True)
537
- class SerializeLocalDateTimeError(Exception):
499
+ class SerializePlainDateTimeError(Exception):
538
500
  datetime: dt.datetime
539
501
 
540
502
  @override
541
503
  def __str__(self) -> str:
542
- return f"Unable to serialize local datetime; got {self.datetime}"
504
+ return f"Unable to serialize plain datetime; got {self.datetime}"
543
505
 
544
506
 
545
507
  ##
@@ -630,43 +592,43 @@ class _ToDateTimeDeltaError(Exception):
630
592
  __all__ = [
631
593
  "MAX_SERIALIZABLE_TIMEDELTA",
632
594
  "MIN_SERIALIZABLE_TIMEDELTA",
633
- "CheckValidZonedDateimeError",
595
+ "CheckValidZonedDateTimeError",
634
596
  "EnsureDateError",
635
597
  "EnsureDateTimeError",
636
- "EnsureLocalDateTimeError",
598
+ "EnsurePlainDateTimeError",
637
599
  "EnsureTimeError",
638
600
  "EnsureTimedeltaError",
639
601
  "EnsureZonedDateTimeError",
640
602
  "ParseDateError",
641
603
  "ParseDateTimeError",
642
604
  "ParseDurationError",
643
- "ParseLocalDateTimeError",
605
+ "ParsePlainDateTimeError",
644
606
  "ParseTimeError",
645
607
  "ParseTimedeltaError",
646
608
  "ParseZonedDateTimeError",
647
609
  "SerializeDurationError",
648
- "SerializeLocalDateTimeError",
610
+ "SerializePlainDateTimeError",
649
611
  "SerializeTimeDeltaError",
650
612
  "SerializeZonedDateTimeError",
651
613
  "check_valid_zoned_datetime",
652
614
  "ensure_date",
653
615
  "ensure_datetime",
654
616
  "ensure_duration",
655
- "ensure_local_datetime",
617
+ "ensure_plain_datetime",
656
618
  "ensure_time",
657
619
  "ensure_timedelta",
658
620
  "ensure_zoned_datetime",
659
621
  "parse_date",
660
622
  "parse_datetime",
661
623
  "parse_duration",
662
- "parse_local_datetime",
624
+ "parse_plain_datetime",
663
625
  "parse_time",
664
626
  "parse_timedelta",
665
627
  "parse_zoned_datetime",
666
628
  "serialize_date",
667
629
  "serialize_datetime",
668
630
  "serialize_duration",
669
- "serialize_local_datetime",
631
+ "serialize_plain_datetime",
670
632
  "serialize_time",
671
633
  "serialize_timedelta",
672
634
  "serialize_zoned_datetime",
utilities/zoneinfo.py CHANGED
@@ -32,7 +32,7 @@ def ensure_time_zone(obj: TimeZoneLike, /) -> ZoneInfo:
32
32
  raise _EnsureTimeZoneInvalidTZInfoError(time_zone=obj)
33
33
  case dt.datetime() as datetime:
34
34
  if datetime.tzinfo is None:
35
- raise _EnsureTimeZoneLocalDateTimeError(datetime=datetime)
35
+ raise _EnsureTimeZonePlainDateTimeError(datetime=datetime)
36
36
  return ensure_time_zone(datetime.tzinfo)
37
37
  case _ as never:
38
38
  assert_never(never)
@@ -52,12 +52,12 @@ class _EnsureTimeZoneInvalidTZInfoError(EnsureTimeZoneError):
52
52
 
53
53
 
54
54
  @dataclass(kw_only=True, slots=True)
55
- class _EnsureTimeZoneLocalDateTimeError(EnsureTimeZoneError):
55
+ class _EnsureTimeZonePlainDateTimeError(EnsureTimeZoneError):
56
56
  datetime: dt.datetime
57
57
 
58
58
  @override
59
59
  def __str__(self) -> str:
60
- return f"Local datetime: {self.datetime}"
60
+ return f"Plain datetime: {self.datetime}"
61
61
 
62
62
 
63
63
  ##