Skip to content

Commit 6582aae

Browse files
committed
tz-aware datetimes
1 parent ec14730 commit 6582aae

File tree

7 files changed

+28
-26
lines changed

7 files changed

+28
-26
lines changed

handlers/library_handler.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,7 +1068,7 @@ def _should_check_series_grouping(self):
10681068
bool: True if we should check (and potentially disable) series grouping
10691069
"""
10701070
try:
1071-
from datetime import datetime, timedelta
1071+
from datetime import datetime, timedelta, timezone
10721072

10731073
# Get the last check time from the database
10741074
library_settings = self.driver.automator.profile_manager.get_library_settings()
@@ -1082,7 +1082,7 @@ def _should_check_series_grouping(self):
10821082
return True
10831083

10841084
# Check if it's been more than 24 hours
1085-
now = datetime.now()
1085+
now = datetime.now(timezone.utc)
10861086
time_since_check = now - last_check
10871087
should_check = time_since_check > timedelta(hours=24)
10881088

@@ -1135,7 +1135,7 @@ def _handle_series_grouping_if_needed(self):
11351135
repo = UserRepository(session)
11361136
# Use update_user_field which is idempotent (creates library_settings if needed)
11371137
success = repo.update_user_field(
1138-
sindarin_email, "library_settings.last_series_group_check", datetime.now()
1138+
sindarin_email, "library_settings.last_series_group_check", datetime.now(timezone.utc)
11391139
)
11401140
if success:
11411141
logger.info("Updated last_series_group_check timestamp in database")

scripts/db_export.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import json
44
import logging
55
import sys
6-
from datetime import datetime
6+
from datetime import datetime, timezone
77
from pathlib import Path
88

99
# Add project root to Python path
@@ -70,7 +70,7 @@ def export_database(output_file: str = None) -> None:
7070
db_connection.initialize()
7171

7272
# Prepare export data
73-
export_data = {"export_timestamp": datetime.now().isoformat(), "tables": {}}
73+
export_data = {"export_timestamp": datetime.now(timezone.utc).isoformat(), "tables": {}}
7474

7575
with db_connection.get_session() as session:
7676
# Export all tables
@@ -95,7 +95,7 @@ def export_database(output_file: str = None) -> None:
9595

9696
# Generate output filename if not provided
9797
if not output_file:
98-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
98+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
9999
output_file = f"backups/kindle_db_export_{timestamp}.json"
100100

101101
# Ensure backup directory exists

server/resources/cold_storage_resources.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from datetime import datetime
2+
from datetime import datetime, timezone
33

44
from flask import request
55
from flask_restful import Resource
@@ -56,7 +56,7 @@ def _handle_archive_request(self):
5656
"message": f"User {user_email} archived to cold storage",
5757
"user_email": user_email,
5858
"storage_info": storage_info,
59-
"timestamp": datetime.now().isoformat(),
59+
"timestamp": datetime.now(timezone.utc).isoformat(),
6060
"dry_run": dry_run,
6161
}
6262
else:
@@ -65,7 +65,7 @@ def _handle_archive_request(self):
6565
"message": f"Failed to archive user {user_email}",
6666
"user_email": user_email,
6767
"error": storage_info.get("error") if storage_info else "Unknown error",
68-
"timestamp": datetime.now().isoformat(),
68+
"timestamp": datetime.now(timezone.utc).isoformat(),
6969
}, 400
7070

7171
# Otherwise, archive all eligible profiles
@@ -86,7 +86,7 @@ def _handle_archive_request(self):
8686
"success_count": success_count,
8787
"failure_count": failure_count,
8888
"storage_info": storage_info,
89-
"timestamp": datetime.now().isoformat(),
89+
"timestamp": datetime.now(timezone.utc).isoformat(),
9090
"dry_run": dry_run,
9191
}
9292

@@ -150,7 +150,7 @@ def get(self):
150150
if last_used:
151151
try:
152152
# Convert Unix timestamp to ISO format string
153-
last_used_date = datetime.fromtimestamp(last_used).isoformat()
153+
last_used_date = datetime.fromtimestamp(last_used, tz=timezone.utc).isoformat()
154154
except (ValueError, TypeError):
155155
logger.warning(f"Invalid last_used timestamp for {email}: {last_used}")
156156
else:
@@ -183,7 +183,7 @@ def get(self):
183183
"eligible_profiles": eligible_profiles,
184184
"active_profiles": active_profiles,
185185
"days_threshold": days_inactive,
186-
"timestamp": datetime.now().isoformat(),
186+
"timestamp": datetime.now(timezone.utc).isoformat(),
187187
}
188188

189189
except Exception as e:
@@ -235,14 +235,14 @@ def _handle_restore_request(self):
235235
"success": True,
236236
"message": f"Successfully restored {user_email} from local backup",
237237
"user_email": user_email,
238-
"timestamp": datetime.now().isoformat(),
238+
"timestamp": datetime.now(timezone.utc).isoformat(),
239239
}
240240
else:
241241
return {
242242
"success": False,
243243
"message": f"Failed to restore {user_email} from local backup",
244244
"user_email": user_email,
245-
"timestamp": datetime.now().isoformat(),
245+
"timestamp": datetime.now(timezone.utc).isoformat(),
246246
}, 400
247247
else:
248248
# Normal restore from cold storage
@@ -269,7 +269,7 @@ def _handle_restore_request(self):
269269
"message": message,
270270
"user_email": user_email,
271271
"restore_info": restore_info,
272-
"timestamp": datetime.now().isoformat(),
272+
"timestamp": datetime.now(timezone.utc).isoformat(),
273273
"dry_run": dry_run,
274274
}
275275
else:
@@ -278,7 +278,7 @@ def _handle_restore_request(self):
278278
"message": f"Failed to restore {user_email} from cold storage",
279279
"user_email": user_email,
280280
"error": restore_info.get("error") if restore_info else "Unknown error",
281-
"timestamp": datetime.now().isoformat(),
281+
"timestamp": datetime.now(timezone.utc).isoformat(),
282282
}, 400
283283

284284
except Exception as e:

server/resources/idle_check_resources.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import logging
44
import platform
55
import time
6-
from datetime import datetime, timedelta
6+
from datetime import datetime, timedelta, timezone
77

88
from flask import request
99
from flask_restful import Resource
@@ -206,7 +206,7 @@ def _check_and_shutdown_idle(self, timeout_minutes=None):
206206
# Prepare summary
207207
server = AutomationServer.get_instance()
208208
summary = {
209-
"timestamp": datetime.now().isoformat(),
209+
"timestamp": datetime.now(timezone.utc).isoformat(),
210210
"idle_timeout_minutes": timeout_minutes,
211211
"total_checked": len(server.automators),
212212
"shut_down": len([s for s in shutdown_emails if s.get("status") == "shutdown"]),

server/resources/staff_auth_resources.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Staff authentication resource."""
22

33
import logging
4-
from datetime import datetime
4+
from datetime import datetime, timezone
55

66
from flask import jsonify, make_response, request
77
from flask_restful import Resource
@@ -144,9 +144,9 @@ def get(self):
144144
for token_info in tokens:
145145
if "created_at" in token_info:
146146
timestamp = token_info["created_at"]
147-
token_info["created_at_formatted"] = datetime.fromtimestamp(timestamp).strftime(
148-
"%Y-%m-%d %H:%M:%S"
149-
)
147+
token_info["created_at_formatted"] = datetime.fromtimestamp(
148+
timestamp, tz=timezone.utc
149+
).strftime("%Y-%m-%d %H:%M:%S")
150150

151151
# Truncate the actual token for security
152152
if "token" in token_info:

server/resources/user_activity_resource.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import json
55
import os
66
import re
7-
from datetime import datetime, timedelta
7+
from datetime import datetime, timedelta, timezone
88
from pathlib import Path
99

1010
from flask import make_response, request
@@ -186,7 +186,7 @@ def _parse_log_lines(self, file_obj, user_email):
186186
if timestamp_match:
187187
time_str = timestamp_match.group(1)
188188
# Use today's date with the time
189-
today = datetime.now().date()
189+
today = datetime.now(timezone.utc).date()
190190
timestamp = datetime.combine(today, datetime.strptime(time_str, "%H:%M:%S").time())
191191

192192
if not timestamp:

server/utils/emulator_launcher.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import platform
1010
import subprocess
1111
import time
12-
from datetime import datetime
12+
from datetime import datetime, timezone
1313
from pathlib import Path
1414
from typing import Dict, List, Optional, Set, Tuple
1515

@@ -2124,7 +2124,9 @@ def has_snapshot(self, email: str, snapshot_name: str) -> bool:
21242124
# Get snapshot size and modification time for debugging
21252125
snapshot_stat = os.stat(snapshot_path)
21262126
snapshot_size_mb = snapshot_stat.st_size / (1024 * 1024)
2127-
snapshot_mtime = datetime.fromtimestamp(snapshot_stat.st_mtime).strftime("%Y-%m-%d %H:%M:%S")
2127+
snapshot_mtime = datetime.fromtimestamp(snapshot_stat.st_mtime, tz=timezone.utc).strftime(
2128+
"%Y-%m-%d %H:%M:%S"
2129+
)
21282130
logger.debug(
21292131
f"Snapshot '{snapshot_name}' exists for {email} at {snapshot_path} "
21302132
f"(size: {snapshot_size_mb:.1f}MB, modified: {snapshot_mtime})"

0 commit comments

Comments
 (0)