Introduction
Working with timestamps is a common task in data analysis, especially when handling satellite observations, logs, or global datasets. Often, timestamps are given in UTC (Coordinated Universal Time) — a standard time reference — but you may need to display or analyze them in your local time zone.
In this article, we’ll explore how to convert UTC time to local time in Python, using several practical approaches.
Convert Current UTC Time to Local Time Using zoneinfo
Using the datetime and zoneinfo Modules (Python 3.9+)
Starting from Python 3.9, the standard library includes the zoneinfo module for handling time zones without external dependencies.
Example:
1 2 3 4 5 6 7 8 9 10 | from datetime import datetime from zoneinfo import ZoneInfo # Create a datetime object in UTC utc_time = datetime(2025, 7, 5, 12, 0, 0, tzinfo=ZoneInfo("UTC")) print("UTC Time:", utc_time) # Convert to local time (e.g., US Eastern) local_time = utc_time.astimezone(ZoneInfo("America/New_York")) print("Local Time (US Eastern):", local_time) |
Output:
1 2 | UTC Time: 2025-07-05 12:00:00+00:00 Local Time (US Eastern): 2025-07-05 08:00:00-04:00 |
The astimezone() method automatically adjusts for Daylight Saving Time (DST) when applicable.
Convert Current UTC Time to Local Time
You can also convert the current UTC time dynamically:
1 2 3 4 5 6 7 8 9 10 11 | from datetime import datetime from zoneinfo import ZoneInfo # Current UTC time utc_now = datetime.now(ZoneInfo("UTC")) # Convert to local time local_now = utc_now.astimezone(ZoneInfo("America/Los_Angeles")) print("UTC Now:", utc_now) print("Local Time (Los Angeles):", local_now) |
This is useful for real-time applications, such as logging, monitoring systems, or data pipelines.
Convert Without Knowing the Time Zone (System Local Time)
If you just want to convert UTC to your system’s local time zone, use astimezone() with no arguments:
1 2 3 4 5 6 7 8 9 | from datetime import datetime, timezone # UTC datetime utc_time = datetime(2025, 10, 27, 14, 0, 0, tzinfo=timezone.utc) # Convert to local system time local_time = utc_time.astimezone() print("Local Time:", local_time) |
Python will use your computer’s configured time zone.
Converting a Column of UTC Times in a Pandas DataFrame
When working with time series or datasets (e.g., from sensors or satellites), it’s common to convert an entire column of timestamps.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import pandas as pd # Example DataFrame df = pd.DataFrame({ "utc_time": ["2025-07-05T12:00:00Z", "2025-07-05T18:00:00Z"] }) # Convert to datetime and set timezone df["utc_time"] = pd.to_datetime(df["utc_time"], utc=True) # Convert to local timezone (e.g., US Eastern) df["local_time"] = df["utc_time"].dt.tz_convert("America/New_York") print(df) |
Output:
1 2 3 | utc_time local_time 0 2025-07-05 12:00:00+00:00 2025-07-05 08:00:00-04:00 1 2025-07-05 18:00:00+00:00 2025-07-05 14:00:00-04:00 |
pandas handles time zone conversions efficiently, making it ideal for large datasets.
Common Time Zone Examples
| Region | Zone Name | Example |
|---|---|---|
| UTC | "UTC" |
Global standard |
| Eastern US | "America/New_York" |
EST/EDT |
| Pacific US | "America/Los_Angeles" |
PST/PDT |
| Europe | "Europe/Paris" |
CET/CEST |
| Japan | "Asia/Tokyo" |
JST |
You can find all available time zone names in the IANA time zone database.
Summary
| Method | Module | Description |
|---|---|---|
astimezone(ZoneInfo("Zone")) |
zoneinfo |
Best modern approach (Python 3.9+) |
astimezone() |
datetime |
Converts to system local time |
dt.tz_convert() |
pandas |
Ideal for bulk conversion in DataFrames |
Key Takeaways
- Always attach a timezone (
tzinfo) before converting times. - Use
zoneinfo(built-in) instead of olderpytzfor modern code. - Pandas provides vectorized operations for efficient timezone handling.
- Be careful with Daylight Saving Time transitions when comparing times.
Convert UTC Time to Local Time Using Latitude and Longitude
When you only have UTC time and geographic coordinates (latitude, longitude), you can still estimate the local time in two ways:
- Accurately, using the
timezonefinderpackage to determine the real time zone. - Approximately, by computing the time offset from longitude (simple and fast for large datasets).
Option 1 — Using timezonefinder (Accurate Time Zone Detection)
Installation
To install the library:
1 | pip install timezonefinder |
Example: Convert UTC → Local Time from Coordinates
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from datetime import datetime from zoneinfo import ZoneInfo from timezonefinder import TimezoneFinder # Example coordinates: Los Angeles, CA latitude = 34.05 longitude = -118.25 # Step 1. Get timezone name tf = TimezoneFinder() timezone_name = tf.timezone_at(lat=latitude, lng=longitude) print("Detected Time Zone:", timezone_name) # Step 2. Convert UTC time to local time utc_time = datetime(2025, 7, 5, 12, 0, 0, tzinfo=ZoneInfo("UTC")) local_time = utc_time.astimezone(ZoneInfo(timezone_name)) print("Local Time:", local_time) |
Output:
1 2 | Detected Time Zone: America/Los_Angeles Local Time: 2025-07-05 05:00:00-07:00 |
This approach handles Daylight Saving Time (DST) and regional time zone rules precisely.
Option 2 — Estimate Local Time from Longitude (Fast Approximation)
If you’re processing large volumes of data (e.g., millions of satellite detections) and don’t need full time zone accuracy, you can approximate local solar time using longitude:
Every 15° of longitude corresponds to 1 hour of solar time difference from UTC.
Simple Formula:
1 | local_time ≈ utc_time + (longitude / 15 hours) |
This assumes the local solar noon occurs when the sun is directly overhead at that longitude — good enough for climatological studies or diurnal cycle analysis, but it won’t match local civil times exactly (no DST or political boundaries).
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import pandas as pd # Example DataFrame df = pd.DataFrame({ "longitude": [-120, 0, 45], "pixel_date_time": pd.to_datetime([ "2025-07-05T12:00:00Z", "2025-07-05T12:00:00Z", "2025-07-05T12:00:00Z" ], utc=True) }) # Approximate local time df["local_time"] = df["pixel_date_time"] + pd.to_timedelta(df["longitude"] / 15, unit="h") print(df) |
Output:
1 2 3 4 | longitude pixel_date_time local_time 0 -120 2025-07-05 12:00:00+00:00 2025-07-05 04:00:00+00:00 1 0 2025-07-05 12:00:00+00:00 2025-07-05 12:00:00+00:00 2 45 2025-07-05 12:00:00+00:00 2025-07-05 15:00:00+00:00 |
⚠️ This does not account for DST or irregular time zones (e.g., India UTC+5:30).
But it’s excellent for approximating solar local time in global-scale analyses such as FRP diurnal cycles.
Real Example — FRP Diurnal Cycle from UTC Time and Location
Let’s now compute the Fire Radiative Power (FRP) diurnal cycle from a dataset with columns:
| latitude | longitude | obs_date_time | frp |
|---|---|---|---|
| 34.1 | -118.3 | 2025-07-05T12:00:00Z | 55.2 |
| 34.1 | -118.3 | 2025-07-05T19:00:00Z | 72.4 |
| -23.6 | 133.9 | 2025-07-05T01:00:00Z | 80.5 |
| -23.6 | 133.9 | 2025-07-05T05:00:00Z | 120.3 |
Option 1 — Accurate Local Time (Using timezonefinder)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import pandas as pd from datetime import datetime from zoneinfo import ZoneInfo from timezonefinder import TimezoneFinder # Example dataset df = pd.DataFrame({ "latitude": [34.1, 34.1, -23.6, -23.6], "longitude": [-118.3, -118.3, 133.9, 133.9], "obs_date_time": [ "2025-07-05T12:00:00Z", "2025-07-05T19:00:00Z", "2025-07-05T01:00:00Z", "2025-07-05T05:00:00Z" ], "frp": [55.2, 72.4, 80.5, 120.3] }) df["obs_date_time"] = pd.to_datetime(df["obs_date_time"], utc=True) tf = TimezoneFinder() def get_local_time(row): tz_name = tf.timezone_at(lat=row["latitude"], lng=row["longitude"]) if tz_name is None: tz_name = "UTC" return row["obs_date_time"].astimezone(ZoneInfo(tz_name)) df["local_time"] = df.apply(get_local_time, axis=1) df["local_hour"] = df["local_time"].dt.hour frp_diurnal = df.groupby("local_hour")["frp"].mean().reset_index() print(frp_diurnal) |
Option 2 — Approximation (Longitude-Based Offset)
For large-scale or real-time processing:
1 2 3 4 5 6 7 8 | import pandas as pd df["obs_date_time"] = pd.to_datetime(df["obs_date_time"], utc=True) df["local_time"] = df["obs_date_time"] + pd.to_timedelta(df["longitude"] / 15, unit="h") df["local_hour"] = df["local_time"].dt.hour frp_diurnal = df.groupby("local_hour")["frp"].mean().reset_index() print(frp_diurnal) |
Visualize FRP Diurnal Cycle
1 2 3 4 5 6 7 8 9 | import matplotlib.pyplot as plt plt.figure(figsize=(8, 4)) plt.plot(frp_diurnal["local_hour"], frp_diurnal["frp"], marker="o") plt.title("🔥 FRP Diurnal Cycle by Local Hour") plt.xlabel("Local Hour") plt.ylabel("Mean FRP (MW)") plt.grid(True) plt.show() |
Summary
| Approach | Method | Accuracy | Speed | Handles DST | Use Case |
|---|---|---|---|---|---|
timezonefinder + ZoneInfo |
Real time zone lookup | ✅ High | 🐢 Slower | ✅ Yes | Research & reporting |
| Longitude / 15 | Approximation | ⚠️ Medium | ⚡ Very fast | ❌ No | Large-scale diurnal studies |
References
| Links | Site |
|---|---|
Python datetime — Date and Time Objects |
Official Python documentation |
Python zoneinfo — IANA Time Zone Support |
Official Python documentation |
pandas.to_datetime() |
pandas API reference |
pandas.Series.dt.tz_convert() |
pandas API reference |
timezonefinder on PyPI |
Python Package Index (PyPI) |
timezonefinder Documentation |
Official documentation and usage examples |
| IANA Time Zone Database | Source of global time zone data used by zoneinfo |

