Skip to main content

How to Solve "ValueError: year is out of range" with datetime.fromtimestamp() in Python

The ValueError: year is out of range error occurs when you use datetime.fromtimestamp() with a timestamp that's too large (or sometimes too small, though this is rarer in practice). This usually happens because the timestamp is in milliseconds instead of the expected seconds.

This guide explains the cause and provides reliable solutions.

Understanding the Error: Seconds vs. Milliseconds

The datetime.fromtimestamp() method expects a timestamp in seconds since the Unix epoch (January 1, 1970, 00:00:00 UTC). However, many systems and APIs provide timestamps in milliseconds. If you pass a millisecond timestamp directly to fromtimestamp(), you'll get a ValueError because the year will be far in the future (or past, for very small values).

Incorrect code (raises ValueError):

This example throws a ValueError because datetime.fromtimestamp() expects the timestamp to be in seconds.

from datetime import datetime

timestamp_in_ms = 1744618085225 # This is in milliseconds

d = datetime.fromtimestamp(timestamp_in_ms) # ValueError: year 57254 is out of range

Output:

Traceback (most recent call last):
File "main.py", line 4, in <module>
d = datetime.fromtimestamp(timestamp_in_ms) # milliseconds to seconds
ValueError: year 57254 is out of range

Solution 1: Dividing by 1000 (Most Common)

The most straightforward solution is to divide the millisecond timestamp by 1000 (or 1000.0) to convert it to seconds before passing it to fromtimestamp():

from datetime import datetime

timestamp_in_ms = 1744618085225
d = datetime.fromtimestamp(timestamp_in_ms / 1000) # milliseconds to seconds

print(d) # Output: 2025-04-14 08:08:05.225000 (UTC time - your local time will differ)
  • timestamp_in_ms / 1000: This converts the timestamp from milliseconds to seconds. Using /1000 will work, however it is better to use /1000.0 to ensure the division is performed as a float division.

Solution 2: Checking Timestamp Length (More Robust)

A more robust solution is to check the length of the timestamp string. This avoids accidental division when the timestamp is already in seconds:

from datetime import datetime

def datetime_from_ts(timestamp):
timestamp_str = str(timestamp)
if len(timestamp_str) == 13: # Likely milliseconds
return datetime.fromtimestamp(timestamp / 1000)
elif len(timestamp_str) == 10: # Likely seconds
return datetime.fromtimestamp(timestamp)
else:
raise ValueError("Invalid timestamp format") # Or handle differently

timestamp_ms = 1744618085225
timestamp_s = 1744618085

print(datetime_from_ts(timestamp_ms)) # Output: 2025-04-14 08:08:05.225000 (UTC)
print(datetime_from_ts(timestamp_s)) # Output: 2025-04-14 08:08:05 (UTC)

# Example of invalid format:
try:
print(datetime_from_ts(1234))
except ValueError as e:
print(e) # Output: Invalid timestamp format
  • This function checks the length of the timestamp string. A timestamp in seconds is typically 10 digits long. A timestamp in milliseconds is 13 digits long.
  • This is more robust because it explicitly handles both cases, and avoids accidentally dividing a seconds-based timestamp by 1000.
  • The added else and raise statement makes the code even more robust, as it throws an error when unexpected input is provided.

Handling Potential ValueError with try-except

Even with the length check, it's still possible to get a ValueError if the timestamp represents a date outside the range supported by datetime. Wrap the conversion in a try-except block for complete robustness:

from datetime import datetime

timestamp_in_ms = 1744618085225

try:
d = datetime.fromtimestamp(timestamp_in_ms / 1000)
print(d)
except ValueError:
print('Invalid timestamp value')
d = datetime.today() # provide some default value in case of exception
  • The try block attempts to convert the timestamp.
  • The except ValueError block handles the potential error, providing a fallback or error message.