nepkit 0.2.0__tar.gz → 0.4.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.
- {nepkit-0.2.0 → nepkit-0.4.0}/PKG-INFO +119 -27
- {nepkit-0.2.0 → nepkit-0.4.0}/README.md +116 -26
- {nepkit-0.2.0 → nepkit-0.4.0}/pyproject.toml +49 -3
- nepkit-0.4.0/pyproject.toml.orig +129 -0
- nepkit-0.4.0/src/nepkit/__init__.py +78 -0
- {nepkit-0.2.0 → nepkit-0.4.0}/src/nepkit/calendar_data.py +215 -8
- nepkit-0.4.0/src/nepkit/cli.py +719 -0
- nepkit-0.4.0/src/nepkit/convert.py +315 -0
- {nepkit-0.2.0 → nepkit-0.4.0}/src/nepkit/data/DATA.md +33 -3
- nepkit-0.4.0/src/nepkit/data/__init__.py +1 -0
- nepkit-0.4.0/src/nepkit/exceptions.py +34 -0
- nepkit-0.4.0/src/nepkit/render.py +513 -0
- nepkit-0.4.0/src/nepkit/text.py +370 -0
- nepkit-0.2.0/pyproject.toml.orig +0 -81
- nepkit-0.2.0/src/nepkit/__init__.py +0 -32
- nepkit-0.2.0/src/nepkit/cli.py +0 -407
- nepkit-0.2.0/src/nepkit/convert.py +0 -52
- nepkit-0.2.0/src/nepkit/data/__init__.py +0 -0
- nepkit-0.2.0/src/nepkit/exceptions.py +0 -18
- nepkit-0.2.0/src/nepkit/render.py +0 -184
- {nepkit-0.2.0 → nepkit-0.4.0}/LICENSE +0 -0
- {nepkit-0.2.0 → nepkit-0.4.0}/src/nepkit/data/calendar.json +0 -0
- {nepkit-0.2.0 → nepkit-0.4.0}/src/nepkit/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nepkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Typed Bikram Sambat ↔ Gregorian date conversion, as a library and a CLI.
|
|
5
5
|
Keywords: nepal,bikram-sambat,nepali-date,calendar,cli
|
|
6
6
|
Author: Kritagya
|
|
@@ -17,7 +17,9 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
17
17
|
Classifier: Topic :: Utilities
|
|
18
18
|
Classifier: Typing :: Typed
|
|
19
19
|
Requires-Dist: typer>=0.15,<0.28
|
|
20
|
+
Requires-Dist: rich>=13,<16
|
|
20
21
|
Requires-Dist: pyreadline3>=3.5 ; sys_platform == 'win32'
|
|
22
|
+
Requires-Dist: tzdata>=2024.1 ; sys_platform == 'win32'
|
|
21
23
|
Requires-Python: >=3.12
|
|
22
24
|
Project-URL: Homepage, https://github.com/akakritagya/nepkit
|
|
23
25
|
Project-URL: Issues, https://github.com/akakritagya/nepkit/issues
|
|
@@ -43,8 +45,11 @@ command-line tool.
|
|
|
43
45
|
[](https://pypi.org/project/nepkit/)
|
|
44
46
|
[](https://github.com/akakritagya/nepkit/blob/main/LICENSE)
|
|
45
47
|
|
|
46
|
-
> **Status:**
|
|
47
|
-
> API may still change before
|
|
48
|
+
> **Status:** published, pre-1.0. The library and CLI both work and are
|
|
49
|
+
> tested, but the API and the CLI's output shapes may still change before
|
|
50
|
+
> 1.0. Pin a version if you script against stdout, or use `--json` instead.
|
|
51
|
+
> See [STATUS.md](https://github.com/akakritagya/nepkit/blob/main/STATUS.md)
|
|
52
|
+
> for what's changed release to release.
|
|
48
53
|
|
|
49
54
|
[**DEMO.md**](https://github.com/akakritagya/nepkit/blob/main/DEMO.md) walks
|
|
50
55
|
through every command, option, and failure mode with real captured output.
|
|
@@ -119,10 +124,11 @@ works as written.
|
|
|
119
124
|
```python
|
|
120
125
|
from datetime import date
|
|
121
126
|
|
|
122
|
-
from nepkit import BSDate, ad_to_bs, bs_to_ad
|
|
127
|
+
from nepkit import BSDate, __version__, ad_to_bs, bs_to_ad
|
|
123
128
|
|
|
124
129
|
bs_to_ad(BSDate(2081, 4, 15)) # date(2024, 7, 30)
|
|
125
130
|
ad_to_bs(date(2024, 7, 30)) # BSDate(year=2081, month=4, day=15)
|
|
131
|
+
__version__ # "0.4.0"
|
|
126
132
|
```
|
|
127
133
|
|
|
128
134
|
`BSDate` validates on construction, so if you are holding one it is a real date
|
|
@@ -142,6 +148,33 @@ BSDate(2095, 1, 1) # raises DateOutOfRangeError
|
|
|
142
148
|
`ad_to_bs` takes a `datetime.date`, so a malformed Gregorian date is impossible
|
|
143
149
|
by construction — Python's own constructor rejects it before nepkit is involved.
|
|
144
150
|
|
|
151
|
+
`BSDate` mirrors `datetime.date`'s string handling, and `parse_bs_date`/
|
|
152
|
+
`format_bs_date` (with Gregorian counterparts `parse_ad_date`/`format_ad_date`)
|
|
153
|
+
cover the human-readable forms the CLI accepts and prints — the CLI is a thin
|
|
154
|
+
layer over these, not a separate implementation:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from nepkit import BSDate, format_bs_date, parse_ad_date, parse_bs_date
|
|
158
|
+
|
|
159
|
+
bs = BSDate(2081, 4, 15)
|
|
160
|
+
str(bs) # "2081-04-15"
|
|
161
|
+
BSDate.fromisoformat("2081-04-15") # BSDate(year=2081, month=4, day=15)
|
|
162
|
+
|
|
163
|
+
# "D Month YYYY", the month matched case-insensitively against a common
|
|
164
|
+
# romanisation variant or Devnagari, not just BS_MONTH_NAMES's one spelling
|
|
165
|
+
parse_bs_date("15 Baishakh 2081") # BSDate(year=2081, month=1, day=15)
|
|
166
|
+
|
|
167
|
+
format_bs_date(bs, named=True) # "15 Shrawan 2081"
|
|
168
|
+
format_bs_date(bs, named=True, devnagari=True) # "१५ साउन २०८१"
|
|
169
|
+
|
|
170
|
+
parse_ad_date("30 Jul 2024") # date(2024, 7, 30)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`BSDate.isoformat()`'s result is not an ISO 8601 date — `datetime.date.fromisoformat`
|
|
174
|
+
will accept it and silently return a different, wrong Gregorian day. It is
|
|
175
|
+
only ever meaningful alongside something that says it is Bikram Sambat, the
|
|
176
|
+
same way nepkit's CLI always prints a `BS`/`AD` label alongside it.
|
|
177
|
+
|
|
145
178
|
### Errors
|
|
146
179
|
|
|
147
180
|
```text
|
|
@@ -165,15 +198,18 @@ add` installs into the project's `.venv` without activating it, so reach the
|
|
|
165
198
|
command with `uv run nepkit` — or activate the venv first.
|
|
166
199
|
|
|
167
200
|
```console
|
|
201
|
+
$ nepkit --version
|
|
202
|
+
nepkit 0.4.0
|
|
203
|
+
|
|
168
204
|
$ nepkit bs2ad 2081-04-15
|
|
169
|
-
2024-07-30 Tue
|
|
205
|
+
AD 30 Jul 2024 (2024-07-30) Tue
|
|
170
206
|
|
|
171
|
-
$ nepkit ad2bs 2024
|
|
172
|
-
2081-04-15 Tue
|
|
207
|
+
$ nepkit ad2bs "30 July 2024"
|
|
208
|
+
BS 15 Shrawan 2081 (2081-04-15) Tue
|
|
173
209
|
|
|
174
210
|
$ nepkit today
|
|
175
|
-
BS
|
|
176
|
-
AD
|
|
211
|
+
BS २७ साउन २०८३ १४:३२ बुध
|
|
212
|
+
AD 12 Aug 2026 14:32 Wed
|
|
177
213
|
|
|
178
214
|
$ nepkit range
|
|
179
215
|
BS 2000-01-01 .. 2090-12-30 (years 2000-2090)
|
|
@@ -184,6 +220,19 @@ Direction is always explicit, and has to be: the BS and AD year numbers overlap
|
|
|
184
220
|
from 2000 to 2034, so `2024` is a valid year in both calendars and nothing
|
|
185
221
|
could reliably guess which one you meant.
|
|
186
222
|
|
|
223
|
+
`bs2ad`/`ad2bs` accept the date either as `YYYY-MM-DD` or as `"D Month YYYY"`
|
|
224
|
+
(e.g. `"1 Baisakh 2083"`, `"1 Jan 2000"` or `"1 January 2000"`) — the month
|
|
225
|
+
name matched case-insensitively either way, so `Shrawan`, `shrawan`, and
|
|
226
|
+
`SHRAWAN` all work. The BS side also accepts common romanisation variants
|
|
227
|
+
(`Baishakh` alongside `Baisakh`, `Sawan` alongside `Shrawan`, ...) and
|
|
228
|
+
Devnagari month names (`साउन`), not just the one spelling `BS_MONTH_NAMES`
|
|
229
|
+
prints — `calbs`'s month argument does the same.
|
|
230
|
+
|
|
231
|
+
`today` defaults to `--script devnagari`, so its BS line reads Devnagari
|
|
232
|
+
without any flag; pass `--script latin` for the romanised form instead. The
|
|
233
|
+
AD line is always Latin. `bs2ad`/`ad2bs`/`range` default to `latin` and need
|
|
234
|
+
`--script devnagari` explicitly.
|
|
235
|
+
|
|
187
236
|
### Interactive
|
|
188
237
|
|
|
189
238
|
Run `nepkit` with no arguments in a terminal and it clears the screen and opens
|
|
@@ -197,17 +246,17 @@ $ nepkit
|
|
|
197
246
|
| | | || __/ | |_) || < | || |_
|
|
198
247
|
|_| |_| \___| | .__/ |_|\_\|_| \__|
|
|
199
248
|
|_|
|
|
200
|
-
nepkit v0.
|
|
201
|
-
Today BS 2083
|
|
249
|
+
nepkit v0.4.0 - Bikram Sambat (BS) <-> Gregorian (AD) date conversion
|
|
250
|
+
Today 14:32 NPT BS 27 Shrawan 2083 AD 12 Aug 2026 14:32 Wed
|
|
202
251
|
|
|
203
252
|
Type a command, 'help', 'clear', or 'quit'. Up/Down recalls history.
|
|
204
253
|
|
|
205
254
|
nepkit> today
|
|
206
|
-
BS
|
|
207
|
-
AD
|
|
255
|
+
BS २७ साउन २०८३ १४:३२ बुध
|
|
256
|
+
AD 12 Aug 2026 14:32 Wed
|
|
208
257
|
|
|
209
258
|
nepkit> bs2ad 2081-04-15
|
|
210
|
-
2024-07-30 Tue
|
|
259
|
+
AD 30 Jul 2024 (2024-07-30) Tue
|
|
211
260
|
|
|
212
261
|
nepkit> quit
|
|
213
262
|
```
|
|
@@ -256,13 +305,28 @@ Sun Mon Tue Wed Thu Fri Sat
|
|
|
256
305
|
28 29 30 31
|
|
257
306
|
```
|
|
258
307
|
|
|
308
|
+
Shown here without a box: grids are boxed and coloured only on a real
|
|
309
|
+
terminal, and plain like this when redirected — piped, or captured for this
|
|
310
|
+
README — the same convention `ls` and `git` follow. See
|
|
311
|
+
[DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#colour) for
|
|
312
|
+
what it looks like on a terminal. Force it either way with
|
|
313
|
+
`--color always|never|auto`.
|
|
314
|
+
|
|
259
315
|
Both default to the current month. A Gregorian month never lines up with a BS
|
|
260
316
|
month, so the subtitle names both ends of the span rather than pretending a
|
|
261
317
|
single corresponding month exists.
|
|
262
318
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
319
|
+
The month argument accepts a name too, case-insensitively — `calbs` matches
|
|
320
|
+
BS names (`Shrawan`/`shrawan`, a romanisation variant like `Sawan`, or a
|
|
321
|
+
Devnagari name like `साउन`), `calad` matches English names or 3-letter
|
|
322
|
+
abbreviations (`July`/`Jul`/`jul`) — alongside the numeric `1`-`12` form:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
nepkit calbs 2081 Shrawan
|
|
326
|
+
nepkit calad 2024 Jul
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Neither command takes `--script` — see [Limitations](#limitations) below.
|
|
266
330
|
|
|
267
331
|
On a terminal, today's date is picked out in bold bright cyan — the bright form
|
|
268
332
|
of the box's own border colour, so the highlight belongs to the grid containing
|
|
@@ -333,19 +397,47 @@ the standard library.
|
|
|
333
397
|
`datetime.date` rather than three integers, which removes an entire error class
|
|
334
398
|
from its contract at no cost.
|
|
335
399
|
|
|
400
|
+
**Human-text parsing and formatting are library code, not CLI code.** The CLI
|
|
401
|
+
used to own `parse_bs_date`/`format_bs_date` and friends as private helpers,
|
|
402
|
+
which meant a library caller could not parse `"1 Baisakh 2083"` into a
|
|
403
|
+
`BSDate`, or format one back into that form, at all -- only the CLI process
|
|
404
|
+
could. They moved into the library so the CLI is provably a thin layer over
|
|
405
|
+
it rather than a second implementation that has to be kept in sync by hand.
|
|
406
|
+
|
|
336
407
|
## Limitations
|
|
337
408
|
|
|
338
|
-
- **
|
|
339
|
-
|
|
409
|
+
- **Time of day works only in Nepal Standard Time (UTC+05:45).** `BSDateTime`
|
|
410
|
+
and `bs_datetime_to_ad_datetime`/`ad_datetime_to_bs_datetime` carry a
|
|
411
|
+
naive time-of-day through the date conversion; nepkit does not convert
|
|
412
|
+
between timezones. A tz-aware `datetime` is rejected outright rather than
|
|
413
|
+
silently treated as NPT — convert it yourself with `astimezone` first. In
|
|
414
|
+
the CLI, only `today` and the interactive banner show the time; there is
|
|
415
|
+
no `--time` flag on `bs2ad`/`ad2bs`.
|
|
416
|
+
- **Devnagari formatting stops at the calendar grid.** `--script devnagari`
|
|
417
|
+
covers `bs2ad`/`ad2bs`/`today`/`range` and the library
|
|
418
|
+
(`nepkit.BS_MONTH_NAMES_NE`, `nepkit.format_bs_date`/`nepkit.bs_month_name`'s
|
|
419
|
+
`devnagari` flag, and `nepkit.render`'s grid functions); `calbs` and `calad`
|
|
420
|
+
render Latin only. `today` defaults to `--script devnagari` (the
|
|
421
|
+
others default to `latin`), and its AD line is Latin regardless of
|
|
422
|
+
`--script` -- there is no Devnagari table for Gregorian month names, so the
|
|
423
|
+
option only ever touches its BS line. See
|
|
424
|
+
[DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#script).
|
|
340
425
|
- **The range is hard-bounded** at BS 2000–2090 and will not extrapolate.
|
|
341
|
-
- **Correctness rests on the data, and
|
|
342
|
-
suite verifies self-consistency exhaustively — every one
|
|
343
|
-
round-trips, and consecutive day counts produce
|
|
344
|
-
directions read the same table, so a wrong
|
|
345
|
-
and every property still passes. This was
|
|
346
|
-
the table: all properties passed while
|
|
347
|
-
|
|
348
|
-
|
|
426
|
+
- **Correctness rests on the data, and round-trip tests alone cannot prove
|
|
427
|
+
it.** The property suite verifies self-consistency exhaustively — every one
|
|
428
|
+
of the 33,238 days round-trips, and consecutive day counts produce
|
|
429
|
+
consecutive dates. But both directions read the same table, so a wrong
|
|
430
|
+
month length cancels out exactly and every property still passes. This was
|
|
431
|
+
verified by deliberately corrupting the table: all properties passed while
|
|
432
|
+
conversions were silently wrong. Two things stand behind the numbers
|
|
433
|
+
themselves instead: the independent sourcing in
|
|
434
|
+
[`src/nepkit/data/DATA.md`](https://github.com/akakritagya/nepkit/blob/main/src/nepkit/data/DATA.md),
|
|
435
|
+
and [`tests/test_oracle.py`](https://github.com/akakritagya/nepkit/blob/main/tests/test_oracle.py),
|
|
436
|
+
which checks conversions against a handful of BS↔AD dates attested by
|
|
437
|
+
sources with no connection to nepkit or to either source table. Both are a
|
|
438
|
+
sample, not a proof — the oracle pairs cover select decades, and nothing
|
|
439
|
+
past today can ever be externally attested, since the table's later years
|
|
440
|
+
(toward BS 2090) haven't happened yet.
|
|
349
441
|
|
|
350
442
|
## Data provenance
|
|
351
443
|
|
|
@@ -17,8 +17,11 @@ command-line tool.
|
|
|
17
17
|
[](https://pypi.org/project/nepkit/)
|
|
18
18
|
[](https://github.com/akakritagya/nepkit/blob/main/LICENSE)
|
|
19
19
|
|
|
20
|
-
> **Status:**
|
|
21
|
-
> API may still change before
|
|
20
|
+
> **Status:** published, pre-1.0. The library and CLI both work and are
|
|
21
|
+
> tested, but the API and the CLI's output shapes may still change before
|
|
22
|
+
> 1.0. Pin a version if you script against stdout, or use `--json` instead.
|
|
23
|
+
> See [STATUS.md](https://github.com/akakritagya/nepkit/blob/main/STATUS.md)
|
|
24
|
+
> for what's changed release to release.
|
|
22
25
|
|
|
23
26
|
[**DEMO.md**](https://github.com/akakritagya/nepkit/blob/main/DEMO.md) walks
|
|
24
27
|
through every command, option, and failure mode with real captured output.
|
|
@@ -93,10 +96,11 @@ works as written.
|
|
|
93
96
|
```python
|
|
94
97
|
from datetime import date
|
|
95
98
|
|
|
96
|
-
from nepkit import BSDate, ad_to_bs, bs_to_ad
|
|
99
|
+
from nepkit import BSDate, __version__, ad_to_bs, bs_to_ad
|
|
97
100
|
|
|
98
101
|
bs_to_ad(BSDate(2081, 4, 15)) # date(2024, 7, 30)
|
|
99
102
|
ad_to_bs(date(2024, 7, 30)) # BSDate(year=2081, month=4, day=15)
|
|
103
|
+
__version__ # "0.4.0"
|
|
100
104
|
```
|
|
101
105
|
|
|
102
106
|
`BSDate` validates on construction, so if you are holding one it is a real date
|
|
@@ -116,6 +120,33 @@ BSDate(2095, 1, 1) # raises DateOutOfRangeError
|
|
|
116
120
|
`ad_to_bs` takes a `datetime.date`, so a malformed Gregorian date is impossible
|
|
117
121
|
by construction — Python's own constructor rejects it before nepkit is involved.
|
|
118
122
|
|
|
123
|
+
`BSDate` mirrors `datetime.date`'s string handling, and `parse_bs_date`/
|
|
124
|
+
`format_bs_date` (with Gregorian counterparts `parse_ad_date`/`format_ad_date`)
|
|
125
|
+
cover the human-readable forms the CLI accepts and prints — the CLI is a thin
|
|
126
|
+
layer over these, not a separate implementation:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from nepkit import BSDate, format_bs_date, parse_ad_date, parse_bs_date
|
|
130
|
+
|
|
131
|
+
bs = BSDate(2081, 4, 15)
|
|
132
|
+
str(bs) # "2081-04-15"
|
|
133
|
+
BSDate.fromisoformat("2081-04-15") # BSDate(year=2081, month=4, day=15)
|
|
134
|
+
|
|
135
|
+
# "D Month YYYY", the month matched case-insensitively against a common
|
|
136
|
+
# romanisation variant or Devnagari, not just BS_MONTH_NAMES's one spelling
|
|
137
|
+
parse_bs_date("15 Baishakh 2081") # BSDate(year=2081, month=1, day=15)
|
|
138
|
+
|
|
139
|
+
format_bs_date(bs, named=True) # "15 Shrawan 2081"
|
|
140
|
+
format_bs_date(bs, named=True, devnagari=True) # "१५ साउन २०८१"
|
|
141
|
+
|
|
142
|
+
parse_ad_date("30 Jul 2024") # date(2024, 7, 30)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`BSDate.isoformat()`'s result is not an ISO 8601 date — `datetime.date.fromisoformat`
|
|
146
|
+
will accept it and silently return a different, wrong Gregorian day. It is
|
|
147
|
+
only ever meaningful alongside something that says it is Bikram Sambat, the
|
|
148
|
+
same way nepkit's CLI always prints a `BS`/`AD` label alongside it.
|
|
149
|
+
|
|
119
150
|
### Errors
|
|
120
151
|
|
|
121
152
|
```text
|
|
@@ -139,15 +170,18 @@ add` installs into the project's `.venv` without activating it, so reach the
|
|
|
139
170
|
command with `uv run nepkit` — or activate the venv first.
|
|
140
171
|
|
|
141
172
|
```console
|
|
173
|
+
$ nepkit --version
|
|
174
|
+
nepkit 0.4.0
|
|
175
|
+
|
|
142
176
|
$ nepkit bs2ad 2081-04-15
|
|
143
|
-
2024-07-30 Tue
|
|
177
|
+
AD 30 Jul 2024 (2024-07-30) Tue
|
|
144
178
|
|
|
145
|
-
$ nepkit ad2bs 2024
|
|
146
|
-
2081-04-15 Tue
|
|
179
|
+
$ nepkit ad2bs "30 July 2024"
|
|
180
|
+
BS 15 Shrawan 2081 (2081-04-15) Tue
|
|
147
181
|
|
|
148
182
|
$ nepkit today
|
|
149
|
-
BS
|
|
150
|
-
AD
|
|
183
|
+
BS २७ साउन २०८३ १४:३२ बुध
|
|
184
|
+
AD 12 Aug 2026 14:32 Wed
|
|
151
185
|
|
|
152
186
|
$ nepkit range
|
|
153
187
|
BS 2000-01-01 .. 2090-12-30 (years 2000-2090)
|
|
@@ -158,6 +192,19 @@ Direction is always explicit, and has to be: the BS and AD year numbers overlap
|
|
|
158
192
|
from 2000 to 2034, so `2024` is a valid year in both calendars and nothing
|
|
159
193
|
could reliably guess which one you meant.
|
|
160
194
|
|
|
195
|
+
`bs2ad`/`ad2bs` accept the date either as `YYYY-MM-DD` or as `"D Month YYYY"`
|
|
196
|
+
(e.g. `"1 Baisakh 2083"`, `"1 Jan 2000"` or `"1 January 2000"`) — the month
|
|
197
|
+
name matched case-insensitively either way, so `Shrawan`, `shrawan`, and
|
|
198
|
+
`SHRAWAN` all work. The BS side also accepts common romanisation variants
|
|
199
|
+
(`Baishakh` alongside `Baisakh`, `Sawan` alongside `Shrawan`, ...) and
|
|
200
|
+
Devnagari month names (`साउन`), not just the one spelling `BS_MONTH_NAMES`
|
|
201
|
+
prints — `calbs`'s month argument does the same.
|
|
202
|
+
|
|
203
|
+
`today` defaults to `--script devnagari`, so its BS line reads Devnagari
|
|
204
|
+
without any flag; pass `--script latin` for the romanised form instead. The
|
|
205
|
+
AD line is always Latin. `bs2ad`/`ad2bs`/`range` default to `latin` and need
|
|
206
|
+
`--script devnagari` explicitly.
|
|
207
|
+
|
|
161
208
|
### Interactive
|
|
162
209
|
|
|
163
210
|
Run `nepkit` with no arguments in a terminal and it clears the screen and opens
|
|
@@ -171,17 +218,17 @@ $ nepkit
|
|
|
171
218
|
| | | || __/ | |_) || < | || |_
|
|
172
219
|
|_| |_| \___| | .__/ |_|\_\|_| \__|
|
|
173
220
|
|_|
|
|
174
|
-
nepkit v0.
|
|
175
|
-
Today BS 2083
|
|
221
|
+
nepkit v0.4.0 - Bikram Sambat (BS) <-> Gregorian (AD) date conversion
|
|
222
|
+
Today 14:32 NPT BS 27 Shrawan 2083 AD 12 Aug 2026 14:32 Wed
|
|
176
223
|
|
|
177
224
|
Type a command, 'help', 'clear', or 'quit'. Up/Down recalls history.
|
|
178
225
|
|
|
179
226
|
nepkit> today
|
|
180
|
-
BS
|
|
181
|
-
AD
|
|
227
|
+
BS २७ साउन २०८३ १४:३२ बुध
|
|
228
|
+
AD 12 Aug 2026 14:32 Wed
|
|
182
229
|
|
|
183
230
|
nepkit> bs2ad 2081-04-15
|
|
184
|
-
2024-07-30 Tue
|
|
231
|
+
AD 30 Jul 2024 (2024-07-30) Tue
|
|
185
232
|
|
|
186
233
|
nepkit> quit
|
|
187
234
|
```
|
|
@@ -230,13 +277,28 @@ Sun Mon Tue Wed Thu Fri Sat
|
|
|
230
277
|
28 29 30 31
|
|
231
278
|
```
|
|
232
279
|
|
|
280
|
+
Shown here without a box: grids are boxed and coloured only on a real
|
|
281
|
+
terminal, and plain like this when redirected — piped, or captured for this
|
|
282
|
+
README — the same convention `ls` and `git` follow. See
|
|
283
|
+
[DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#colour) for
|
|
284
|
+
what it looks like on a terminal. Force it either way with
|
|
285
|
+
`--color always|never|auto`.
|
|
286
|
+
|
|
233
287
|
Both default to the current month. A Gregorian month never lines up with a BS
|
|
234
288
|
month, so the subtitle names both ends of the span rather than pretending a
|
|
235
289
|
single corresponding month exists.
|
|
236
290
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
291
|
+
The month argument accepts a name too, case-insensitively — `calbs` matches
|
|
292
|
+
BS names (`Shrawan`/`shrawan`, a romanisation variant like `Sawan`, or a
|
|
293
|
+
Devnagari name like `साउन`), `calad` matches English names or 3-letter
|
|
294
|
+
abbreviations (`July`/`Jul`/`jul`) — alongside the numeric `1`-`12` form:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
nepkit calbs 2081 Shrawan
|
|
298
|
+
nepkit calad 2024 Jul
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Neither command takes `--script` — see [Limitations](#limitations) below.
|
|
240
302
|
|
|
241
303
|
On a terminal, today's date is picked out in bold bright cyan — the bright form
|
|
242
304
|
of the box's own border colour, so the highlight belongs to the grid containing
|
|
@@ -307,19 +369,47 @@ the standard library.
|
|
|
307
369
|
`datetime.date` rather than three integers, which removes an entire error class
|
|
308
370
|
from its contract at no cost.
|
|
309
371
|
|
|
372
|
+
**Human-text parsing and formatting are library code, not CLI code.** The CLI
|
|
373
|
+
used to own `parse_bs_date`/`format_bs_date` and friends as private helpers,
|
|
374
|
+
which meant a library caller could not parse `"1 Baisakh 2083"` into a
|
|
375
|
+
`BSDate`, or format one back into that form, at all -- only the CLI process
|
|
376
|
+
could. They moved into the library so the CLI is provably a thin layer over
|
|
377
|
+
it rather than a second implementation that has to be kept in sync by hand.
|
|
378
|
+
|
|
310
379
|
## Limitations
|
|
311
380
|
|
|
312
|
-
- **
|
|
313
|
-
|
|
381
|
+
- **Time of day works only in Nepal Standard Time (UTC+05:45).** `BSDateTime`
|
|
382
|
+
and `bs_datetime_to_ad_datetime`/`ad_datetime_to_bs_datetime` carry a
|
|
383
|
+
naive time-of-day through the date conversion; nepkit does not convert
|
|
384
|
+
between timezones. A tz-aware `datetime` is rejected outright rather than
|
|
385
|
+
silently treated as NPT — convert it yourself with `astimezone` first. In
|
|
386
|
+
the CLI, only `today` and the interactive banner show the time; there is
|
|
387
|
+
no `--time` flag on `bs2ad`/`ad2bs`.
|
|
388
|
+
- **Devnagari formatting stops at the calendar grid.** `--script devnagari`
|
|
389
|
+
covers `bs2ad`/`ad2bs`/`today`/`range` and the library
|
|
390
|
+
(`nepkit.BS_MONTH_NAMES_NE`, `nepkit.format_bs_date`/`nepkit.bs_month_name`'s
|
|
391
|
+
`devnagari` flag, and `nepkit.render`'s grid functions); `calbs` and `calad`
|
|
392
|
+
render Latin only. `today` defaults to `--script devnagari` (the
|
|
393
|
+
others default to `latin`), and its AD line is Latin regardless of
|
|
394
|
+
`--script` -- there is no Devnagari table for Gregorian month names, so the
|
|
395
|
+
option only ever touches its BS line. See
|
|
396
|
+
[DEMO.md](https://github.com/akakritagya/nepkit/blob/main/DEMO.md#script).
|
|
314
397
|
- **The range is hard-bounded** at BS 2000–2090 and will not extrapolate.
|
|
315
|
-
- **Correctness rests on the data, and
|
|
316
|
-
suite verifies self-consistency exhaustively — every one
|
|
317
|
-
round-trips, and consecutive day counts produce
|
|
318
|
-
directions read the same table, so a wrong
|
|
319
|
-
and every property still passes. This was
|
|
320
|
-
the table: all properties passed while
|
|
321
|
-
|
|
322
|
-
|
|
398
|
+
- **Correctness rests on the data, and round-trip tests alone cannot prove
|
|
399
|
+
it.** The property suite verifies self-consistency exhaustively — every one
|
|
400
|
+
of the 33,238 days round-trips, and consecutive day counts produce
|
|
401
|
+
consecutive dates. But both directions read the same table, so a wrong
|
|
402
|
+
month length cancels out exactly and every property still passes. This was
|
|
403
|
+
verified by deliberately corrupting the table: all properties passed while
|
|
404
|
+
conversions were silently wrong. Two things stand behind the numbers
|
|
405
|
+
themselves instead: the independent sourcing in
|
|
406
|
+
[`src/nepkit/data/DATA.md`](https://github.com/akakritagya/nepkit/blob/main/src/nepkit/data/DATA.md),
|
|
407
|
+
and [`tests/test_oracle.py`](https://github.com/akakritagya/nepkit/blob/main/tests/test_oracle.py),
|
|
408
|
+
which checks conversions against a handful of BS↔AD dates attested by
|
|
409
|
+
sources with no connection to nepkit or to either source table. Both are a
|
|
410
|
+
sample, not a proof — the oracle pairs cover select decades, and nothing
|
|
411
|
+
past today can ever be externally attested, since the table's later years
|
|
412
|
+
(toward BS 2090) haven't happened yet.
|
|
323
413
|
|
|
324
414
|
## Data provenance
|
|
325
415
|
|
|
@@ -13,7 +13,9 @@ classifiers = [
|
|
|
13
13
|
]
|
|
14
14
|
dependencies = [
|
|
15
15
|
"typer>=0.15,<0.28",
|
|
16
|
+
"rich>=13,<16",
|
|
16
17
|
"pyreadline3>=3.5; sys_platform == 'win32'",
|
|
18
|
+
"tzdata>=2024.1; sys_platform == 'win32'",
|
|
17
19
|
]
|
|
18
20
|
description = "Typed Bikram Sambat ↔ Gregorian date conversion, as a library and a CLI."
|
|
19
21
|
keywords = [
|
|
@@ -28,7 +30,7 @@ license-files = ["LICENSE"]
|
|
|
28
30
|
name = "nepkit"
|
|
29
31
|
readme = "README.md"
|
|
30
32
|
requires-python = ">=3.12"
|
|
31
|
-
version = "0.
|
|
33
|
+
version = "0.4.0"
|
|
32
34
|
|
|
33
35
|
[[project.authors]]
|
|
34
36
|
name = "Kritagya"
|
|
@@ -57,9 +59,12 @@ requires = ["uv_build>=0.12.1,<0.13.0"]
|
|
|
57
59
|
[tool.ruff]
|
|
58
60
|
indent-width = 4
|
|
59
61
|
line-length = 100
|
|
62
|
+
required-version = ">=0.16,<0.17"
|
|
63
|
+
show-fixes = true
|
|
60
64
|
target-version = "py312"
|
|
61
65
|
|
|
62
66
|
[tool.ruff.lint]
|
|
67
|
+
dummy-variable-rgx = "^_.*$"
|
|
63
68
|
select = [
|
|
64
69
|
"E",
|
|
65
70
|
"F",
|
|
@@ -69,22 +74,60 @@ select = [
|
|
|
69
74
|
"SIM",
|
|
70
75
|
"ANN",
|
|
71
76
|
"RUF",
|
|
77
|
+
"D",
|
|
78
|
+
"S",
|
|
79
|
+
"PTH",
|
|
80
|
+
"C901",
|
|
81
|
+
"PLR0913",
|
|
72
82
|
]
|
|
83
|
+
unfixable = [
|
|
84
|
+
"F401",
|
|
85
|
+
"F841",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[tool.ruff.lint.isort]
|
|
89
|
+
known-first-party = ["nepkit"]
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint.mccabe]
|
|
92
|
+
max-complexity = 10
|
|
93
|
+
|
|
94
|
+
[tool.ruff.lint.pylint]
|
|
95
|
+
max-args = 7
|
|
96
|
+
|
|
97
|
+
[tool.ruff.lint.pydocstyle]
|
|
98
|
+
convention = "numpy"
|
|
99
|
+
|
|
100
|
+
[tool.ruff.lint.per-file-ignores]
|
|
101
|
+
"tests/**/*.py" = [
|
|
102
|
+
"D",
|
|
103
|
+
"S101",
|
|
104
|
+
]
|
|
105
|
+
"scripts/*.py" = ["S310"]
|
|
73
106
|
|
|
74
107
|
[tool.ruff.format]
|
|
75
108
|
docstring-code-format = true
|
|
76
109
|
line-ending = "lf"
|
|
77
110
|
|
|
78
111
|
[tool.pytest.ini_options]
|
|
79
|
-
addopts =
|
|
112
|
+
addopts = [
|
|
113
|
+
"-q",
|
|
114
|
+
"--strict-markers",
|
|
115
|
+
"--strict-config",
|
|
116
|
+
"--import-mode=importlib",
|
|
117
|
+
"--cov=nepkit",
|
|
118
|
+
"--cov-report=term-missing",
|
|
119
|
+
]
|
|
80
120
|
testpaths = ["tests"]
|
|
121
|
+
pythonpath = ["scripts"]
|
|
122
|
+
xfail_strict = true
|
|
123
|
+
filterwarnings = ["error"]
|
|
81
124
|
|
|
82
125
|
[tool.coverage.run]
|
|
83
126
|
branch = true
|
|
84
127
|
source = ["nepkit"]
|
|
85
128
|
|
|
86
129
|
[tool.coverage.report]
|
|
87
|
-
|
|
130
|
+
exclude_also = [
|
|
88
131
|
"if TYPE_CHECKING:",
|
|
89
132
|
"raise NotImplementedError",
|
|
90
133
|
]
|
|
@@ -94,7 +137,10 @@ show_missing = true
|
|
|
94
137
|
files = [
|
|
95
138
|
"src",
|
|
96
139
|
"tests",
|
|
140
|
+
"scripts",
|
|
97
141
|
]
|
|
98
142
|
python_executable = ".venv/bin/python"
|
|
99
143
|
python_version = "3.12"
|
|
100
144
|
strict = true
|
|
145
|
+
warn_unreachable = true
|
|
146
|
+
pretty = true
|