While working on a project where I had to process server logs with timestamps stored as epoch time. The challenge was converting these Unix timestamps to human-readable datetime formats for analysis.
If you’ve ever dealt with APIs, databases, or log files, you’ve probably encountered epoch time. It’s everywhere in the tech world, but it’s not exactly user-friendly when you’re trying to understand when something happened.
In this article, I’ll show you five different methods to convert epoch time to datetime in Python. Each method has its use case, and I’ll explain when to use which approach based on my experience.
Epoch Time
Epoch time (also called Unix timestamp) represents the number of seconds that have elapsed since January 1, 1970, 00:00:00 UTC. This date is known as the Unix epoch.
For example, the epoch time 1672531200 represents January 1, 2023, 00:00:00 UTC. It’s a standardized way to represent time across different systems and programming languages.
Methods to Convert Epoch Time to Datetime in Python
Let me explain to you the efficient methods to convert epoch time to datetime in Python.
1 – Use datetime.fromtimestamp()
The easy way to convert epoch time to a datetime is using Python’s built-in datetime.fromtimestamp() method.
Here’s a practical example using a timestamp from a typical web server log:
from datetime import datetime
# Example: Converting a server log timestamp
epoch_time = 1672531200 # January 1, 2023, 00:00:00 UTC
datetime_obj = datetime.fromtimestamp(epoch_time)
print(f"Epoch time: {epoch_time}")
print(f"Datetime: {datetime_obj}")
print(f"Formatted: {datetime_obj.strftime('%Y-%m-%d %H:%M:%S')}")Output:
Epoch time: 1672531200
Datetime: 2023-01-01 00:00:00
Formatted: 2023-01-01 00:00:00You can refer to the screenshot below to see the output.

This method automatically converts to your local timezone. If you’re in EST, the result will show EST time, not UTC.
2 – Use datetime.utcfromtimestamp() for UTC Time
When working with international applications or when you need precise UTC, use datetime.utcfromtimestamp() method in Python.
from datetime import datetime
# Example: Processing timestamps from a global API
api_timestamps = [1672531200, 1672534800, 1672538400] # New Year's Day 2023 hourly data
print("API Response Timestamps (UTC):")
for i, timestamp in enumerate(api_timestamps):
utc_datetime = datetime.utcfromtimestamp(timestamp)
print(f"Entry {i+1}: {utc_datetime} UTC")
print(f" Formatted: {utc_datetime.strftime('%B %d, %Y at %I:%M %p')} UTC")
print()Output:
API Response Timestamps (UTC):
Entry 1: 2023-01-01 00:00:00 UTC
Formatted: January 01, 2023 at 12:00 AM UTC
Entry 2: 2023-01-01 01:00:00 UTC
Formatted: January 01, 2023 at 01:00 AM UTC
Entry 3: 2023-01-01 02:00:00 UTC
Formatted: January 01, 2023 at 02:00 AM UTCYou can refer to the screenshot below to see the output.

This method is crucial when you’re dealing with data from multiple time zones or when storing data in databases.
3 – Use timezone-aware datetime with pytz
For production applications, I always recommend using timezone-aware datetime objects. This requires the pytz library for better timezone handling.
First, install pytz if you haven’t already:
pip install pytzHere’s how to convert epoch time to different US time zones:
from datetime import datetime
import pytz
def convert_epoch_to_timezone(epoch_time, timezone_str):
"""Convert epoch time to specified timezone"""
utc_datetime = datetime.utcfromtimestamp(epoch_time)
utc_datetime = pytz.utc.localize(utc_datetime)
target_timezone = pytz.timezone(timezone_str)
return utc_datetime.astimezone(target_timezone)
# Example: Converting trading session timestamps
trading_start_epoch = 1672934400 # January 5, 2023 (typical trading day)
# Convert to different US time zones
timezones = [
'US/Eastern', # New York Stock Exchange
'US/Central', # Chicago
'US/Mountain', # Denver
'US/Pacific' # NASDAQ (California)
]
print(f"Trading Session Start (Epoch: {trading_start_epoch}):")
for tz in timezones:
tz_datetime = convert_epoch_to_timezone(trading_start_epoch, tz)
print(f" {tz}: {tz_datetime.strftime('%Y-%m-%d %I:%M:%S %p %Z')}")Output:
Trading Session Start (Epoch: 1672934400):
US/Eastern: 2023-01-05 02:00:00 PM EST
US/Central: 2023-01-05 01:00:00 PM CST
US/Mountain: 2023-01-05 12:00:00 PM MST
US/Pacific: 2023-01-05 11:00:00 AM PSTYou can refer to the screenshot below to see the output.

This approach handles daylight saving time automatically, which is essential for financial or business applications.
4 – Use pandas for Large Datasets
When working with large datasets containing multiple epoch timestamps, pandas provides an efficient solution.
import pandas as pd
from datetime import datetime
# Example: Processing e-commerce transaction data
transaction_data = {
'transaction_id': ['TXN001', 'TXN002', 'TXN003', 'TXN004', 'TXN005'],
'epoch_timestamp': [1672531200, 1672534800, 1672538400, 1672542000, 1672545600],
'amount': [149.99, 79.50, 299.00, 45.25, 199.99],
'customer_id': ['CUST001', 'CUST002', 'CUST003', 'CUST004', 'CUST005']
}
# Create DataFrame
df = pd.DataFrame(transaction_data)
# Convert epoch timestamps to datetime
df['transaction_datetime'] = pd.to_datetime(df['epoch_timestamp'], unit='s')
# Format for better readability
df['formatted_date'] = df['transaction_datetime'].dt.strftime('%B %d, %Y at %I:%M %p')
# Display results
print("E-commerce Transaction Analysis:")
print(df[['transaction_id', 'formatted_date', 'amount']].to_string(index=False))
# Additional analysis
print(f"\nTotal transactions: {len(df)}")
print(f"Date range: {df['transaction_datetime'].min().date()} to {df['transaction_datetime'].max().date()}")
print(f"Total revenue: ${df['amount'].sum():.2f}")Output:
E-commerce Transaction Analysis:
transaction_id formatted_date amount
TXN001 January 01, 2023 at 12:00 AM 149.99
TXN002 January 01, 2023 at 01:00 AM 79.50
TXN003 January 01, 2023 at 02:00 AM 299.00
TXN004 January 01, 2023 at 03:00 AM 45.25
TXN005 January 01, 2023 at 04:00 AM 199.99
Total transactions: 5
Date range: 2023-01-01 to 2023-01-01
Total revenue: $773.73You can refer to the screenshot below to see the output.

This method is particularly useful when you’re analyzing time-series data or working with CSV files containing epoch timestamps.
5 – Handle Millisecond Epoch Time
Sometimes you’ll encounter epoch timestamps in milliseconds instead of seconds. This is common with JavaScript APIs or certain databases.
from datetime import datetime
import pandas as pd
def convert_millisecond_epoch(ms_epoch):
"""Convert millisecond epoch to datetime"""
return datetime.fromtimestamp(ms_epoch / 1000)
# Example: Processing mobile app analytics data
app_events = [
{'event': 'app_open', 'timestamp_ms': 1672531200000},
{'event': 'user_login', 'timestamp_ms': 1672531260000},
{'event': 'purchase_view', 'timestamp_ms': 1672531320000},
{'event': 'purchase_complete', 'timestamp_ms': 1672531380000},
{'event': 'app_close', 'timestamp_ms': 1672531440000}
]
print("Mobile App User Journey:")
for event in app_events:
dt = convert_millisecond_epoch(event['timestamp_ms'])
formatted_time = dt.strftime('%I:%M:%S %p')
print(f" {formatted_time} - {event['event'].replace('_', ' ').title()}")
# Using pandas for millisecond conversion
df = pd.DataFrame(app_events)
df['datetime'] = pd.to_datetime(df['timestamp_ms'], unit='ms')
df['time_spent'] = df['datetime'].diff().dt.total_seconds().fillna(0)
print(f"\nSession Analysis:")
print(f"Total session time: {df['time_spent'].sum()} seconds")
print(f"Time to purchase: {df[df['event'] == 'purchase_complete']['time_spent'].sum()} seconds from login")Output:
Mobile App User Journey:
12:00:00 AM - App Open
12:01:00 AM - User Login
12:02:00 AM - Purchase View
12:03:00 AM - Purchase Complete
12:04:00 AM - App Close
Session Analysis:
Total session time: 240.0 seconds
Time to purchase: 60.0 seconds from loginThis example demonstrates converting millisecond-based epoch timestamps into human-readable datetimes and analyzing event durations.
Real-World Application Example
Here’s a complete example that demonstrates how I recently used epoch time conversion in a financial trading application:
import pandas as pd
from datetime import datetime
import pytz
import json
class TradingDataProcessor:
"""Process trading data with epoch timestamp conversion"""
def __init__(self, timezone='US/Eastern'):
self.timezone = pytz.timezone(timezone)
def process_trade_data(self, raw_data):
"""Process raw trading data from API"""
# Convert to DataFrame
df = pd.DataFrame(raw_data)
# Convert epoch timestamps
df['trade_datetime'] = pd.to_datetime(df['timestamp'], unit='s')
df['trade_datetime'] = df['trade_datetime'].dt.tz_localize('UTC').dt.tz_convert(self.timezone)
# Add market session info
df['market_session'] = df['trade_datetime'].apply(self._get_market_session)
df['trading_day'] = df['trade_datetime'].dt.date
# Format for display
df['formatted_time'] = df['trade_datetime'].dt.strftime('%Y-%m-%d %I:%M:%S %p %Z')
return df
def _get_market_session(self, dt):
"""Determine market session based on time"""
hour = dt.hour
if 4 <= hour < 9:
return "Pre-Market"
elif 9 <= hour < 16:
return "Regular Hours"
elif 16 <= hour < 20:
return "After Hours"
else:
return "Closed"
def generate_summary(self, df):
"""Generate trading summary"""
summary = {
'total_trades': len(df),
'trading_days': df['trading_day'].nunique(),
'sessions': df['market_session'].value_counts().to_dict(),
'volume': df['quantity'].sum(),
'value': (df['price'] * df['quantity']).sum(),
'time_range': {
'start': df['trade_datetime'].min().strftime('%Y-%m-%d %I:%M:%S %p %Z'),
'end': df['trade_datetime'].max().strftime('%Y-%m-%d %I:%M:%S %p %Z')
}
}
return summary
# Example usage with sample trading data
sample_trades = [
{'timestamp': 1672934400, 'symbol': 'AAPL', 'price': 130.15, 'quantity': 100, 'side': 'BUY'},
{'timestamp': 1672938000, 'symbol': 'GOOGL', 'price': 89.25, 'quantity': 50, 'side': 'BUY'},
{'timestamp': 1672941600, 'symbol': 'MSFT', 'price': 239.50, 'quantity': 75, 'side': 'SELL'},
{'timestamp': 1672945200, 'symbol': 'AAPL', 'price': 131.20, 'quantity': 200, 'side': 'BUY'},
{'timestamp': 1672948800, 'symbol': 'TSLA', 'price': 157.90, 'quantity': 25, 'side': 'BUY'},
]
# Process the data
processor = TradingDataProcessor()
trades_df = processor.process_trade_data(sample_trades)
print("Trading Data Analysis")
print("=" * 50)
print(trades_df[['symbol', 'formatted_time', 'market_session', 'price', 'quantity', 'side']].to_string(index=False))
# Generate summary
summary = processor.generate_summary(trades_df)
print(f"\nTrading Summary:")
print(f"Total Trades: {summary['total_trades']}")
print(f"Trading Days: {summary['trading_days']}")
print(f"Total Volume: {summary['volume']:,} shares")
print(f"Total Value: ${summary['value']:,.2f}")
print(f"Time Range: {summary['time_range']['start']} to {summary['time_range']['end']}")
print(f"\nSession Breakdown:")
for session, count in summary['sessions'].items():
print(f" {session}: {count} trades")
Output:
Trading Data Analysis
==================================================
symbol formatted_time market_session price quantity side
AAPL 2023-01-05 02:00:00 PM EST Regular Hours 130.15 100 BUY
GOOGL 2023-01-05 03:00:00 PM EST Regular Hours 89.25 50 BUY
MSFT 2023-01-05 04:00:00 PM EST After Hours 239.50 75 SELL
AAPL 2023-01-05 05:00:00 PM EST After Hours 131.20 200 BUY
TSLA 2023-01-05 06:00:00 PM EST After Hours 157.90 25 BUY
Trading Summary:
Total Trades: 5
Trading Days: 1
Total Volume: 450 shares
Total Value: $67,650.00
Time Range: 2023-01-05 02:00:00 PM EST to 2023-01-05 06:00:00 PM EST
Session Breakdown:
Regular Hours: 2 trades
After Hours: 3 tradesThis example showcases how epoch timestamps can be transformed into readable trading insights with detailed session-based summaries.
Conclusion
The key is understanding your data source and choosing the right method for your specific use case. Whether you’re processing server logs, analyzing trading data, or building APIs, these techniques will help you handle epoch timestamps confidently and efficiently.
Remember to always validate your timestamps, handle errors gracefully, and be explicit about time zones. Your future self (and your users) will thank you for taking the time to implement robust timestamp conversion from the start.
You may also read:
- NameError: name is not defined in Python
- Fix SyntaxError: invalid character in identifier in Python
- Remove Unicode Characters in Python
- Exit an If Statement in Python

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.