Initial commit
This commit is contained in:
136
skills/timezone-tools/SKILL.md
Normal file
136
skills/timezone-tools/SKILL.md
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
name: timezone-tools
|
||||
description: Get current time in any timezone and convert times between timezones. Use when working with time, dates, timezones, scheduling across regions, or when user mentions specific cities/regions for time queries. Supports IANA timezone names.
|
||||
---
|
||||
|
||||
# Timezone Tools
|
||||
|
||||
Get current time in any timezone and convert times between different timezones using IANA timezone database.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Get current time in a timezone
|
||||
|
||||
```bash
|
||||
python scripts/get_time.py "America/New_York"
|
||||
```
|
||||
|
||||
### Convert time between timezones
|
||||
|
||||
```bash
|
||||
python scripts/convert_time.py "America/New_York" "14:30" "Australia/Perth"
|
||||
```
|
||||
|
||||
### Search for timezone names
|
||||
|
||||
```bash
|
||||
python scripts/list_timezones.py "perth"
|
||||
```
|
||||
|
||||
## Instructions
|
||||
|
||||
When the user asks about time or timezones:
|
||||
|
||||
1. **For current time queries** (e.g., "What time is it in Tokyo?"):
|
||||
- Use `get_time.py` with IANA timezone name
|
||||
- If unsure of timezone name, search first with `list_timezones.py`
|
||||
- Script outputs: timezone, datetime, day of week, DST status
|
||||
|
||||
2. **For time conversions** (e.g., "What's 2pm EST in Perth time?"):
|
||||
- Use `convert_time.py` with source timezone, time (HH:MM 24-hour), target timezone
|
||||
- Script shows source time, target time, and time difference
|
||||
- Automatically handles DST changes
|
||||
|
||||
3. **For timezone searches**:
|
||||
- Use `list_timezones.py` with city/country name
|
||||
- Returns matching IANA timezone names
|
||||
|
||||
## Common Timezones Reference
|
||||
|
||||
For quick reference, see [data/common_timezones.json](data/common_timezones.json) which includes major cities worldwide, with Perth prominently featured.
|
||||
|
||||
**User's local timezone**: The scripts automatically detect your local timezone using `tzlocal`.
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Current time query
|
||||
|
||||
User: "What time is it in Perth?"
|
||||
|
||||
```bash
|
||||
python scripts/list_timezones.py "perth"
|
||||
# Output: Australia/Perth
|
||||
|
||||
python scripts/get_time.py "Australia/Perth"
|
||||
# Output:
|
||||
# Timezone: Australia/Perth
|
||||
# Current time: 2025-11-07T15:30:45
|
||||
# Day: Thursday
|
||||
# DST: No
|
||||
```
|
||||
|
||||
### Example 2: Time conversion
|
||||
|
||||
User: "I have a meeting at 2pm New York time, what time is that in Perth?"
|
||||
|
||||
```bash
|
||||
python scripts/convert_time.py "America/New_York" "14:00" "Australia/Perth"
|
||||
# Output:
|
||||
# Source: America/New_York - 2025-11-07T14:00:00 (Thursday, DST: No)
|
||||
# Target: Australia/Perth - 2025-11-08T03:00:00 (Friday, DST: No)
|
||||
# Time difference: +13.0h
|
||||
```
|
||||
|
||||
### Example 3: Multiple timezone search
|
||||
|
||||
User: "What are the timezone codes for London, Tokyo, and Sydney?"
|
||||
|
||||
```bash
|
||||
python scripts/list_timezones.py "london"
|
||||
python scripts/list_timezones.py "tokyo"
|
||||
python scripts/list_timezones.py "sydney"
|
||||
# Outputs:
|
||||
# Europe/London
|
||||
# Asia/Tokyo
|
||||
# Australia/Sydney
|
||||
```
|
||||
|
||||
## Time Format
|
||||
|
||||
- All times use **24-hour format** (HH:MM): `14:30` not `2:30 PM`
|
||||
- ISO 8601 datetime format for output: `2025-11-07T14:30:45`
|
||||
- IANA timezone names (e.g., `America/New_York`, not `EST`)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Invalid timezone" error
|
||||
|
||||
- Use IANA timezone names: `America/New_York` not `EST` or `Eastern`
|
||||
- Search with `list_timezones.py` if unsure
|
||||
- Check [data/common_timezones.json](data/common_timezones.json) for reference
|
||||
|
||||
### "Invalid time format" error
|
||||
|
||||
- Use 24-hour format: `14:30` not `2:30 PM`
|
||||
- Format must be `HH:MM` with colon separator
|
||||
|
||||
### Missing dependencies
|
||||
|
||||
Install required Python packages:
|
||||
|
||||
```bash
|
||||
pip install tzlocal
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Python 3.9+
|
||||
- `tzlocal>=5.0` - for local timezone detection
|
||||
- `zoneinfo` - built-in Python 3.9+ (IANA timezone database)
|
||||
|
||||
## Notes
|
||||
|
||||
- Scripts automatically handle Daylight Saving Time (DST)
|
||||
- Local timezone is auto-detected from system
|
||||
- All timezone data uses IANA Time Zone Database
|
||||
- Perth, Australia timezone: `Australia/Perth` (UTC+8, no DST)
|
||||
67
skills/timezone-tools/data/common_timezones.json
Normal file
67
skills/timezone-tools/data/common_timezones.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"australia": {
|
||||
"Perth": "Australia/Perth",
|
||||
"Sydney": "Australia/Sydney",
|
||||
"Melbourne": "Australia/Melbourne",
|
||||
"Brisbane": "Australia/Brisbane",
|
||||
"Adelaide": "Australia/Adelaide",
|
||||
"Darwin": "Australia/Darwin",
|
||||
"Hobart": "Australia/Hobart"
|
||||
},
|
||||
"north_america": {
|
||||
"New York": "America/New_York",
|
||||
"Los Angeles": "America/Los_Angeles",
|
||||
"Chicago": "America/Chicago",
|
||||
"Denver": "America/Denver",
|
||||
"Toronto": "America/Toronto",
|
||||
"Vancouver": "America/Vancouver",
|
||||
"Mexico City": "America/Mexico_City"
|
||||
},
|
||||
"europe": {
|
||||
"London": "Europe/London",
|
||||
"Paris": "Europe/Paris",
|
||||
"Berlin": "Europe/Berlin",
|
||||
"Madrid": "Europe/Madrid",
|
||||
"Rome": "Europe/Rome",
|
||||
"Amsterdam": "Europe/Amsterdam",
|
||||
"Stockholm": "Europe/Stockholm",
|
||||
"Moscow": "Europe/Moscow"
|
||||
},
|
||||
"asia": {
|
||||
"Tokyo": "Asia/Tokyo",
|
||||
"Hong Kong": "Asia/Hong_Kong",
|
||||
"Singapore": "Asia/Singapore",
|
||||
"Beijing": "Asia/Shanghai",
|
||||
"Mumbai": "Asia/Kolkata",
|
||||
"Dubai": "Asia/Dubai",
|
||||
"Seoul": "Asia/Seoul",
|
||||
"Bangkok": "Asia/Bangkok"
|
||||
},
|
||||
"south_america": {
|
||||
"Sao Paulo": "America/Sao_Paulo",
|
||||
"Buenos Aires": "America/Argentina/Buenos_Aires",
|
||||
"Lima": "America/Lima",
|
||||
"Bogota": "America/Bogota",
|
||||
"Santiago": "America/Santiago"
|
||||
},
|
||||
"africa": {
|
||||
"Cairo": "Africa/Cairo",
|
||||
"Johannesburg": "Africa/Johannesburg",
|
||||
"Lagos": "Africa/Lagos",
|
||||
"Nairobi": "Africa/Nairobi"
|
||||
},
|
||||
"pacific": {
|
||||
"Auckland": "Pacific/Auckland",
|
||||
"Fiji": "Pacific/Fiji",
|
||||
"Honolulu": "Pacific/Honolulu",
|
||||
"Guam": "Pacific/Guam"
|
||||
},
|
||||
"utc": {
|
||||
"UTC": "UTC"
|
||||
},
|
||||
"_notes": {
|
||||
"format": "City Name -> IANA Timezone",
|
||||
"perth_details": "Perth: UTC+8, no DST, Western Australia",
|
||||
"usage": "Use list_timezones.py to search for additional cities"
|
||||
}
|
||||
}
|
||||
89
skills/timezone-tools/scripts/convert_time.py
Executable file
89
skills/timezone-tools/scripts/convert_time.py
Executable 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()
|
||||
45
skills/timezone-tools/scripts/get_time.py
Executable file
45
skills/timezone-tools/scripts/get_time.py
Executable 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()
|
||||
53
skills/timezone-tools/scripts/list_timezones.py
Executable file
53
skills/timezone-tools/scripts/list_timezones.py
Executable 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()
|
||||
7
skills/timezone-tools/scripts/requirements.txt
Normal file
7
skills/timezone-tools/scripts/requirements.txt
Normal 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
|
||||
Reference in New Issue
Block a user