khmer-time-format 0.1.0__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.
- khmer_time_format-0.1.0/.github/workflows/ci.yml +15 -0
- khmer_time_format-0.1.0/.github/workflows/publish.yml +25 -0
- khmer_time_format-0.1.0/.gitignore +9 -0
- khmer_time_format-0.1.0/CHANGELOG.md +4 -0
- khmer_time_format-0.1.0/LICENSE +3 -0
- khmer_time_format-0.1.0/PKG-INFO +76 -0
- khmer_time_format-0.1.0/README.md +55 -0
- khmer_time_format-0.1.0/pyproject.toml +41 -0
- khmer_time_format-0.1.0/setup.cfg +4 -0
- khmer_time_format-0.1.0/src/khmer_time_format/__init__.py +10 -0
- khmer_time_format-0.1.0/src/khmer_time_format/formatter.py +104 -0
- khmer_time_format-0.1.0/src/khmer_time_format.egg-info/PKG-INFO +76 -0
- khmer_time_format-0.1.0/src/khmer_time_format.egg-info/SOURCES.txt +15 -0
- khmer_time_format-0.1.0/src/khmer_time_format.egg-info/dependency_links.txt +1 -0
- khmer_time_format-0.1.0/src/khmer_time_format.egg-info/requires.txt +5 -0
- khmer_time_format-0.1.0/src/khmer_time_format.egg-info/top_level.txt +1 -0
- khmer_time_format-0.1.0/tests/test_formatter.py +13 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
jobs:
|
|
4
|
+
test:
|
|
5
|
+
runs-on: ubuntu-latest
|
|
6
|
+
steps:
|
|
7
|
+
- uses: actions/checkout@v4
|
|
8
|
+
- uses: actions/setup-python@v5
|
|
9
|
+
with:
|
|
10
|
+
python-version: "3.11"
|
|
11
|
+
- run: python -m pip install -U pip
|
|
12
|
+
- run: pip install -e ".[dev]"
|
|
13
|
+
- run: ruff check .
|
|
14
|
+
- run: mypy src
|
|
15
|
+
- run: pytest
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags:
|
|
5
|
+
- "v*"
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
contents: read
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
with:
|
|
16
|
+
fetch-depth: 0
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.11"
|
|
20
|
+
- run: python -m pip install -U build
|
|
21
|
+
- run: python -m build
|
|
22
|
+
- run: python -m pip install -U twine
|
|
23
|
+
- run: python -m twine check dist/*
|
|
24
|
+
- name: Publish
|
|
25
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: khmer-time-format
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Format 12/24 hour time into Khmer (digits or words).
|
|
5
|
+
Author: Kon Thaina
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Konthaina/khmer-time-format-py
|
|
8
|
+
Project-URL: Repository, https://github.com/Konthaina/khmer-time-format-py
|
|
9
|
+
Keywords: khmer,time,format
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
18
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
19
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# khmer-time-format (Python)
|
|
23
|
+
|
|
24
|
+
Format 12-hour / 24-hour time (e.g. `1:22 PM`, `13:22`) into Khmer with **two options**:
|
|
25
|
+
|
|
26
|
+
1) **Khmer numerals (digits)**
|
|
27
|
+
`ម៉ោង១ និង ២២ នាទី រសៀល`
|
|
28
|
+
|
|
29
|
+
2) **Khmer words (no digits)**
|
|
30
|
+
`ម៉ោងមួយ និង ម្ភៃពីរ នាទី រសៀល`
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install khmer-time-format
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from khmer_time_format import format_time
|
|
42
|
+
|
|
43
|
+
print(format_time("1:22 PM", mode="digits"))
|
|
44
|
+
print(format_time("13:22", mode="words"))
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Development
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m venv .venv
|
|
51
|
+
# Windows: .venv\Scripts\activate
|
|
52
|
+
# macOS/Linux: source .venv/bin/activate
|
|
53
|
+
pip install -e ".[dev]"
|
|
54
|
+
pytest
|
|
55
|
+
ruff check .
|
|
56
|
+
mypy src
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Build & publish (PyPI)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python -m build
|
|
63
|
+
python -m twine check dist/*
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Push a version tag to publish to PyPI via GitHub Actions:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# tag value becomes package version
|
|
70
|
+
git tag v0.1.0
|
|
71
|
+
git push origin v0.1.0
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Tag pushes matching `v*` trigger `.github/workflows/publish.yml`.
|
|
75
|
+
|
|
76
|
+
With this setup, you do not need to edit the version in `pyproject.toml` for each release.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# khmer-time-format (Python)
|
|
2
|
+
|
|
3
|
+
Format 12-hour / 24-hour time (e.g. `1:22 PM`, `13:22`) into Khmer with **two options**:
|
|
4
|
+
|
|
5
|
+
1) **Khmer numerals (digits)**
|
|
6
|
+
`ម៉ោង១ និង ២២ នាទី រសៀល`
|
|
7
|
+
|
|
8
|
+
2) **Khmer words (no digits)**
|
|
9
|
+
`ម៉ោងមួយ និង ម្ភៃពីរ នាទី រសៀល`
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install khmer-time-format
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from khmer_time_format import format_time
|
|
21
|
+
|
|
22
|
+
print(format_time("1:22 PM", mode="digits"))
|
|
23
|
+
print(format_time("13:22", mode="words"))
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Development
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
python -m venv .venv
|
|
30
|
+
# Windows: .venv\Scripts\activate
|
|
31
|
+
# macOS/Linux: source .venv/bin/activate
|
|
32
|
+
pip install -e ".[dev]"
|
|
33
|
+
pytest
|
|
34
|
+
ruff check .
|
|
35
|
+
mypy src
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Build & publish (PyPI)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
python -m build
|
|
42
|
+
python -m twine check dist/*
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Push a version tag to publish to PyPI via GitHub Actions:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# tag value becomes package version
|
|
49
|
+
git tag v0.1.0
|
|
50
|
+
git push origin v0.1.0
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Tag pushes matching `v*` trigger `.github/workflows/publish.yml`.
|
|
54
|
+
|
|
55
|
+
With this setup, you do not need to edit the version in `pyproject.toml` for each release.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "setuptools-scm[toml]>=8", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "khmer-time-format"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Format 12/24 hour time into Khmer (digits or words)."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [{name = "Kon Thaina"}]
|
|
13
|
+
keywords = ["khmer", "time", "format"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent"
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://github.com/Konthaina/khmer-time-format-py"
|
|
22
|
+
Repository = "https://github.com/Konthaina/khmer-time-format-py"
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
dev = ["pytest>=7", "ruff>=0.5", "mypy>=1.10"]
|
|
26
|
+
|
|
27
|
+
[tool.pytest.ini_options]
|
|
28
|
+
testpaths = ["tests"]
|
|
29
|
+
|
|
30
|
+
[tool.ruff]
|
|
31
|
+
line-length = 88
|
|
32
|
+
target-version = "py38"
|
|
33
|
+
|
|
34
|
+
[tool.mypy]
|
|
35
|
+
python_version = "3.8"
|
|
36
|
+
strict = true
|
|
37
|
+
mypy_path = ["src"]
|
|
38
|
+
|
|
39
|
+
[tool.setuptools_scm]
|
|
40
|
+
fallback_version = "0.0.0"
|
|
41
|
+
local_scheme = "no-local-version"
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Literal, Tuple
|
|
5
|
+
|
|
6
|
+
Mode = Literal["digits", "words"]
|
|
7
|
+
|
|
8
|
+
_KHMER_DIGITS = str.maketrans(
|
|
9
|
+
{"0": "០", "1": "១", "2": "២", "3": "៣", "4": "៤", "5": "៥", "6": "៦", "7": "៧", "8": "៨", "9": "៩"}
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
_UNITS = {
|
|
13
|
+
0: "សូន្យ",
|
|
14
|
+
1: "មួយ",
|
|
15
|
+
2: "ពីរ",
|
|
16
|
+
3: "បី",
|
|
17
|
+
4: "បួន",
|
|
18
|
+
5: "ប្រាំ",
|
|
19
|
+
6: "ប្រាំមួយ",
|
|
20
|
+
7: "ប្រាំពីរ",
|
|
21
|
+
8: "ប្រាំបី",
|
|
22
|
+
9: "ប្រាំបួន",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_TENS = {10: "ដប់", 20: "ម្ភៃ", 30: "សាមសិប", 40: "សែសិប", 50: "ហាសិប"}
|
|
26
|
+
|
|
27
|
+
_TIME_RE = re.compile(r"^\s*(\d{1,2})\s*:\s*(\d{2})\s*(AM|PM)?\s*$", re.IGNORECASE)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _number_to_khmer_words(n: int) -> str:
|
|
31
|
+
if n < 0 or n > 59:
|
|
32
|
+
raise ValueError("number out of supported range (0-59)")
|
|
33
|
+
if n < 10:
|
|
34
|
+
return _UNITS[n]
|
|
35
|
+
if n < 20:
|
|
36
|
+
if n == 10:
|
|
37
|
+
return _TENS[10]
|
|
38
|
+
return _TENS[10] + _UNITS[n - 10]
|
|
39
|
+
tens = (n // 10) * 10
|
|
40
|
+
ones = n % 10
|
|
41
|
+
if ones == 0:
|
|
42
|
+
return _TENS[tens]
|
|
43
|
+
return _TENS[tens] + _UNITS[ones]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _number_to_khmer_digits(n: int) -> str:
|
|
47
|
+
return str(n).translate(_KHMER_DIGITS)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _period_km(hour24: int) -> str:
|
|
51
|
+
if 0 <= hour24 <= 5:
|
|
52
|
+
return "យប់"
|
|
53
|
+
if 6 <= hour24 <= 11:
|
|
54
|
+
return "ព្រឹក"
|
|
55
|
+
if 12 <= hour24 <= 17:
|
|
56
|
+
return "រសៀល"
|
|
57
|
+
return "ល្ងាច"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _to_12h(hour24: int) -> int:
|
|
61
|
+
h = hour24 % 12
|
|
62
|
+
return 12 if h == 0 else h
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _parse_time(time_str: str) -> Tuple[int, int]:
|
|
66
|
+
m = _TIME_RE.match(time_str)
|
|
67
|
+
if not m:
|
|
68
|
+
raise ValueError("Invalid time format. Use 'H:MM', 'HH:MM', or 'H:MM AM/PM'.")
|
|
69
|
+
hour = int(m.group(1))
|
|
70
|
+
minute = int(m.group(2))
|
|
71
|
+
ampm = m.group(3)
|
|
72
|
+
if minute < 0 or minute > 59:
|
|
73
|
+
raise ValueError("Minute must be 00-59.")
|
|
74
|
+
if ampm:
|
|
75
|
+
if hour < 1 or hour > 12:
|
|
76
|
+
raise ValueError("Hour must be 1-12 when using AM/PM.")
|
|
77
|
+
ap = ampm.upper()
|
|
78
|
+
if ap == "AM":
|
|
79
|
+
hour24 = 0 if hour == 12 else hour
|
|
80
|
+
else:
|
|
81
|
+
hour24 = 12 if hour == 12 else hour + 12
|
|
82
|
+
else:
|
|
83
|
+
if hour < 0 or hour > 23:
|
|
84
|
+
raise ValueError("Hour must be 0-23 for 24-hour input.")
|
|
85
|
+
hour24 = hour
|
|
86
|
+
return hour24, minute
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def format_time(time_str: str, mode: Mode = "digits") -> str:
|
|
90
|
+
hour24, minute = _parse_time(time_str)
|
|
91
|
+
hour12 = _to_12h(hour24)
|
|
92
|
+
period = _period_km(hour24)
|
|
93
|
+
|
|
94
|
+
if mode == "digits":
|
|
95
|
+
h = _number_to_khmer_digits(hour12)
|
|
96
|
+
m = _number_to_khmer_digits(minute)
|
|
97
|
+
return f"ម៉ោង{h} និង {m} នាទី {period}"
|
|
98
|
+
|
|
99
|
+
if mode == "words":
|
|
100
|
+
h = _number_to_khmer_words(hour12)
|
|
101
|
+
m = _number_to_khmer_words(minute)
|
|
102
|
+
return f"ម៉ោង{h} និង {m} នាទី {period}"
|
|
103
|
+
|
|
104
|
+
raise ValueError("mode must be 'digits' or 'words'")
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: khmer-time-format
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Format 12/24 hour time into Khmer (digits or words).
|
|
5
|
+
Author: Kon Thaina
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Konthaina/khmer-time-format-py
|
|
8
|
+
Project-URL: Repository, https://github.com/Konthaina/khmer-time-format-py
|
|
9
|
+
Keywords: khmer,time,format
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
18
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
19
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# khmer-time-format (Python)
|
|
23
|
+
|
|
24
|
+
Format 12-hour / 24-hour time (e.g. `1:22 PM`, `13:22`) into Khmer with **two options**:
|
|
25
|
+
|
|
26
|
+
1) **Khmer numerals (digits)**
|
|
27
|
+
`ម៉ោង១ និង ២២ នាទី រសៀល`
|
|
28
|
+
|
|
29
|
+
2) **Khmer words (no digits)**
|
|
30
|
+
`ម៉ោងមួយ និង ម្ភៃពីរ នាទី រសៀល`
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pip install khmer-time-format
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from khmer_time_format import format_time
|
|
42
|
+
|
|
43
|
+
print(format_time("1:22 PM", mode="digits"))
|
|
44
|
+
print(format_time("13:22", mode="words"))
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Development
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m venv .venv
|
|
51
|
+
# Windows: .venv\Scripts\activate
|
|
52
|
+
# macOS/Linux: source .venv/bin/activate
|
|
53
|
+
pip install -e ".[dev]"
|
|
54
|
+
pytest
|
|
55
|
+
ruff check .
|
|
56
|
+
mypy src
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Build & publish (PyPI)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python -m build
|
|
63
|
+
python -m twine check dist/*
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Push a version tag to publish to PyPI via GitHub Actions:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# tag value becomes package version
|
|
70
|
+
git tag v0.1.0
|
|
71
|
+
git push origin v0.1.0
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Tag pushes matching `v*` trigger `.github/workflows/publish.yml`.
|
|
75
|
+
|
|
76
|
+
With this setup, you do not need to edit the version in `pyproject.toml` for each release.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
.gitignore
|
|
2
|
+
CHANGELOG.md
|
|
3
|
+
LICENSE
|
|
4
|
+
README.md
|
|
5
|
+
pyproject.toml
|
|
6
|
+
.github/workflows/ci.yml
|
|
7
|
+
.github/workflows/publish.yml
|
|
8
|
+
src/khmer_time_format/__init__.py
|
|
9
|
+
src/khmer_time_format/formatter.py
|
|
10
|
+
src/khmer_time_format.egg-info/PKG-INFO
|
|
11
|
+
src/khmer_time_format.egg-info/SOURCES.txt
|
|
12
|
+
src/khmer_time_format.egg-info/dependency_links.txt
|
|
13
|
+
src/khmer_time_format.egg-info/requires.txt
|
|
14
|
+
src/khmer_time_format.egg-info/top_level.txt
|
|
15
|
+
tests/test_formatter.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
khmer_time_format
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from khmer_time_format import format_time
|
|
2
|
+
|
|
3
|
+
def test_digits_12h_pm():
|
|
4
|
+
assert format_time("1:22 PM", mode="digits") == "ម៉ោង១ និង ២២ នាទី រសៀល"
|
|
5
|
+
|
|
6
|
+
def test_words_12h_pm():
|
|
7
|
+
assert format_time("1:22 PM", mode="words") == "ម៉ោងមួយ និង ម្ភៃពីរ នាទី រសៀល"
|
|
8
|
+
|
|
9
|
+
def test_digits_24h():
|
|
10
|
+
assert format_time("13:22", mode="digits") == "ម៉ោង១ និង ២២ នាទី រសៀល"
|
|
11
|
+
|
|
12
|
+
def test_words_24h():
|
|
13
|
+
assert format_time("13:22", mode="words") == "ម៉ោងមួយ និង ម្ភៃពីរ នាទី រសៀល"
|