alexwlchan-chives 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.
- alexwlchan_chives-1/LICENSE +19 -0
- alexwlchan_chives-1/PKG-INFO +68 -0
- alexwlchan_chives-1/README.md +52 -0
- alexwlchan_chives-1/pyproject.toml +57 -0
- alexwlchan_chives-1/setup.cfg +4 -0
- alexwlchan_chives-1/src/alexwlchan_chives.egg-info/PKG-INFO +68 -0
- alexwlchan_chives-1/src/alexwlchan_chives.egg-info/SOURCES.txt +11 -0
- alexwlchan_chives-1/src/alexwlchan_chives.egg-info/dependency_links.txt +1 -0
- alexwlchan_chives-1/src/alexwlchan_chives.egg-info/top_level.txt +1 -0
- alexwlchan_chives-1/src/chives/__init__.py +28 -0
- alexwlchan_chives-1/src/chives/py.typed +0 -0
- alexwlchan_chives-1/src/chives/timestamps.py +73 -0
- alexwlchan_chives-1/tests/test_timestamps.py +62 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2025 Alex Chan
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
|
4
|
+
copy of this software and associated documentation files (the "Software"),
|
|
5
|
+
to deal in the Software without restriction, including without limitation
|
|
6
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
7
|
+
and/or sell copies of the Software, and to permit persons to whom the Software
|
|
8
|
+
is furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
16
|
+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
17
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
18
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
19
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: alexwlchan-chives
|
|
3
|
+
Version: 1
|
|
4
|
+
Summary: Utility functions for working with my local media archives
|
|
5
|
+
Author-email: Alex Chan <alex@alexwlchan.net>
|
|
6
|
+
Maintainer-email: Alex Chan <alex@alexwlchan.net>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/alexwlchan/chives
|
|
9
|
+
Project-URL: Changelog, https://github.com/alexwlchan/chives/blob/main/CHANGELOG.md
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Requires-Python: >=3.13
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# chives
|
|
18
|
+
|
|
19
|
+
chives is a collection of Python functions for working with my local
|
|
20
|
+
media archives.
|
|
21
|
+
|
|
22
|
+
I store a lot of media archives as [static websites][static-sites], and I use Python scripts to manage the sites.
|
|
23
|
+
This includes:
|
|
24
|
+
|
|
25
|
+
* Verifying every file that's described in the metadata is stored correctly
|
|
26
|
+
* Downloading pages from sites I want to bookmark
|
|
27
|
+
* Checking the quality and consistency of my metadata
|
|
28
|
+
|
|
29
|
+
This package has some functions I share across multiple archives/sites.
|
|
30
|
+
|
|
31
|
+
[static-sites]: https://alexwlchan.net/2024/static-websites/
|
|
32
|
+
|
|
33
|
+
## References
|
|
34
|
+
|
|
35
|
+
I've written blog posts about some of the code in this repo:
|
|
36
|
+
|
|
37
|
+
* [Cleaning up messy dates in JSON](https://alexwlchan.net/2025/messy-dates-in-json/)
|
|
38
|
+
|
|
39
|
+
## Versioning
|
|
40
|
+
|
|
41
|
+
This library is monotically versioned.
|
|
42
|
+
I'll try not to break anything between releases, but I make no guarantees of back-compatibility.
|
|
43
|
+
|
|
44
|
+
I'm making this public because it's convenient for me, and you might find useful code here, but be aware this may not be entirely stable.
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
All the functions are available in the `chives` namespace.
|
|
49
|
+
|
|
50
|
+
See the docstrings on individual functions for usage descriptions.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
If you want to use this in your project, I recommend copying the relevant function and test into your codebase (with a link back to this repo).
|
|
55
|
+
|
|
56
|
+
Alternatively, you can install the package from PyPI:
|
|
57
|
+
|
|
58
|
+
```console
|
|
59
|
+
$ pip install alexwlchan-chives
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Development
|
|
63
|
+
|
|
64
|
+
If you want to make changes to the library, there are instructions in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# chives
|
|
2
|
+
|
|
3
|
+
chives is a collection of Python functions for working with my local
|
|
4
|
+
media archives.
|
|
5
|
+
|
|
6
|
+
I store a lot of media archives as [static websites][static-sites], and I use Python scripts to manage the sites.
|
|
7
|
+
This includes:
|
|
8
|
+
|
|
9
|
+
* Verifying every file that's described in the metadata is stored correctly
|
|
10
|
+
* Downloading pages from sites I want to bookmark
|
|
11
|
+
* Checking the quality and consistency of my metadata
|
|
12
|
+
|
|
13
|
+
This package has some functions I share across multiple archives/sites.
|
|
14
|
+
|
|
15
|
+
[static-sites]: https://alexwlchan.net/2024/static-websites/
|
|
16
|
+
|
|
17
|
+
## References
|
|
18
|
+
|
|
19
|
+
I've written blog posts about some of the code in this repo:
|
|
20
|
+
|
|
21
|
+
* [Cleaning up messy dates in JSON](https://alexwlchan.net/2025/messy-dates-in-json/)
|
|
22
|
+
|
|
23
|
+
## Versioning
|
|
24
|
+
|
|
25
|
+
This library is monotically versioned.
|
|
26
|
+
I'll try not to break anything between releases, but I make no guarantees of back-compatibility.
|
|
27
|
+
|
|
28
|
+
I'm making this public because it's convenient for me, and you might find useful code here, but be aware this may not be entirely stable.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
All the functions are available in the `chives` namespace.
|
|
33
|
+
|
|
34
|
+
See the docstrings on individual functions for usage descriptions.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
If you want to use this in your project, I recommend copying the relevant function and test into your codebase (with a link back to this repo).
|
|
39
|
+
|
|
40
|
+
Alternatively, you can install the package from PyPI:
|
|
41
|
+
|
|
42
|
+
```console
|
|
43
|
+
$ pip install alexwlchan-chives
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
If you want to make changes to the library, there are instructions in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
49
|
+
|
|
50
|
+
## License
|
|
51
|
+
|
|
52
|
+
MIT.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools >= 65",
|
|
4
|
+
]
|
|
5
|
+
build-backend = "setuptools.build_meta"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "alexwlchan-chives"
|
|
9
|
+
description = "Utility functions for working with my local media archives"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Alex Chan", email = "alex@alexwlchan.net"},
|
|
13
|
+
]
|
|
14
|
+
maintainers = [
|
|
15
|
+
{name = "Alex Chan", email="alex@alexwlchan.net"},
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
]
|
|
21
|
+
requires-python = ">=3.13"
|
|
22
|
+
dependencies = []
|
|
23
|
+
dynamic = ["version"]
|
|
24
|
+
license = "MIT"
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
"Homepage" = "https://github.com/alexwlchan/chives"
|
|
28
|
+
"Changelog" = "https://github.com/alexwlchan/chives/blob/main/CHANGELOG.md"
|
|
29
|
+
|
|
30
|
+
[tool.setuptools.dynamic]
|
|
31
|
+
version = {attr = "chives.__version__"}
|
|
32
|
+
|
|
33
|
+
[tool.setuptools.packages.find]
|
|
34
|
+
where = ["src"]
|
|
35
|
+
|
|
36
|
+
[tool.setuptools.package-data]
|
|
37
|
+
nitrate = ["py.typed"]
|
|
38
|
+
|
|
39
|
+
[tool.coverage.run]
|
|
40
|
+
branch = true
|
|
41
|
+
source = ["chives", "tests",]
|
|
42
|
+
|
|
43
|
+
[tool.coverage.report]
|
|
44
|
+
show_missing = true
|
|
45
|
+
skip_covered = true
|
|
46
|
+
fail_under = 100
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
filterwarnings = ["error"]
|
|
50
|
+
|
|
51
|
+
[tool.mypy]
|
|
52
|
+
mypy_path = "src"
|
|
53
|
+
strict = true
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
select = ["D"]
|
|
57
|
+
ignore = ["D200", "D203", "D204", "D205", "D212", "D401"]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: alexwlchan-chives
|
|
3
|
+
Version: 1
|
|
4
|
+
Summary: Utility functions for working with my local media archives
|
|
5
|
+
Author-email: Alex Chan <alex@alexwlchan.net>
|
|
6
|
+
Maintainer-email: Alex Chan <alex@alexwlchan.net>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/alexwlchan/chives
|
|
9
|
+
Project-URL: Changelog, https://github.com/alexwlchan/chives/blob/main/CHANGELOG.md
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Requires-Python: >=3.13
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# chives
|
|
18
|
+
|
|
19
|
+
chives is a collection of Python functions for working with my local
|
|
20
|
+
media archives.
|
|
21
|
+
|
|
22
|
+
I store a lot of media archives as [static websites][static-sites], and I use Python scripts to manage the sites.
|
|
23
|
+
This includes:
|
|
24
|
+
|
|
25
|
+
* Verifying every file that's described in the metadata is stored correctly
|
|
26
|
+
* Downloading pages from sites I want to bookmark
|
|
27
|
+
* Checking the quality and consistency of my metadata
|
|
28
|
+
|
|
29
|
+
This package has some functions I share across multiple archives/sites.
|
|
30
|
+
|
|
31
|
+
[static-sites]: https://alexwlchan.net/2024/static-websites/
|
|
32
|
+
|
|
33
|
+
## References
|
|
34
|
+
|
|
35
|
+
I've written blog posts about some of the code in this repo:
|
|
36
|
+
|
|
37
|
+
* [Cleaning up messy dates in JSON](https://alexwlchan.net/2025/messy-dates-in-json/)
|
|
38
|
+
|
|
39
|
+
## Versioning
|
|
40
|
+
|
|
41
|
+
This library is monotically versioned.
|
|
42
|
+
I'll try not to break anything between releases, but I make no guarantees of back-compatibility.
|
|
43
|
+
|
|
44
|
+
I'm making this public because it's convenient for me, and you might find useful code here, but be aware this may not be entirely stable.
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
All the functions are available in the `chives` namespace.
|
|
49
|
+
|
|
50
|
+
See the docstrings on individual functions for usage descriptions.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
If you want to use this in your project, I recommend copying the relevant function and test into your codebase (with a link back to this repo).
|
|
55
|
+
|
|
56
|
+
Alternatively, you can install the package from PyPI:
|
|
57
|
+
|
|
58
|
+
```console
|
|
59
|
+
$ pip install alexwlchan-chives
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Development
|
|
63
|
+
|
|
64
|
+
If you want to make changes to the library, there are instructions in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/alexwlchan_chives.egg-info/PKG-INFO
|
|
5
|
+
src/alexwlchan_chives.egg-info/SOURCES.txt
|
|
6
|
+
src/alexwlchan_chives.egg-info/dependency_links.txt
|
|
7
|
+
src/alexwlchan_chives.egg-info/top_level.txt
|
|
8
|
+
src/chives/__init__.py
|
|
9
|
+
src/chives/py.typed
|
|
10
|
+
src/chives/timestamps.py
|
|
11
|
+
tests/test_timestamps.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
chives
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""
|
|
2
|
+
chives is a collection of Python functions for working with my local
|
|
3
|
+
media archives.
|
|
4
|
+
|
|
5
|
+
I store a lot of media archives as static websites [1][2], and I use
|
|
6
|
+
Python scripts to manage my media. This package has some functions
|
|
7
|
+
I share across multiple sites.
|
|
8
|
+
|
|
9
|
+
[1]: https://alexwlchan.net/2024/static-websites/
|
|
10
|
+
[2]: https://alexwlchan.net/2025/mildly-dynamic-websites/
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .timestamps import (
|
|
15
|
+
find_all_dates,
|
|
16
|
+
date_matches_format,
|
|
17
|
+
date_matches_any_format,
|
|
18
|
+
reformat_date,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__version__ = "1"
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"date_matches_any_format",
|
|
25
|
+
"date_matches_format",
|
|
26
|
+
"find_all_dates",
|
|
27
|
+
"reformat_date",
|
|
28
|
+
]
|
|
File without changes
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Functions for interacting with timestamps and date strings.
|
|
3
|
+
|
|
4
|
+
References:
|
|
5
|
+
* https://alexwlchan.net/2025/messy-dates-in-json/
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from collections.abc import Iterable, Iterator
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def find_all_dates(json_value: Any) -> Iterator[tuple[dict[str, Any], str, str]]:
|
|
15
|
+
"""
|
|
16
|
+
Find all the timestamps in a heavily nested JSON object.
|
|
17
|
+
|
|
18
|
+
This function looks for any JSON objects with a key-value pair
|
|
19
|
+
where the key starts with `date_` and the value is a string, and
|
|
20
|
+
emits a 3-tuple:
|
|
21
|
+
|
|
22
|
+
* the JSON object
|
|
23
|
+
* the key
|
|
24
|
+
* the value
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
if isinstance(json_value, dict):
|
|
28
|
+
for key, value in json_value.items():
|
|
29
|
+
if (
|
|
30
|
+
isinstance(key, str)
|
|
31
|
+
and key.startswith("date_")
|
|
32
|
+
and isinstance(value, str)
|
|
33
|
+
):
|
|
34
|
+
yield json_value, key, value
|
|
35
|
+
else:
|
|
36
|
+
yield from find_all_dates(value)
|
|
37
|
+
elif isinstance(json_value, list):
|
|
38
|
+
for value in json_value:
|
|
39
|
+
yield from find_all_dates(value)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def date_matches_format(date_string: str, format: str) -> bool:
|
|
43
|
+
"""
|
|
44
|
+
Returns True if `date_string` can be parsed as a datetime
|
|
45
|
+
using `format`, False otherwise.
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
datetime.strptime(date_string, format)
|
|
49
|
+
return True
|
|
50
|
+
except ValueError:
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def date_matches_any_format(date_string: str, formats: Iterable[str]) -> bool:
|
|
55
|
+
"""
|
|
56
|
+
Returns True if `date_string` can be parsed as a datetime
|
|
57
|
+
with any of the `formats`, False otherwise.
|
|
58
|
+
"""
|
|
59
|
+
return any(date_matches_format(date_string, fmt) for fmt in formats)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def reformat_date(s: str, /, orig_fmt: str) -> str:
|
|
63
|
+
"""
|
|
64
|
+
Reformat a date to one of my desired formats.
|
|
65
|
+
"""
|
|
66
|
+
if "%Z" in orig_fmt:
|
|
67
|
+
d = datetime.strptime(s, orig_fmt)
|
|
68
|
+
else:
|
|
69
|
+
d = datetime.strptime(s.replace("Z", "+0000"), orig_fmt.replace("Z", "%z"))
|
|
70
|
+
d = d.replace(microsecond=0)
|
|
71
|
+
if d.tzinfo is None:
|
|
72
|
+
d = d.replace(tzinfo=timezone.utc)
|
|
73
|
+
return d.strftime("%Y-%m-%dT%H:%M:%S%z").replace("+0000", "Z")
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Tests for `chives.timestamps`."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from chives import date_matches_any_format, find_all_dates, reformat_date
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_find_all_dates() -> None:
|
|
11
|
+
"""find_all_dates finds all the nested dates in a JSON object."""
|
|
12
|
+
json_value = json.loads("""{
|
|
13
|
+
"doc1": {"id": "1", "date_created": "2025-10-14T05:34:07+0000"},
|
|
14
|
+
"shapes": [
|
|
15
|
+
{"color": "blue", "date_saved": "2015-03-01 23:34:39 +00:00"},
|
|
16
|
+
{"color": "yellow", "date_saved": "2013-9-21 13:43:00Z", "is_square": true},
|
|
17
|
+
{"color": "green", "date_saved": null}
|
|
18
|
+
],
|
|
19
|
+
"date_verified": "2024-08-30"
|
|
20
|
+
}""")
|
|
21
|
+
|
|
22
|
+
assert list(find_all_dates(json_value)) == [
|
|
23
|
+
(
|
|
24
|
+
{"id": "1", "date_created": "2025-10-14T05:34:07+0000"},
|
|
25
|
+
"date_created",
|
|
26
|
+
"2025-10-14T05:34:07+0000",
|
|
27
|
+
),
|
|
28
|
+
(
|
|
29
|
+
{"color": "blue", "date_saved": "2015-03-01 23:34:39 +00:00"},
|
|
30
|
+
"date_saved",
|
|
31
|
+
"2015-03-01 23:34:39 +00:00",
|
|
32
|
+
),
|
|
33
|
+
(
|
|
34
|
+
{"color": "yellow", "date_saved": "2013-9-21 13:43:00Z", "is_square": True},
|
|
35
|
+
"date_saved",
|
|
36
|
+
"2013-9-21 13:43:00Z",
|
|
37
|
+
),
|
|
38
|
+
(json_value, "date_verified", "2024-08-30"),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_date_matches_any_format() -> None:
|
|
43
|
+
"""
|
|
44
|
+
Tests for `date_matches_any_format`.
|
|
45
|
+
"""
|
|
46
|
+
assert date_matches_any_format(
|
|
47
|
+
"2001-01-01", formats=["%Y-%m-%d", "%Y-%m-%dT%H:%M:%S%z"]
|
|
48
|
+
)
|
|
49
|
+
assert not date_matches_any_format("2001-01-01", formats=["%Y-%m-%dT%H:%M:%S%z"])
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@pytest.mark.parametrize(
|
|
53
|
+
"s, orig_fmt, formatted_date",
|
|
54
|
+
[
|
|
55
|
+
("2025-11-12T15:34:39.570Z", "%Y-%m-%dT%H:%M:%S.%fZ", "2025-11-12T15:34:39Z"),
|
|
56
|
+
("2025-03-12 09:57:03", "%Y-%m-%d %H:%M:%S", "2025-03-12T09:57:03Z"),
|
|
57
|
+
("2016-02-25 05:28:35 GMT", "%Y-%m-%d %H:%M:%S %Z", "2016-02-25T05:28:35Z"),
|
|
58
|
+
],
|
|
59
|
+
)
|
|
60
|
+
def test_reformat_date(s: str, orig_fmt: str, formatted_date: str) -> None:
|
|
61
|
+
"""Tests for `reformat_date`."""
|
|
62
|
+
assert reformat_date(s, orig_fmt) == formatted_date
|