Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/log_analyzer_cli/parsers/syslog.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,22 @@ def _parse_timestamp(self, ts_str: str) -> Optional[datetime]:
formats = [
"%b %d %H:%M:%S",
"%Y-%m-%d %H:%M:%S",
"%Y-%m-%dT%H:%M:%S.%f%z",
"%Y-%m-%dT%H:%M:%S.%f",
"%Y-%m-%dT%H:%M:%S%z",
]

ts_str_normalized = ts_str
if ts_str_normalized.endswith("Z"):
ts_str_normalized = ts_str_normalized[:-1] + "+00:00"

for fmt in formats:
try:
if fmt == "%b %d %H:%M:%S":
dt = datetime.strptime(ts_str, fmt)
dt = dt.replace(year=year)
return dt
return datetime.strptime(ts_str, fmt)
return datetime.strptime(ts_str_normalized, fmt)
except ValueError:
continue
return None
28 changes: 28 additions & 0 deletions tests/test_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,34 @@ def test_parse_syslog_with_level(self):
assert entry.level == "ERROR"
assert "Database connection failed" in entry.message

def test_parse_iso8601_with_microseconds_and_z(self):
"""ISO-8601 timestamps with fractional seconds and a Z suffix should parse."""
parser = SyslogParser()
line = "2025-03-20T10:15:32.123Z host process[1234]: something happened"
entry = parser.parse(line)

assert entry is not None
assert entry.timestamp is not None
assert entry.timestamp.year == 2025
assert entry.timestamp.month == 3
assert entry.timestamp.day == 20
assert entry.timestamp.hour == 10
assert entry.timestamp.minute == 15
assert entry.timestamp.second == 32
assert entry.timestamp.microsecond == 123000
assert entry.timestamp.tzinfo is not None

def test_parse_iso8601_with_microseconds_and_offset(self):
"""ISO-8601 timestamps with fractional seconds and a numeric offset should parse."""
parser = SyslogParser()
line = "2025-03-20T10:15:32.123+02:00 host process[1234]: something happened"
entry = parser.parse(line)

assert entry is not None
assert entry.timestamp is not None
assert entry.timestamp.microsecond == 123000
assert entry.timestamp.utcoffset().total_seconds() == 2 * 3600


class TestJSONLogParser:
"""Tests for JSONLogParser."""
Expand Down
Loading