diff --git a/kosmorro/__main__.py b/kosmorro/__main__.py
index 177fdbd..ccc24b8 100644
--- a/kosmorro/__main__.py
+++ b/kosmorro/__main__.py
@@ -17,14 +17,18 @@
# along with this program. If not, see .
import argparse
+import datetime
import sys
import os.path
+import pytz
from babel.dates import format_date
from kosmorrolib import Position, get_ephemerides, get_events, get_moon_phase
from kosmorrolib.exceptions import OutOfRangeDateError
from datetime import date
+from pytz import timezone
+
from . import dumper, environment, debug
from .date import parse_date
from .geolocation import get_position
@@ -34,6 +38,7 @@ from .utils import (
colored,
set_colors_activated,
print_stderr,
+ get_timezone,
)
from .exceptions import (
InvalidOutputFormatError,
@@ -88,12 +93,31 @@ def run():
)
)
- timezone = args.timezone
+ timezone = 0
- if timezone is None and env_vars.timezone is not None:
- timezone = int(env_vars.timezone)
- elif timezone is None:
- timezone = 0
+ try:
+ if args.timezone is not None:
+ timezone = get_timezone(args.timezone)
+ elif env_vars.tz is not None:
+ timezone = get_timezone(env_vars.tz)
+ elif env_vars.timezone is not None:
+ print_stderr(
+ colored(
+ _(
+ "Environment variable KOSMORRO_TIMEZONE is deprecated. Use TZ instead, which is more standard."
+ ),
+ "yellow",
+ )
+ )
+ timezone = get_timezone(env_vars.timezone)
+ except pytz.UnknownTimeZoneError as error:
+ print_stderr(
+ colored(
+ _("Unknown timezone: {timezone}").format(timezone=error.args[0]),
+ color="red",
+ )
+ )
+ return -1
try:
use_colors = not environment.NO_COLOR and args.colors
@@ -290,11 +314,12 @@ def get_args(output_formats: [str]):
parser.add_argument(
"--timezone",
"-t",
- type=int,
+ type=str,
default=None,
help=_(
- "The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). "
- "Can also be set in the KOSMORRO_TIMEZONE environment variable."
+ "The timezone to use to display the hours. It can be either a number (e.g. 1 for UTC+1) or a timezone name (e.g. Europe/Paris). "
+ "See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones to find your timezone. "
+ "Can also be set in the TZ environment variable."
),
)
parser.add_argument(
diff --git a/kosmorro/environment.py b/kosmorro/environment.py
index be3dac2..309213f 100644
--- a/kosmorro/environment.py
+++ b/kosmorro/environment.py
@@ -44,6 +44,8 @@ class Environment:
def get_env_vars() -> Environment:
environment = Environment()
+ environment.tz = os.getenv("TZ")
+
for var in os.environ:
if not re.search("^KOSMORRO_", var):
continue
diff --git a/kosmorro/locales/messages.pot b/kosmorro/locales/messages.pot
index c211d64..22df864 100644
--- a/kosmorro/locales/messages.pot
+++ b/kosmorro/locales/messages.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2025-04-21 15:35+0200\n"
+"POT-Creation-Date: 2025-09-22 17:24+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,89 +17,102 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.17.0\n"
-#: kosmorro/__main__.py:84
+#: kosmorro/__main__.py:89
msgid ""
"Output file will not contain the ephemerides, because you didn't provide "
"the observation coordinates."
msgstr ""
-#: kosmorro/__main__.py:135
+#: kosmorro/__main__.py:107
+msgid ""
+"Environment variable KOSMORRO_TIMEZONE is deprecated. Use TZ instead, "
+"which is more standard."
+msgstr ""
+
+#: kosmorro/__main__.py:116
+#, python-brace-format
+msgid "Unknown timezone: {timezone}"
+msgstr ""
+
+#: kosmorro/__main__.py:159
#, python-brace-format
msgid "The file could not be saved in \"{path}\": {error}"
msgstr ""
-#: kosmorro/__main__.py:149
+#: kosmorro/__main__.py:173
msgid "Please provide a file path to export in this format (--output)."
msgstr ""
-#: kosmorro/__main__.py:181
+#: kosmorro/__main__.py:205
#, python-brace-format
msgid "Moon phase can only be computed between {min_date} and {max_date}"
msgstr ""
-#: kosmorro/__main__.py:228
+#: kosmorro/__main__.py:252
#, python-brace-format
msgid "Running on Python {python_version} with Kosmorrolib v{kosmorrolib_version}"
msgstr ""
-#: kosmorro/__main__.py:241
+#: kosmorro/__main__.py:265
msgid ""
"Compute the ephemerides and the events for a given date and a given "
"position on Earth."
msgstr ""
-#: kosmorro/__main__.py:244
+#: kosmorro/__main__.py:268
msgid ""
"By default, only the events will be computed for today.\n"
"To compute also the ephemerides, latitude and longitude arguments are "
"needed."
msgstr ""
-#: kosmorro/__main__.py:256
+#: kosmorro/__main__.py:280
msgid "Show the program version"
msgstr ""
-#: kosmorro/__main__.py:265
+#: kosmorro/__main__.py:289
msgid ""
"The format to output the information to. If not provided, the output "
"format will be inferred from the file extension of the output file."
msgstr ""
-#: kosmorro/__main__.py:275
+#: kosmorro/__main__.py:299
#, python-brace-format
msgid ""
"The observer's position on Earth, in the \"{latitude},{longitude}\" "
"format. Can also be set in the KOSMORRO_POSITION environment variable."
msgstr ""
-#: kosmorro/__main__.py:285
+#: kosmorro/__main__.py:309
msgid ""
"The date for which the ephemerides must be calculated. Can be in the "
"YYYY-MM-DD format or an interval in the \"[+-]YyMmDd\" format (with Y, M,"
" and D numbers). Defaults to current date."
msgstr ""
-#: kosmorro/__main__.py:296
+#: kosmorro/__main__.py:320
msgid ""
-"The timezone to display the hours in (e.g. 2 for UTC+2 or -3 for UTC-3). "
-"Can also be set in the KOSMORRO_TIMEZONE environment variable."
+"The timezone to use to display the hours. It can be either a number (e.g."
+" 1 for UTC+1) or a timezone name (e.g. Europe/Paris). See "
+"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones to find your"
+" timezone. Can also be set in the TZ environment variable."
msgstr ""
-#: kosmorro/__main__.py:304
+#: kosmorro/__main__.py:329
msgid "Disable the colors in the console."
msgstr ""
-#: kosmorro/__main__.py:312
+#: kosmorro/__main__.py:337
msgid "A file to export the output to. If not given, the standard output is used."
msgstr ""
-#: kosmorro/__main__.py:320
+#: kosmorro/__main__.py:345
msgid ""
"Do not generate a graph to represent the rise and set times in the LaTeX "
"file."
msgstr ""
-#: kosmorro/__main__.py:327
+#: kosmorro/__main__.py:352
msgid "Show debugging messages"
msgstr ""
diff --git a/kosmorro/utils.py b/kosmorro/utils.py
index bd68ae9..892d9c4 100644
--- a/kosmorro/utils.py
+++ b/kosmorro/utils.py
@@ -1,5 +1,7 @@
#!/usr/bin/env python3
+from datetime import datetime
+import pytz
from termcolor import colored as do_color
from sys import stderr
@@ -27,3 +29,12 @@ def colored(text, color=None, on_color=None, attrs=None):
def print_stderr(*values: object):
print(*values, file=stderr)
+
+
+def get_timezone(value: int | str) -> float:
+ try:
+ timezone = float(value)
+ except ValueError:
+ timezone = pytz.timezone(value).utcoffset(datetime.now()).total_seconds() / 3600
+
+ return timezone
diff --git a/manpage/kosmorro.1.md b/manpage/kosmorro.1.md
index f44bb4b..3f25024 100644
--- a/manpage/kosmorro.1.md
+++ b/manpage/kosmorro.1.md
@@ -23,7 +23,7 @@
The date for which the ephemerides must be computed, either in the YYYY-MM-DD format or as an interval in the "[+-]YyMmDd" format (with Y, M, and D numbers); defaults to the current date
`--timezone=`_TIMEZONE_, `-t` _TIMEZONE_
- the timezone to display the hours in; e.g. 2 for UTC+2 or -3 for UTC-3
+ the timezone to use to display the hours; it can be either a number (e.g. 1 for UTC+1) or a timezone name (e.g. Europe/Paris)
`--no-colors`
disable the colors in the console
diff --git a/poetry.lock b/poetry.lock
index 6903d0c..6ceb6e5 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -391,6 +391,18 @@ files = [
[package.dependencies]
six = ">=1.5"
+[[package]]
+name = "pytz"
+version = "2025.2"
+description = "World timezone definitions, modern and historical"
+optional = false
+python-versions = "*"
+groups = ["main"]
+files = [
+ {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"},
+ {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"},
+]
+
[[package]]
name = "sgp4"
version = "2.25"
@@ -529,4 +541,4 @@ tests = ["pytest", "pytest-cov"]
[metadata]
lock-version = "2.1"
python-versions = "^3.12"
-content-hash = "edfb347df82f9895ce51f3af9005b1d924129c24aa7e38b5e2f7bd858e33ec25"
+content-hash = "12bf9cdda9cfaf9616bf3d899450e105991f788267601a41a79fed1b5cbd73a9"
diff --git a/pyproject.toml b/pyproject.toml
index 07c9b58..9ccdc97 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -22,6 +22,7 @@ kosmorrolib = "^1.0"
python-dateutil = "^2.8"
Babel = "^2.9"
openlocationcode = "^1.0"
+pytz = "^2025.2"
[tool.poetry.group.dev.dependencies]
black = "^24.4"
diff --git a/tests/general.py b/tests/general.py
index 290699d..d12ace7 100644
--- a/tests/general.py
+++ b/tests/general.py
@@ -62,9 +62,11 @@ options:
"[+-]YyMmDd" format (with Y, M, and D numbers).
Defaults to current date.
--timezone TIMEZONE, -t TIMEZONE
- The timezone to display the hours in (e.g. 2 for UTC+2
- or -3 for UTC-3). Can also be set in the
- KOSMORRO_TIMEZONE environment variable.
+ The timezone to use to display the hours. It can be
+ either a number (e.g. 1 for UTC+1) or a timezone name
+ (e.g. Europe/Paris). See https://en.wikipedia.org/wiki
+ /List_of_tz_database_time_zones to find your timezone.
+ Can also be set in the TZ environment variable.
--no-colors Disable the colors in the console.
--output OUTPUT, -o OUTPUT
A file to export the output to. If not given, the
@@ -103,9 +105,11 @@ options:
"[+-]YyMmDd" format (with Y, M, and D numbers).
Defaults to current date.
--timezone, -t TIMEZONE
- The timezone to display the hours in (e.g. 2 for UTC+2
- or -3 for UTC-3). Can also be set in the
- KOSMORRO_TIMEZONE environment variable.
+ The timezone to use to display the hours. It can be
+ either a number (e.g. 1 for UTC+1) or a timezone name
+ (e.g. Europe/Paris). See https://en.wikipedia.org/wiki
+ /List_of_tz_database_time_zones to find your timezone.
+ Can also be set in the TZ environment variable.
--no-colors Disable the colors in the console.
--output, -o OUTPUT A file to export the output to. If not given, the
standard output is used.
diff --git a/tests/timezone.py b/tests/timezone.py
index a1f6802..6226f48 100644
--- a/tests/timezone.py
+++ b/tests/timezone.py
@@ -6,68 +6,88 @@ from .utils import (
)
-def check_command_return_t_plus_one(result):
+def test_timezone_with_command_line_arg():
+ result = execute(KOSMORRO + ["--timezone=1", "-d2020-01-27"])
assert result.successful
- assert (
- result.stdout
- == """Monday, January 27, 2020
+ assert "Note: All the hours are given in the UTC+1.0 timezone." in result.stdout
-New Moon
-First Quarter on Sunday, February 2, 2020 at 2:41 AM
+ result = execute(KOSMORRO + ["--timezone=Europe/Paris", "-d2020-01-27"])
+ assert result.successful
+ assert "Note: All the hours are given in the UTC+1.0 timezone." not in result.stdout
-Expected events:
-9:00 PM Venus and Neptune are in conjunction
+ result = execute(KOSMORRO + ["--timezone=-5", "-d2020-01-27"])
+ assert result.successful
+ assert "Note: All the hours are given in the UTC-5.0 timezone." in result.stdout
-Note: All the hours are given in the UTC+1 timezone.
-"""
- )
+ result = execute(KOSMORRO + ["--timezone=America/Chicago", "-d2020-01-27"])
+ assert result.successful
+ assert "Note: All the hours are given in the UTC-5.0 timezone." in result.stdout
-def check_command_return_t_minus_one(result):
+def test_timezone_with_env_var():
+ result = execute(KOSMORRO + ["-d2020-01-27"], environment={"TZ": "1"})
assert result.successful
- assert (
- result.stdout
- == """Monday, January 27, 2020
+ assert "Note: All the hours are given in the UTC+1.0 timezone." in result.stdout
-New Moon
-First Quarter on Sunday, February 2, 2020 at 12:41 AM
+ result = execute(KOSMORRO + ["-d2020-01-27"], environment={"TZ": "Europe/Paris"})
+ assert result.successful
+ assert "Note: All the hours are given in the UTC+1.0 timezone." not in result.stdout
+
+ result = execute(KOSMORRO + ["-d2020-01-27"], environment={"TZ": "-5"})
+ assert result.successful
+ assert "Note: All the hours are given in the UTC-5.0 timezone." in result.stdout
+
+ result = execute(KOSMORRO + ["-d2020-01-27"], environment={"TZ": "America/Chicago"})
+ assert result.successful
+ assert "Note: All the hours are given in the UTC-5.0 timezone." in result.stdout
-Expected events:
-7:00 PM Venus and Neptune are in conjunction
-Note: All the hours are given in the UTC-1 timezone.
-"""
+def test_timezone_with_env_var_and_command_line_arg():
+ result = execute(
+ KOSMORRO + ["--timezone=3", "-d2020-01-27"], environment={"TZ": "Europe/Paris"}
)
+ assert result.successful
+ assert "Note: All the hours are given in the UTC+3.0 timezone." in result.stdout
-def test_timezone():
- check_command_return_t_plus_one(
- execute(KOSMORRO + ["--timezone=1", "-d2020-01-27"])
+def test_timezone_with_deprecated_env_var():
+ result = execute(
+ KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "1"}
)
- check_command_return_t_minus_one(
- execute(KOSMORRO + ["--timezone=-1", "-d2020-01-27"])
+ assert result.successful
+ assert (
+ "Environment variable KOSMORRO_TIMEZONE is deprecated. Use TZ instead, which is more standard."
+ in result.stderr
)
+ assert "Note: All the hours are given in the UTC+1.0 timezone." in result.stdout
-
-def test_timezone_with_env_var():
- check_command_return_t_plus_one(
- execute(KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "1"})
+ result = execute(
+ KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "Europe/Paris"}
)
- check_command_return_t_minus_one(
- execute(KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "-1"})
+ assert result.successful
+ assert (
+ "Environment variable KOSMORRO_TIMEZONE is deprecated. Use TZ instead, which is more standard."
+ in result.stderr
)
+ assert "Note: All the hours are given in the UTC+1.0 timezone." not in result.stdout
- # If both environment variable and argument are set, use argument:
+ result = execute(
+ KOSMORRO + ["-d2020-01-27"], environment={"KOSMORRO_TIMEZONE": "-5"}
+ )
+ assert result.successful
+ assert (
+ "Environment variable KOSMORRO_TIMEZONE is deprecated. Use TZ instead, which is more standard."
+ in result.stderr
+ )
+ assert "Note: All the hours are given in the UTC-5.0 timezone." in result.stdout
- check_command_return_t_plus_one(
- execute(
- KOSMORRO + ["--timezone=1", "-d2020-01-27"],
- environment={"KOSMORRO_TIMEZONE": "-1"},
- )
+ result = execute(
+ KOSMORRO + ["-d2020-01-27"],
+ environment={"KOSMORRO_TIMEZONE": "America/Chicago"},
)
- check_command_return_t_minus_one(
- execute(
- KOSMORRO + ["--timezone=-1", "-d2020-01-27"],
- environment={"KOSMORRO_TIMEZONE": "1"},
- )
+ assert result.successful
+ assert (
+ "Environment variable KOSMORRO_TIMEZONE is deprecated. Use TZ instead, which is more standard."
+ in result.stderr
)
+ assert "Note: All the hours are given in the UTC-5.0 timezone." in result.stdout