feat: Add intial site
All checks were successful
Build Docker / BuildImage (push) Successful in 50s

This commit is contained in:
2025-03-06 15:15:24 +11:00
parent 66620204ac
commit 6d7019bba5
6 changed files with 284 additions and 5 deletions

118
server.py
View File

@@ -13,8 +13,12 @@ from flask import (
import os
import json
import requests
from datetime import datetime
from datetime import datetime, timedelta
import dotenv
from pytz import timezone
import pytz
import re
dotenv.load_dotenv()
@@ -76,6 +80,118 @@ def wellknown(path):
def index():
return render_template("index.html")
# Mapping of short timezone names to full names
SHORT_TZ_MAP = {
"GMT": "Etc/GMT",
"PST": "America/Los_Angeles",
"PDT": "America/Los_Angeles",
"MST": "America/Denver",
"MDT": "America/Denver",
"CST": "America/Chicago",
"CDT": "America/Chicago",
"EST": "America/New_York",
"EDT": "America/New_York",
"AKST": "America/Anchorage",
"AKDT": "America/Anchorage",
"HST": "Pacific/Honolulu",
"HDT": "Pacific/Honolulu",
"AST": "America/Puerto_Rico",
"NST": "America/St_Johns",
"BST": "Europe/London",
"CET": "Europe/Paris",
"CEST": "Europe/Paris",
"EET": "Europe/Athens",
"EEST": "Europe/Athens",
"MSK": "Europe/Moscow",
"MSD": "Europe/Moscow",
"IST": "Asia/Kolkata",
"PKT": "Asia/Karachi",
"WIB": "Asia/Jakarta",
"WITA": "Asia/Makassar",
"WIT": "Asia/Jayapura",
"CST": "Asia/Shanghai",
"JST": "Asia/Tokyo",
"KST": "Asia/Seoul",
"AEDT": "Australia/Sydney",
"AEST": "Australia/Sydney",
"ACST": "Australia/Adelaide",
"ACDT": "Australia/Adelaide",
"AWST": "Australia/Perth",
}
def get_full_timezone(tz):
match = re.match(r"^UTC([+-]\d{1,2}):?(\d{2})?$", tz)
if match:
hours = int(match.group(1))
minutes = int(match.group(2)) if match.group(2) else 0
return pytz.FixedOffset(hours * 60 + minutes)
full_tz = SHORT_TZ_MAP.get(tz, tz)
return pytz.timezone(full_tz) if isinstance(full_tz, str) else None
@app.route("/api/v1/convert", methods=["POST"])
def convert():
data = request.json
from_tz = get_full_timezone(data.get("from_tz").replace("_", "/"))
to_tz = get_full_timezone(data.get("to_tz").replace("_", "/"))
time = data.get("time")
if from_tz is None or to_tz is None:
return jsonify({"error": "Invalid timezone"}), 400
# Parse the input time
try:
input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S")
except ValueError:
input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M")
try:
# Get the timezone
from_tz_time = from_tz.localize(input_time)
# Convert the time
to_tz_time = from_tz_time.astimezone(to_tz)
except Exception as e:
return jsonify({"error": str(e)}), 400
return jsonify(
{
"from": from_tz_time.strftime("%Y-%m-%d %H:%M:%S %Z"),
"to": to_tz_time.strftime("%Y-%m-%d %H:%M:%S %Z"),
}
)
@app.route("/api/v1/convert_multiple", methods=["POST"])
def convert_multiple():
data = request.json
from_tz = get_full_timezone(data.get("from_tz").replace("_", "/"))
time = data.get("time")
to_tz_list = [(tz, get_full_timezone(tz.replace("_", "/"))) for tz in data.get("to_tzs") if len(tz) > 0]
if from_tz is None or any(tz[1] is None for tz in to_tz_list):
return jsonify({"error": "Invalid timezone"}), 400
# Parse the input time
try:
input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S")
except ValueError:
input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M")
try:
# Get the timezone
from_tz_time = from_tz.localize(input_time)
# Convert the time to each timezone in the list
results = {}
for original_tz, tz in to_tz_list:
to_tz_time = from_tz_time.astimezone(tz)
offset = to_tz_time.strftime('%z')
offset_formatted = f"UTC{offset[:3]}:{offset[3:]}" if offset else ""
tz_name = to_tz_time.tzname() if to_tz_time.tzname() else offset_formatted
results[original_tz] = f"{to_tz_time.strftime('%Y-%m-%d %H:%M:%S')} {tz_name}"
except Exception as e:
return jsonify({"error": str(e)}), 400
return jsonify(results)
@app.route("/<path:path>")
def catch_all(path: str):