Normalize Timestamps to UTC DateTime in Python

Convert timestamps in multiple formats to UTC-aware datetime objects using datetime.strptime and astimezone.

Medium Python 3.9+ Aug 9, 2026 Data pipelines & processing 14 views 0 copies

Python code

28 lines
Python 3.9+
from datetime import datetime, timezone

raw_timestamps = [
    "2024-01-15 14:30:00+02:00",
    "17/05/2024 09:15:00 -0500",
    "2024-03-01T22:45:00Z",
    "2024-06-20 08:00:00+09:30"
]

def parse_and_convert(ts: str) -> datetime:
    normalized_ts = ts.strip().replace("Z", "+00:00")
    formats = [
        "%Y-%m-%d %H:%M:%S%z",
        "%d/%m/%Y %H:%M:%S %z",
        "%Y-%m-%dT%H:%M:%S%z"
    ]
    for fmt in formats:
        try:
            parsed = datetime.strptime(normalized_ts, fmt)
            return parsed.astimezone(timezone.utc)
        except ValueError:
            continue
    raise ValueError(f"Unsupported format: {ts}")

if __name__ == "__main__":
    for ts in raw_timestamps:
        utc_time = parse_and_convert(ts)
        print(f"{ts} -> {utc_time.isoformat()}")

Output

stdout
2024-01-15 14:30:00+02:00 -> 2024-01-15T12:30:00+00:00
17/05/2024 09:15:00 -0500 -> 2024-05-17T14:15:00+00:00
2024-03-01T22:45:00Z -> 2024-03-01T22:45:00+00:00
2024-06-20 08:00:00+09:30 -> 2024-06-19T22:30:00+00:00

How it works

The strptime method parses a string according to the format specifiers, producing a datetime object with the timezone offset if %z is included. The %z directive handles offsets like +0200 or -0500, but the Z suffix is not recognized by default, so it's replaced with +00:00 first. After parsing, astimezone(timezone.utc) converts to UTC in a single step, normalizing timezone differences. Trying multiple formats in a loop with try/except allows flexible parsing without complex regex. ValueError is raised only if no format matches, making the function explicit and debuggable.

Common mistakes

  • Forgetting to replace 'Z' with '+00:00'—strptime does not accept 'Z' by default.
  • Using `%z` with a space in the format when the input has no space before the offset.
  • Treating timezone-naive datetimes as UTC when an offset is actually present.

Variations

  1. Use `datetime.fromisoformat` for ISO 8601 strings, but it may not handle all formats.
  2. Use third-party libraries like `dateutil.parser` for automatic format detection.

Real-world use cases

  • Normalizing logs from multiple servers with different time zones into a single UTC timeline for analysis.
  • Converting API response timestamps before storing them in a database with UTC standard.
  • Standardizing user-generated date inputs from different regions for aggregation in a data pipeline.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Data pipelines & processing

Related tutorials and quizzes for this topic.