Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/source/commands/dt/dt.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.. hckr documentation master file, created by
sphinx-quickstart on Wed Jun 12 20:06:39 2024.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.

.. click:: hckr.cli.dt:dt
:prog: hckr dt
:nested: full

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add a title for the hckr dt command.

Include a top-level heading to introduce this command (e.g., hckr dt underlined with =) above the click directive for better readability.

Apply this diff:

+ hckr dt
+ ========

 .. click:: hckr.cli.dt:dt
    :prog: hckr dt
    :nested: full
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.. click:: hckr.cli.dt:dt
:prog: hckr dt
:nested: full
hckr dt
========
.. click:: hckr.cli.dt:dt
:prog: hckr dt
:nested: full
🤖 Prompt for AI Agents
In docs/source/commands/dt/dt.rst around lines 6 to 8, add a top-level heading
for the `hckr dt` command by inserting a line with `hckr dt` followed by an
underline of equal signs (`=`) above the existing click directive. This will
improve readability by clearly introducing the command section.

17 changes: 17 additions & 0 deletions docs/source/commands/dt/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.. hckr documentation master file, created by
sphinx-quickstart on Wed Jun 12 20:06:39 2024.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.


Datetime Commands
=================
``hckr`` provides utilities to work with different timezones.

.. tip::
More commands will be added in future updates. Stay tuned!

commands
---------------
.. toctree::
dt
8 changes: 8 additions & 0 deletions docs/source/commands/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,11 @@ hckr
:hidden:

info/index

.. toctree::
:maxdepth: 2
:caption: Datetime
:hidden:

dt/index

2 changes: 2 additions & 0 deletions src/hckr/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from .info import info
from .k8s import k8s
from .net import net
from .dt import dt
from ..__about__ import __version__
from ..cli.cron import cron
from ..cli.crypto import crypto
Expand Down Expand Up @@ -93,6 +94,7 @@ def cli(

# NETWORK command
cli.add_command(net)
cli.add_command(dt)

# config
cli.add_command(config)
Expand Down
42 changes: 42 additions & 0 deletions src/hckr/cli/dt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import click

from hckr.utils.MessageUtils import success, error
from hckr.utils.TimeUtils import current_time, convert


@click.group(
help="datetime utilities",
context_settings={"help_option_names": ["-h", "--help"]},
)
def dt():
pass


@dt.command(help="show current time in the given timezone")
@click.option(
"-t",
"--timezone",
default="UTC",
show_default=True,
help="Timezone in which to display the time",
)
def now(timezone):
try:
dt_now = current_time(timezone)
success(f"Current time in {timezone}: {dt_now.strftime('%Y-%m-%d %H:%M:%S')}")
except Exception:
error("Failed to get current time")


@dt.command(help="convert datetime between timezones")
@click.option("--datetime", "dt_str", required=True, help="Datetime in ISO format")
@click.option("--from-tz", required=True, help="Source timezone")
@click.option("--to-tz", required=True, help="Destination timezone")
def convert_time(dt_str, from_tz, to_tz):
try:
result = convert(dt_str, from_tz, to_tz)
success(
f"{dt_str} [{from_tz}] -> {result.strftime('%Y-%m-%d %H:%M:%S')} [{to_tz}]"
)
except Exception:
error("Failed to convert time")
30 changes: 30 additions & 0 deletions src/hckr/utils/TimeUtils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from datetime import datetime
from zoneinfo import ZoneInfo

from .MessageUtils import error, success


def current_time(timezone: str = "UTC") -> datetime:
"""Return current time in the given timezone."""
try:
tz = ZoneInfo(timezone)
except Exception as e: # pragma: no cover - error should be very rare
error(f"Invalid timezone: {timezone}\n{e}")
raise
return datetime.now(tz)


def convert(dt_str: str, from_tz: str, to_tz: str) -> datetime:
"""Convert ``dt_str`` from ``from_tz`` timezone to ``to_tz`` timezone."""
try:
from_zone = ZoneInfo(from_tz)
to_zone = ZoneInfo(to_tz)
except Exception as e: # pragma: no cover - user input error
error(f"Invalid timezone provided\n{e}")
raise
dt = datetime.fromisoformat(dt_str)
if dt.tzinfo is None:
dt = dt.replace(tzinfo=from_zone)
else:
dt = dt.astimezone(from_zone)
return dt.astimezone(to_zone)
1 change: 1 addition & 0 deletions tests/cli/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def test_hckr():
crypto crypto commands
data data related commands
db Database commands
dt datetime utilities
env Environment commands
hash hash commands
info info commands
Expand Down
20 changes: 20 additions & 0 deletions tests/cli/test_dt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from click.testing import CliRunner

from hckr.cli.dt import now, convert_time


def test_dt_now():
runner = CliRunner()
result = runner.invoke(now, ["--timezone", "UTC"])
assert result.exit_code == 0
assert "Current time in UTC" in result.output


def test_dt_convert():
runner = CliRunner()
result = runner.invoke(
convert_time,
["--datetime", "2024-01-01 10:00:00", "--from-tz", "UTC", "--to-tz", "US/Pacific"],
)
assert result.exit_code == 0
assert "US/Pacific" in result.output
Loading