Switch to UTC timestamps, output in local time

This commit is contained in:
2026-01-22 23:56:07 +01:00
parent 9c7f4dfd1a
commit 9f75e5e66b
5 changed files with 23 additions and 16 deletions

View File

@@ -27,11 +27,18 @@ __all__ = [
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S %Z" DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S %Z"
def datetime_str(dt, utc=False): def datetime_str(dt, utc=False):
if not isinstance(dt, datetime.datetime): if not isinstance(dt, datetime.datetime):
return "Never" return "Never"
aware_dt = dt.replace(tzinfo=datetime.UTC) if not dt.tzinfo else dt
if utc: if utc:
return timestamp.strftime(DATETIME_FORMAT) return aware_dt.strftime(DATETIME_FORMAT)
else: else:
return timestamp.astimezone().strftime(DATETIME_FORMAT) return aware_dt.astimezone().strftime(DATETIME_FORMAT)
def utc_now():
return datetime.datetime.now(datetime.UTC).replace(tzinfo=None)

View File

@@ -2,9 +2,10 @@
import logging import logging
import threading import threading
from datetime import datetime, timedelta
from . import utc_now
from .models import Hostname, User from .models import Hostname, User
from datetime import timedelta
def cleanup_expired(app): def cleanup_expired(app):
@@ -17,7 +18,7 @@ def cleanup_expired(app):
Returns: Returns:
Number of expired hostnames processed. Number of expired hostnames processed.
""" """
now = datetime.now(datetime.timezone.utc) now = utc_now()
expired_count = 0 expired_count = 0
for hostname in Hostname.select().join(User).where( for hostname in Hostname.select().join(User).where(

View File

@@ -23,7 +23,7 @@ def cmd_user_list(args, app):
return 0 return 0
print(f"\n{'Username':<20} {'Email':<30} {'Hostnames':<10} {'Created'}") print(f"\n{'Username':<20} {'Email':<30} {'Hostnames':<10} {'Created'}")
print("-" * 82) print("-" * 86)
for user in users: for user in users:
hostname_count = Hostname.select().where( hostname_count = Hostname.select().where(
Hostname.user == user Hostname.user == user
@@ -150,15 +150,15 @@ def cmd_hostname_list(args, app):
print( print(
f"{'Hostname':<35} {'User':<15} {'Zone':<20} " f"{'Hostname':<35} {'User':<15} {'Zone':<20} "
f"{'DNS-TTL':<8} {'Exp-TTL':<8} {'Last-Update IPv4':<21} {'Last-Update IPv6'}" f"{'DNS-TTL':<8} {'Exp-TTL':<8} {'Last-Update IPv4':<25} {'Last-Update IPv6'}"
) )
print("-" * 132) print("-" * 140)
for h in hostnames: for h in hostnames:
last_ipv4_update = datetime_str(h.last_ipv4_update) if h.last_ipv4_update else "Never" last_ipv4_update = datetime_str(h.last_ipv4_update)
last_ipv6_update = datetime_str(h.last_ipv6_update) if h.last_ipv6_update else "Never" last_ipv6_update = datetime_str(h.last_ipv6_update)
print( print(
f"{h.hostname:<35} {h.user.username:<15} {h.zone:<20} " f"{h.hostname:<35} {h.user.username:<15} {h.zone:<20} "
f"{h.dns_ttl:<8} {h.expiry_ttl:<8} {last_ipv4_update:<21} {last_ipv6_update}" f"{h.dns_ttl:<8} {h.expiry_ttl:<8} {last_ipv4_update:<25} {last_ipv6_update}"
) )
return 0 return 0
@@ -252,7 +252,7 @@ def cmd_hostname_delete(args, app):
logging.warning(f"DNS delete failed: type=AAAA error={e}") logging.warning(f"DNS delete failed: type=AAAA error={e}")
hostname.delete_instance() hostname.delete_instance()
print(f"Hostname '{hostname_str}' deleted.") print(f"Hostname '{hostname_str}' in zone '{zone}' deleted.")
return 0 return 0

View File

@@ -2,8 +2,8 @@
import logging import logging
import os import os
from datetime import datetime
from . import utc_now
from peewee import ( from peewee import (
AutoField, AutoField,
CharField, CharField,
@@ -56,7 +56,7 @@ class User(BaseModel):
username = CharField(max_length=64, unique=True) username = CharField(max_length=64, unique=True)
password_hash = CharField(max_length=128) password_hash = CharField(max_length=128)
email = CharField(max_length=255) email = CharField(max_length=255)
created_at = DateTimeField(default=datetime.now) created_at = DateTimeField(default=utc_now)
class Meta: class Meta:
table_name = "users" table_name = "users"

View File

@@ -8,13 +8,12 @@ import json
import logging import logging
import signal import signal
import ssl import ssl
from datetime import datetime
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import parse_qs, urlparse from urllib.parse import parse_qs, urlparse
import argon2 import argon2
from . import datetime_str from . import datetime_str, utc_now
from .cleanup import ExpiredRecordsCleanupThread, RateLimitCleanupThread from .cleanup import ExpiredRecordsCleanupThread, RateLimitCleanupThread
from .logging import clear_txn_id, set_txn_id from .logging import clear_txn_id, set_txn_id
from .models import DoesNotExist, get_hostname_for_user, get_user from .models import DoesNotExist, get_hostname_for_user, get_user
@@ -316,7 +315,7 @@ class DDNSRequestHandler(BaseHTTPRequestHandler):
except ValueError: except ValueError:
return (400, "badip") return (400, "badip")
now = datetime.now(datetime.timezone.utc) now = utc_now()
changed = False changed = False
if ipv4: if ipv4: