From a124d66edf3e9af07cb5641f8ee3e549f3dfa797 Mon Sep 17 00:00:00 2001 From: actualben Date: Tue, 17 Feb 2026 11:43:49 +0100 Subject: [PATCH 1/4] Add manpage and --version flag - Add man/datetimecalc.1 with full documentation of CLI usage - Add --version flag using importlib.metadata --- man/datetimecalc.1 | 130 +++++++++++++++++++++++++++++++++++ src/datetimecalc/__main__.py | 6 ++ 2 files changed, 136 insertions(+) create mode 100644 man/datetimecalc.1 diff --git a/man/datetimecalc.1 b/man/datetimecalc.1 new file mode 100644 index 0000000..04847ea --- /dev/null +++ b/man/datetimecalc.1 @@ -0,0 +1,130 @@ +.TH DATETIMECALC 1 "February 2026" "datetimecalc 0.1.0" "User Commands" +.SH NAME +datetimecalc \- parse and compute with natural language datetime expressions +.SH SYNOPSIS +.B datetimecalc +.RB [ \-h ] +.RB [ \-\-debug ] +.RB [ \-\-repr ] +.RB [ \-\-version ] +.IR expression ... +.SH DESCRIPTION +.B datetimecalc +is a command-line calculator for datetime and timedelta expressions. +It parses natural language dates, times, and durations, and performs +arithmetic operations on them. +.PP +Multiple words can be provided as separate arguments and will be joined +into a single expression. +.SH OPTIONS +.TP +.BR \-h ", " \-\-help +Show help message and exit. +.TP +.B \-\-debug +Enable debug output showing how the expression was parsed. +.TP +.B \-\-repr +Output Python repr() format instead of human-friendly formatting. +.TP +.B \-\-version +Show program version and exit. +.SH EXPRESSIONS +Expressions consist of temporal values (datetimes, timedeltas, or timezones) +combined with operators. +.SS Operators +.TP +.B + +Add a timedelta to a datetime, or add two timedeltas. +.TP +.B \- +Subtract a timedelta from a datetime, subtract two datetimes to get a +timedelta, or subtract two timedeltas. +.TP +.B @ +Convert a datetime to a different timezone. +.TP +.BR < ", " <= ", " > ", " >= ", " == ", " != +Compare two datetimes or two timedeltas. +.SS Datetime Formats +Datetimes can be specified in various formats: +.IP \(bu 2 +ISO format: 2024-01-15, 2024-01-15 14:30 +.IP \(bu 2 +Natural language: tomorrow, next Friday, yesterday at 3pm +.IP \(bu 2 +With timezone: 2024-01-15 14:30 UTC, tomorrow America/New_York +.IP \(bu 2 +With UTC offset: 2024-01-15 +05:30 +.SS Timedelta Formats +Durations support various units and formats: +.IP \(bu 2 +Full words: 1 day, 2 hours, 30 minutes +.IP \(bu 2 +Abbreviations: 1d, 2h, 30m, 15s +.IP \(bu 2 +Combined: 1 day 2 hours 30 minutes, 1d2h30m +.IP \(bu 2 +Fractional: 1.5 hours, 2.5 days +.PP +Supported units: years (y), months (mo), weeks (w), days (d), hours (h), +minutes (m), seconds (s), milliseconds (ms), microseconds (us). +.PP +.B Note: +Years and months use fixed approximations (1 year = 365 days, +1 month = 30 days). +.SS Timezone Formats +Timezones can be specified as: +.IP \(bu 2 +IANA names: America/New_York, Europe/London, Asia/Tokyo +.IP \(bu 2 +Abbreviations: UTC, EST, PST (where unambiguous) +.IP \(bu 2 +UTC offsets: +05:30, -08:00 +.SH EXAMPLES +.TP +Add one week to a date: +.B datetimecalc \(dq2024-01-01 + 1 week\(dq +.TP +Calculate days until a date: +.B datetimecalc \(dq2025-01-01 - now\(dq +.TP +Convert timezone: +.B datetimecalc \(dq2024-01-01 12:00 America/New_York @ UTC\(dq +.TP +Compare durations: +.B datetimecalc \(dq1 day == 24 hours\(dq +.TP +Natural language with multiple arguments (no quotes needed): +.B datetimecalc tomorrow at 3pm + 2 hours +.TP +Get Python repr output: +.B datetimecalc \-\-repr \(dq2025-01-01 - 2024-01-01\(dq +.SH OUTPUT +By default, datetimes are formatted in ISO 8601 format and timedeltas +are formatted in a human-readable localized form based on system locale. +.PP +With +.BR \-\-repr , +output uses Python's repr() format (e.g., datetime.timedelta(days=7)). +.SH LOCALIZATION +Timedelta output is automatically localized based on the system locale. +Supported languages: English, Spanish, Chinese, Hindi, Portuguese, +Bengali, Russian, Japanese, Vietnamese, Turkish, Marathi. +.SH EXIT STATUS +.TP +.B 0 +Success. +.TP +.B 1 +Error parsing expression or invalid input. +.SH SEE ALSO +.BR date (1), +.BR python3 (1) +.SH BUGS +Only single binary operations are supported. Chained expressions like +"a + b + c" do not work; use separate invocations or parentheses in a shell. +.SH AUTHOR +Backplane +.SH COPYRIGHT +Copyright \(co 2024-2026 Backplane. Licensed under the Apache License 2.0. diff --git a/src/datetimecalc/__main__.py b/src/datetimecalc/__main__.py index df71dc7..50ba255 100755 --- a/src/datetimecalc/__main__.py +++ b/src/datetimecalc/__main__.py @@ -13,6 +13,7 @@ import argparse import logging import sys +from importlib.metadata import version from .functions import format_temporal_object, parse_temporal_expr @@ -29,6 +30,11 @@ def main() -> int: ), formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) + argp.add_argument( + "--version", + action="version", + version=f"%(prog)s {version(__package__)}", + ) argp.add_argument( "--debug", action="store_true", From 0f67779a48bee665662cef0e8ef165a273c0338d Mon Sep 17 00:00:00 2001 From: actualben Date: Tue, 17 Feb 2026 12:18:05 +0100 Subject: [PATCH 2/4] Generate manpage from argparse with Makefile automation - Add Makefile with build, manpage, test, clean targets - Extract get_parser() function for argparse-manpage compatibility - Add man/extra-sections.man with expressions, examples, and other docs - Generate man/datetimecalc.1 using argparse-manpage - Update wheel.yml workflow to use make build - Add argparse-manpage as dev dependency --- .github/workflows/wheel.yml | 4 +- Makefile | 27 +++++++++ man/datetimecalc.1 | 54 ++++++++++-------- man/extra-sections.man | 108 +++++++++++++++++++++++++++++++++++ pyproject.toml | 1 + src/datetimecalc/__main__.py | 20 +++++-- uv.lock | 8 +++ 7 files changed, 191 insertions(+), 31 deletions(-) create mode 100644 Makefile create mode 100644 man/extra-sections.man diff --git a/.github/workflows/wheel.yml b/.github/workflows/wheel.yml index e5cc5f5..24f0c84 100644 --- a/.github/workflows/wheel.yml +++ b/.github/workflows/wheel.yml @@ -29,8 +29,8 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v5 - - name: Build wheel - run: uv build --wheel --out-dir wheelhouse + - name: Build package + run: make build OUT_DIR=wheelhouse # https://github.com/actions/upload-artifact - uses: actions/upload-artifact@v6 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6655a6a --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +.PHONY: all build clean manpage test + +OUT_DIR ?= dist + +all: build + +build: manpage + uv build --wheel --out-dir $(OUT_DIR) + +manpage: man/datetimecalc.1 + +man/datetimecalc.1: src/datetimecalc/__main__.py man/extra-sections.man + uv run argparse-manpage \ + --module datetimecalc.__main__ \ + --function get_parser \ + --project-name datetimecalc \ + --description "parse and compute with natural language datetime expressions" \ + --author "Backplane " \ + --url "https://github.com/backplane/datetimecalc" \ + --include man/extra-sections.man \ + --output man/datetimecalc.1 + +test: + uv run pytest + +clean: + rm -rf dist/ build/ *.egg-info diff --git a/man/datetimecalc.1 b/man/datetimecalc.1 index 04847ea..990fe6e 100644 --- a/man/datetimecalc.1 +++ b/man/datetimecalc.1 @@ -1,37 +1,32 @@ -.TH DATETIMECALC 1 "February 2026" "datetimecalc 0.1.0" "User Commands" +.TH DATETIMECALC "1" "2026\-02\-17" "datetimecalc" "Generated Python Manual" .SH NAME datetimecalc \- parse and compute with natural language datetime expressions .SH SYNOPSIS .B datetimecalc -.RB [ \-h ] -.RB [ \-\-debug ] -.RB [ \-\-repr ] -.RB [ \-\-version ] -.IR expression ... +[-h] [--version] [--debug] [--repr] expr [expr ...] .SH DESCRIPTION -.B datetimecalc -is a command-line calculator for datetime and timedelta expressions. -It parses natural language dates, times, and durations, and performs -arithmetic operations on them. -.PP -Multiple words can be provided as separate arguments and will be joined -into a single expression. -.SH OPTIONS +program which parses natural language datetime and timedelta expressions + .TP -.BR \-h ", " \-\-help -Show help message and exit. +\fBexpr\fR +a natural language date and time operation expression + +.SH OPTIONS .TP -.B \-\-debug -Enable debug output showing how the expression was parsed. +\fB\-\-version\fR +show program's version number and exit + .TP -.B \-\-repr -Output Python repr() format instead of human-friendly formatting. +\fB\-\-debug\fR +enable debug output + .TP -.B \-\-version -Show program version and exit. +\fB\-\-repr\fR +use the python repr function on the object instead of human\-friendly formatting .SH EXPRESSIONS Expressions consist of temporal values (datetimes, timedeltas, or timezones) combined with operators. + .SS Operators .TP .B + @@ -46,6 +41,7 @@ Convert a datetime to a different timezone. .TP .BR < ", " <= ", " > ", " >= ", " == ", " != Compare two datetimes or two timedeltas. + .SS Datetime Formats Datetimes can be specified in various formats: .IP \(bu 2 @@ -56,6 +52,7 @@ Natural language: tomorrow, next Friday, yesterday at 3pm With timezone: 2024-01-15 14:30 UTC, tomorrow America/New_York .IP \(bu 2 With UTC offset: 2024-01-15 +05:30 + .SS Timedelta Formats Durations support various units and formats: .IP \(bu 2 @@ -73,6 +70,7 @@ minutes (m), seconds (s), milliseconds (ms), microseconds (us). .B Note: Years and months use fixed approximations (1 year = 365 days, 1 month = 30 days). + .SS Timezone Formats Timezones can be specified as: .IP \(bu 2 @@ -124,7 +122,15 @@ Error parsing expression or invalid input. .SH BUGS Only single binary operations are supported. Chained expressions like "a + b + c" do not work; use separate invocations or parentheses in a shell. -.SH AUTHOR -Backplane .SH COPYRIGHT Copyright \(co 2024-2026 Backplane. Licensed under the Apache License 2.0. + +.SH AUTHOR +.nf +Backplane +.fi + +.SH DISTRIBUTION +The latest version of datetimecalc may be downloaded from +.UR https://github.com/backplane/datetimecalc +.UE diff --git a/man/extra-sections.man b/man/extra-sections.man new file mode 100644 index 0000000..2f5c2af --- /dev/null +++ b/man/extra-sections.man @@ -0,0 +1,108 @@ +[EXPRESSIONS] +Expressions consist of temporal values (datetimes, timedeltas, or timezones) +combined with operators. + +.SS Operators +.TP +.B + +Add a timedelta to a datetime, or add two timedeltas. +.TP +.B \- +Subtract a timedelta from a datetime, subtract two datetimes to get a +timedelta, or subtract two timedeltas. +.TP +.B @ +Convert a datetime to a different timezone. +.TP +.BR < ", " <= ", " > ", " >= ", " == ", " != +Compare two datetimes or two timedeltas. + +.SS Datetime Formats +Datetimes can be specified in various formats: +.IP \(bu 2 +ISO format: 2024-01-15, 2024-01-15 14:30 +.IP \(bu 2 +Natural language: tomorrow, next Friday, yesterday at 3pm +.IP \(bu 2 +With timezone: 2024-01-15 14:30 UTC, tomorrow America/New_York +.IP \(bu 2 +With UTC offset: 2024-01-15 +05:30 + +.SS Timedelta Formats +Durations support various units and formats: +.IP \(bu 2 +Full words: 1 day, 2 hours, 30 minutes +.IP \(bu 2 +Abbreviations: 1d, 2h, 30m, 15s +.IP \(bu 2 +Combined: 1 day 2 hours 30 minutes, 1d2h30m +.IP \(bu 2 +Fractional: 1.5 hours, 2.5 days +.PP +Supported units: years (y), months (mo), weeks (w), days (d), hours (h), +minutes (m), seconds (s), milliseconds (ms), microseconds (us). +.PP +.B Note: +Years and months use fixed approximations (1 year = 365 days, +1 month = 30 days). + +.SS Timezone Formats +Timezones can be specified as: +.IP \(bu 2 +IANA names: America/New_York, Europe/London, Asia/Tokyo +.IP \(bu 2 +Abbreviations: UTC, EST, PST (where unambiguous) +.IP \(bu 2 +UTC offsets: +05:30, -08:00 + +[EXAMPLES] +.TP +Add one week to a date: +.B datetimecalc \(dq2024-01-01 + 1 week\(dq +.TP +Calculate days until a date: +.B datetimecalc \(dq2025-01-01 - now\(dq +.TP +Convert timezone: +.B datetimecalc \(dq2024-01-01 12:00 America/New_York @ UTC\(dq +.TP +Compare durations: +.B datetimecalc \(dq1 day == 24 hours\(dq +.TP +Natural language with multiple arguments (no quotes needed): +.B datetimecalc tomorrow at 3pm + 2 hours +.TP +Get Python repr output: +.B datetimecalc \-\-repr \(dq2025-01-01 - 2024-01-01\(dq + +[OUTPUT] +By default, datetimes are formatted in ISO 8601 format and timedeltas +are formatted in a human-readable localized form based on system locale. +.PP +With +.BR \-\-repr , +output uses Python's repr() format (e.g., datetime.timedelta(days=7)). + +[LOCALIZATION] +Timedelta output is automatically localized based on the system locale. +Supported languages: English, Spanish, Chinese, Hindi, Portuguese, +Bengali, Russian, Japanese, Vietnamese, Turkish, Marathi. + +[EXIT STATUS] +.TP +.B 0 +Success. +.TP +.B 1 +Error parsing expression or invalid input. + +[SEE ALSO] +.BR date (1), +.BR python3 (1) + +[BUGS] +Only single binary operations are supported. Chained expressions like +"a + b + c" do not work; use separate invocations or parentheses in a shell. + +[COPYRIGHT] +Copyright \(co 2024-2026 Backplane. Licensed under the Apache License 2.0. diff --git a/pyproject.toml b/pyproject.toml index d0cb2f5..070edbf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,4 +46,5 @@ build-backend = "uv_build" dev = [ "pytest>=8.4.2", "pdoc3>=0.11.1", + "argparse-manpage>=4.7", ] diff --git a/src/datetimecalc/__main__.py b/src/datetimecalc/__main__.py index 50ba255..bea7f5b 100755 --- a/src/datetimecalc/__main__.py +++ b/src/datetimecalc/__main__.py @@ -18,13 +18,14 @@ from .functions import format_temporal_object, parse_temporal_expr -def main() -> int: +def get_parser() -> argparse.ArgumentParser: """ - entrypoint for direct execution; returns an integer suitable for use with - sys.exit + Build and return the argument parser for datetimecalc. + + This function is also used by argparse-manpage to generate the manpage. """ argp = argparse.ArgumentParser( - prog=__package__, + prog="datetimecalc", description=( "program which parses natural language datetime and timedelta expressions" ), @@ -33,7 +34,7 @@ def main() -> int: argp.add_argument( "--version", action="version", - version=f"%(prog)s {version(__package__)}", + version=f"%(prog)s {version('datetimecalc')}", ) argp.add_argument( "--debug", @@ -51,6 +52,15 @@ def main() -> int: nargs="+", help="a natural language date and time operation expression", ) + return argp + + +def main() -> int: + """ + entrypoint for direct execution; returns an integer suitable for use with + sys.exit + """ + argp = get_parser() args = argp.parse_args() logging.basicConfig( diff --git a/uv.lock b/uv.lock index 6db0da6..5f3da56 100644 --- a/uv.lock +++ b/uv.lock @@ -2,6 +2,12 @@ version = 1 revision = 3 requires-python = ">=3.12" +[[package]] +name = "argparse-manpage" +version = "4.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/6e/2907db04890c23728eecfcb04c37f66cba24d7903fe0ff6b8dc84d943ca5/argparse_manpage-4.7.tar.gz", hash = "sha256:1deab76b212ac8753cbb67b9d2d2bc0949bbc338bb1cc3547f0890cb34108b32", size = 58871, upload-time = "2025-08-15T10:24:20.601Z" } + [[package]] name = "colorama" version = "0.4.6" @@ -21,6 +27,7 @@ dependencies = [ [package.dev-dependencies] dev = [ + { name = "argparse-manpage" }, { name = "pdoc3" }, { name = "pytest" }, ] @@ -30,6 +37,7 @@ requires-dist = [{ name = "parsedatetime", specifier = ">=2.6" }] [package.metadata.requires-dev] dev = [ + { name = "argparse-manpage", specifier = ">=4.7" }, { name = "pdoc3", specifier = ">=0.11.1" }, { name = "pytest", specifier = ">=8.4.2" }, ] From 8f5620139b938de022c17f596e223b207830d982 Mon Sep 17 00:00:00 2001 From: actualben Date: Tue, 17 Feb 2026 12:31:36 +0100 Subject: [PATCH 3/4] Improve Makefile structure and naming - Rename 'build' target to 'wheel' for clarity - Add progress echo for each target - Reorder dependencies so $< works for --include - Place .PHONY declarations adjacent to targets - Quote automatic variables - Update workflow to use 'make wheel' --- .github/workflows/wheel.yml | 2 +- Makefile | 35 +++++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/.github/workflows/wheel.yml b/.github/workflows/wheel.yml index 24f0c84..bd5c2ff 100644 --- a/.github/workflows/wheel.yml +++ b/.github/workflows/wheel.yml @@ -30,7 +30,7 @@ jobs: uses: astral-sh/setup-uv@v5 - name: Build package - run: make build OUT_DIR=wheelhouse + run: make wheel OUT_DIR=wheelhouse # https://github.com/actions/upload-artifact - uses: actions/upload-artifact@v6 diff --git a/Makefile b/Makefile index 6655a6a..6f156ae 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,28 @@ -.PHONY: all build clean manpage test - OUT_DIR ?= dist -all: build +.PHONY: all +all: wheel + +.PHONY: test +test: + @echo "==> $@" + uv run pytest + +.PHONY: clean +clean: + @echo "==> $@" + rm -rf dist/ build/ *.egg-info man/datetimecalc.1 -build: manpage +.PHONY: wheel +wheel: manpages + @echo "==> $@" uv build --wheel --out-dir $(OUT_DIR) -manpage: man/datetimecalc.1 +.PHONY: manpages +manpages: man/datetimecalc.1 -man/datetimecalc.1: src/datetimecalc/__main__.py man/extra-sections.man +man/datetimecalc.1: man/extra-sections.man src/datetimecalc/__main__.py + @echo "==> $@" uv run argparse-manpage \ --module datetimecalc.__main__ \ --function get_parser \ @@ -17,11 +30,5 @@ man/datetimecalc.1: src/datetimecalc/__main__.py man/extra-sections.man --description "parse and compute with natural language datetime expressions" \ --author "Backplane " \ --url "https://github.com/backplane/datetimecalc" \ - --include man/extra-sections.man \ - --output man/datetimecalc.1 - -test: - uv run pytest - -clean: - rm -rf dist/ build/ *.egg-info + --include "$<" \ + --output "$@" From 9ca38c62fc8538c814461a49ec90b9437f3727e6 Mon Sep 17 00:00:00 2001 From: actualben Date: Tue, 17 Feb 2026 12:35:12 +0100 Subject: [PATCH 4/4] Exclude generated manpage from version control The manpage is generated from argparse via 'make manpages'. --- .gitignore | 1 + man/datetimecalc.1 | 136 --------------------------------------------- 2 files changed, 1 insertion(+), 136 deletions(-) delete mode 100644 man/datetimecalc.1 diff --git a/.gitignore b/.gitignore index e067d04..65dd86e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,6 @@ build cruft dist docs +man/*.1 src/*.egg-info venv diff --git a/man/datetimecalc.1 b/man/datetimecalc.1 deleted file mode 100644 index 990fe6e..0000000 --- a/man/datetimecalc.1 +++ /dev/null @@ -1,136 +0,0 @@ -.TH DATETIMECALC "1" "2026\-02\-17" "datetimecalc" "Generated Python Manual" -.SH NAME -datetimecalc \- parse and compute with natural language datetime expressions -.SH SYNOPSIS -.B datetimecalc -[-h] [--version] [--debug] [--repr] expr [expr ...] -.SH DESCRIPTION -program which parses natural language datetime and timedelta expressions - -.TP -\fBexpr\fR -a natural language date and time operation expression - -.SH OPTIONS -.TP -\fB\-\-version\fR -show program's version number and exit - -.TP -\fB\-\-debug\fR -enable debug output - -.TP -\fB\-\-repr\fR -use the python repr function on the object instead of human\-friendly formatting -.SH EXPRESSIONS -Expressions consist of temporal values (datetimes, timedeltas, or timezones) -combined with operators. - -.SS Operators -.TP -.B + -Add a timedelta to a datetime, or add two timedeltas. -.TP -.B \- -Subtract a timedelta from a datetime, subtract two datetimes to get a -timedelta, or subtract two timedeltas. -.TP -.B @ -Convert a datetime to a different timezone. -.TP -.BR < ", " <= ", " > ", " >= ", " == ", " != -Compare two datetimes or two timedeltas. - -.SS Datetime Formats -Datetimes can be specified in various formats: -.IP \(bu 2 -ISO format: 2024-01-15, 2024-01-15 14:30 -.IP \(bu 2 -Natural language: tomorrow, next Friday, yesterday at 3pm -.IP \(bu 2 -With timezone: 2024-01-15 14:30 UTC, tomorrow America/New_York -.IP \(bu 2 -With UTC offset: 2024-01-15 +05:30 - -.SS Timedelta Formats -Durations support various units and formats: -.IP \(bu 2 -Full words: 1 day, 2 hours, 30 minutes -.IP \(bu 2 -Abbreviations: 1d, 2h, 30m, 15s -.IP \(bu 2 -Combined: 1 day 2 hours 30 minutes, 1d2h30m -.IP \(bu 2 -Fractional: 1.5 hours, 2.5 days -.PP -Supported units: years (y), months (mo), weeks (w), days (d), hours (h), -minutes (m), seconds (s), milliseconds (ms), microseconds (us). -.PP -.B Note: -Years and months use fixed approximations (1 year = 365 days, -1 month = 30 days). - -.SS Timezone Formats -Timezones can be specified as: -.IP \(bu 2 -IANA names: America/New_York, Europe/London, Asia/Tokyo -.IP \(bu 2 -Abbreviations: UTC, EST, PST (where unambiguous) -.IP \(bu 2 -UTC offsets: +05:30, -08:00 -.SH EXAMPLES -.TP -Add one week to a date: -.B datetimecalc \(dq2024-01-01 + 1 week\(dq -.TP -Calculate days until a date: -.B datetimecalc \(dq2025-01-01 - now\(dq -.TP -Convert timezone: -.B datetimecalc \(dq2024-01-01 12:00 America/New_York @ UTC\(dq -.TP -Compare durations: -.B datetimecalc \(dq1 day == 24 hours\(dq -.TP -Natural language with multiple arguments (no quotes needed): -.B datetimecalc tomorrow at 3pm + 2 hours -.TP -Get Python repr output: -.B datetimecalc \-\-repr \(dq2025-01-01 - 2024-01-01\(dq -.SH OUTPUT -By default, datetimes are formatted in ISO 8601 format and timedeltas -are formatted in a human-readable localized form based on system locale. -.PP -With -.BR \-\-repr , -output uses Python's repr() format (e.g., datetime.timedelta(days=7)). -.SH LOCALIZATION -Timedelta output is automatically localized based on the system locale. -Supported languages: English, Spanish, Chinese, Hindi, Portuguese, -Bengali, Russian, Japanese, Vietnamese, Turkish, Marathi. -.SH EXIT STATUS -.TP -.B 0 -Success. -.TP -.B 1 -Error parsing expression or invalid input. -.SH SEE ALSO -.BR date (1), -.BR python3 (1) -.SH BUGS -Only single binary operations are supported. Chained expressions like -"a + b + c" do not work; use separate invocations or parentheses in a shell. -.SH COPYRIGHT -Copyright \(co 2024-2026 Backplane. Licensed under the Apache License 2.0. - -.SH AUTHOR -.nf -Backplane -.fi - -.SH DISTRIBUTION -The latest version of datetimecalc may be downloaded from -.UR https://github.com/backplane/datetimecalc -.UE