robust parser for timestamps
This commit is contained in:
parent
35d204d9b0
commit
dd4c417200
38
analytics.py
38
analytics.py
@ -56,6 +56,40 @@ def get_device_type(user_agent):
|
||||
else:
|
||||
return 'Other'
|
||||
|
||||
def parse_timestamp(ts_str):
|
||||
try:
|
||||
# Try the normal ISO parsing.
|
||||
return datetime.fromisoformat(ts_str)
|
||||
except ValueError as e:
|
||||
if 'unconverted data remains' in str(e):
|
||||
# Find where the timezone starts. Look for a '+' or '-' after the time.
|
||||
for sign in ['+', '-']:
|
||||
pos = ts_str.find(sign)
|
||||
if pos != -1:
|
||||
# Assume the base part is up to pos and then the tz part
|
||||
base = ts_str[:pos]
|
||||
tz_part = ts_str[pos:]
|
||||
# Remove any colon from the tz part to help with parsing.
|
||||
tz_clean = tz_part.replace(':', '')
|
||||
# Try parsing the base part. It might or might not have fractional seconds.
|
||||
try:
|
||||
dt = datetime.fromisoformat(base)
|
||||
except ValueError:
|
||||
dt = datetime.strptime(base, '%Y-%m-%dT%H:%M:%S')
|
||||
# Extract hours and minutes from the tz portion.
|
||||
try:
|
||||
offset_hours = int(tz_clean[1:3])
|
||||
offset_minutes = int(tz_clean[3:5])
|
||||
except Exception:
|
||||
raise ValueError(f"Unable to parse timezone from {ts_str}")
|
||||
offset = timedelta(hours=offset_hours, minutes=offset_minutes)
|
||||
if tz_clean[0] == '-':
|
||||
offset = -offset
|
||||
# Return a timezone-aware datetime.
|
||||
return dt.replace(tzinfo=timezone(offset))
|
||||
# If it's some other ValueError, re-raise it.
|
||||
raise
|
||||
|
||||
def log_file_access(rel_path, filesize, mime, ip_address, user_agent, device_id, cached):
|
||||
"""Insert a file access record into the database and prune entries older than 10 minutes."""
|
||||
global file_access_temp
|
||||
@ -70,11 +104,11 @@ def log_file_access(rel_path, filesize, mime, ip_address, user_agent, device_id,
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (iso_ts, rel_path, filesize, mime, ip_address, user_agent, device_id, cached))
|
||||
|
||||
# Remove entries older than 10 minutes
|
||||
# Remove entries older than 10 minutes using our robust parser.
|
||||
cutoff_time = datetime.now(timezone.utc).astimezone() - timedelta(minutes=10)
|
||||
file_access_temp[:] = [
|
||||
entry for entry in file_access_temp
|
||||
if datetime.fromisoformat(entry[0]) >= cutoff_time
|
||||
if parse_timestamp(entry[0]) >= cutoff_time
|
||||
]
|
||||
|
||||
# Add the new entry at the beginning of the list
|
||||
|
||||
11
app.py
11
app.py
@ -364,13 +364,13 @@ def query_recent_connections():
|
||||
rows = a.return_file_access()
|
||||
connections = [
|
||||
{
|
||||
'timestamp': datetime.strptime(row[0], '%Y-%m-%dT%H:%M:%S.%f').strftime('%d.%m.%Y %H:%M:%S'),
|
||||
'timestamp': datetime.fromisoformat(row[0]).strftime('%d.%m.%Y %H:%M:%S'),
|
||||
'full_path': row[1],
|
||||
'filesize' : row[2],
|
||||
'mime_typ' : row[3],
|
||||
'filesize': row[2],
|
||||
'mime_typ': row[3],
|
||||
'ip_address': row[4],
|
||||
'user_agent': row[5],
|
||||
'cached': row[7]
|
||||
'cached': row[7]
|
||||
}
|
||||
for row in rows
|
||||
]
|
||||
@ -384,6 +384,7 @@ def query_recent_connections():
|
||||
background_thread_running = False
|
||||
print("No clients connected; stopping query thread.")
|
||||
|
||||
|
||||
@socketio.on('connect')
|
||||
def handle_connect(auth=None):
|
||||
global clients_connected, background_thread_running
|
||||
@ -405,7 +406,7 @@ def handle_request_initial_data():
|
||||
rows = a.return_file_access()
|
||||
connections = [
|
||||
{
|
||||
'timestamp': datetime.strptime(row[0], '%Y-%m-%dT%H:%M:%S.%f').strftime('%d.%m.%Y %H:%M:%S'),
|
||||
'timestamp': datetime.fromisoformat(row[0]).strftime('%d.%m.%Y %H:%M:%S'),
|
||||
'full_path': row[1],
|
||||
'filesize' : row[2],
|
||||
'mime_typ' : row[3],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user