Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:32:48 +08:00
commit 9997176040
24 changed files with 2371 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
#!/usr/bin/env python3
"""Convert time between timezones."""
import sys
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
def convert_time(source_tz: str, time_str: str, target_tz: str) -> None:
"""Convert time from source timezone to target timezone.
Args:
source_tz: Source IANA timezone name (e.g., 'America/New_York')
time_str: Time to convert in 24-hour format (HH:MM)
target_tz: Target IANA timezone name (e.g., 'Australia/Perth')
"""
try:
# Parse timezone names
source_timezone = ZoneInfo(source_tz)
target_timezone = ZoneInfo(target_tz)
# Parse time string
try:
parsed_time = datetime.strptime(time_str, "%H:%M").time()
except ValueError:
print(f"Error: Invalid time format '{time_str}'", file=sys.stderr)
print("Expected format: HH:MM (24-hour, e.g., '14:30')", file=sys.stderr)
sys.exit(1)
# Create datetime for today in source timezone
now = datetime.now(source_timezone)
source_time = datetime(
now.year,
now.month,
now.day,
parsed_time.hour,
parsed_time.minute,
tzinfo=source_timezone,
)
# Convert to target timezone
target_time = source_time.astimezone(target_timezone)
# Calculate time difference
source_offset = source_time.utcoffset() or timedelta()
target_offset = target_time.utcoffset() or timedelta()
hours_difference = (target_offset - source_offset).total_seconds() / 3600
# Format time difference (handle fractional hours like Nepal's +5:45)
if hours_difference.is_integer():
time_diff_str = f"{hours_difference:+.1f}h"
else:
time_diff_str = f"{hours_difference:+.2f}".rstrip("0").rstrip(".") + "h"
# Check DST status
source_dst = source_time.dst() is not None and source_time.dst().total_seconds() != 0
target_dst = target_time.dst() is not None and target_time.dst().total_seconds() != 0
# Output formatted information
print(f"Source: {source_tz} - {source_time.isoformat(timespec='seconds')} "
f"({source_time.strftime('%A')}, DST: {'Yes' if source_dst else 'No'})")
print(f"Target: {target_tz} - {target_time.isoformat(timespec='seconds')} "
f"({target_time.strftime('%A')}, DST: {'Yes' if target_dst else 'No'})")
print(f"Time difference: {time_diff_str}")
except Exception as e:
if "ZoneInfo" in str(type(e).__name__):
print(f"Error: Invalid timezone", file=sys.stderr)
else:
print(f"Error: {str(e)}", file=sys.stderr)
sys.exit(1)
def main():
if len(sys.argv) != 4:
print("Usage: python convert_time.py <source_tz> <time> <target_tz>", file=sys.stderr)
print("Example: python convert_time.py 'America/New_York' '14:30' 'Australia/Perth'",
file=sys.stderr)
sys.exit(1)
source_tz = sys.argv[1]
time_str = sys.argv[2]
target_tz = sys.argv[3]
convert_time(source_tz, time_str, target_tz)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python3
"""Get current time in a specific timezone."""
import sys
from datetime import datetime
from zoneinfo import ZoneInfo
def get_current_time(timezone_name: str) -> None:
"""Get and display current time in specified timezone.
Args:
timezone_name: IANA timezone name (e.g., 'America/New_York')
"""
try:
timezone = ZoneInfo(timezone_name)
current_time = datetime.now(timezone)
# Check if DST is active
is_dst = current_time.dst() is not None and current_time.dst().total_seconds() != 0
# Output formatted information
print(f"Timezone: {timezone_name}")
print(f"Current time: {current_time.isoformat(timespec='seconds')}")
print(f"Day: {current_time.strftime('%A')}")
print(f"DST: {'Yes' if is_dst else 'No'}")
except Exception as e:
print(f"Error: Invalid timezone '{timezone_name}'", file=sys.stderr)
print(f"Details: {str(e)}", file=sys.stderr)
sys.exit(1)
def main():
if len(sys.argv) != 2:
print("Usage: python get_time.py <timezone>", file=sys.stderr)
print("Example: python get_time.py 'America/New_York'", file=sys.stderr)
sys.exit(1)
timezone_name = sys.argv[1]
get_current_time(timezone_name)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""Search for IANA timezone names."""
import sys
from zoneinfo import available_timezones
def list_timezones(search_term: str = "") -> None:
"""List timezone names matching the search term.
Args:
search_term: Optional search term to filter timezone names (case-insensitive)
"""
try:
all_timezones = sorted(available_timezones())
if search_term:
# Case-insensitive search
search_lower = search_term.lower()
matching = [tz for tz in all_timezones if search_lower in tz.lower()]
if matching:
print(f"Timezones matching '{search_term}':")
for tz in matching:
print(f" {tz}")
else:
print(f"No timezones found matching '{search_term}'", file=sys.stderr)
print("\nTip: Try searching for city names like 'perth', 'london', 'tokyo'",
file=sys.stderr)
sys.exit(1)
else:
# List all timezones (this is a lot!)
print(f"All available timezones ({len(all_timezones)} total):")
for tz in all_timezones:
print(f" {tz}")
except Exception as e:
print(f"Error: {str(e)}", file=sys.stderr)
sys.exit(1)
def main():
if len(sys.argv) > 2:
print("Usage: python list_timezones.py [search_term]", file=sys.stderr)
print("Example: python list_timezones.py 'perth'", file=sys.stderr)
sys.exit(1)
search_term = sys.argv[1] if len(sys.argv) == 2 else ""
list_timezones(search_term)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,7 @@
# Timezone Tools - Python Dependencies
# Install with: pip install -r requirements.txt
# Local timezone detection
tzlocal>=5.0
# Note: zoneinfo is built into Python 3.9+, no installation needed