Python fromtimestamp OSError
Asked Answered
A

6

47

For some reason when constructing datetimes using fromtimestamp, I get a

"OSError [Errno22] Invalid Argument"

when I use negative times less than -43200 (-12hrs). I am on Win7 64-bit and python 3.5.1. Here's code that produces the error.

>>> import datetime
>>> import pytz
>>> datetime.datetime.fromtimestamp(-43200, pytz.utc)
datetime.datetime(1969, 12, 31, 12, 0, tzinfo=<UTC>)
>>> datetime.datetime.fromtimestamp(-43201, pytz.utc)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

The sample uses pytz to simplify timezone information, but the error also occurs without it.

Actium answered 28/5, 2016 at 3:44 Comment(3)
Here your two lines are similar first one print the value second throw error . so i think there is some indent error or something else.. so try to catch exception using except OSError as e: then put your error ..Wardlaw
It's not a syntax error. This example is intentionally simple to show the minimum required to cause the error. I initially found the limit in a for loop.Actium
same issue for me was a bug in python 3.6Reynaldoreynard
D
72

If you get this error and you're not using an obviously wrong timestamp, check your units.

fromtimestamp expects a timestamp in seconds, whereas it's quite common to get timetstamps in milliseconds (e.g. I found this when trying to parse a timestamp produced from Moment.js in a calendar widget).

Take the timestamp 1523443804214 - it's 11th April 2018, about 15 minutes before I made this post. According to Epoch Converter, no problem, but note: "Assuming that this timestamp is in milliseconds:".

In Python this returns an OSError:

In [15]: datetime.fromtimestamp(1523443804214.0)
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-15-0c8efd251031> in <module>()
----> 1 datetime.fromtimestamp(1523443804214.0)

However if we divide by a thousand:

In [17]: datetime.fromtimestamp(1523443804.214)
Out[17]: datetime.datetime(2018, 4, 11, 11, 50, 4, 214000)

the result is what we expect.

Dostie answered 11/4, 2018 at 11:7 Comment(1)
I needed to see this spelled out to me. This is the exact reason I was getting my error. I was using JSON PowerShell dates in Python and they are using milliseconds.Bluster
M
27

To solve this problem, divide the timestamp value by 1000.

In Windows, the timestamp number is multiplied by a factor of a 1000.

Maisey answered 31/1, 2019 at 12:6 Comment(0)
V
20

If the timestamp is out of the range of values supported by the platform C localtime() or gmtime() functions, datetime.fromtimestamp() may raise an exception like you're seeing.

On Windows platform, this range can sometimes be restricted to years in 1970 through 2038. I have never seen this problem on a Linux system.

If you have a negative timestamp t on Windows and are encountering this error, here is a workaround:

from datetime import datetime, timedelta
datetime.fromtimestamp(0) + timedelta(seconds=t)     # localtime
datetime.utcfromtimestamp(0) + timedelta(seconds=t)  # utc
Vociferate answered 30/12, 2016 at 17:39 Comment(8)
I faced this same problem on Windows 10 (and python 3.6.5), when timestamp was equal 0.Euromarket
Just have to divide the timestamp by 1000. I tested over Windows 10 and Linux, both work and give the right answer.Nevernever
Me as well @EdwardWeinert did you figure it out ?Palmerpalmerston
This is the correct answer for OP's case with a 1969 dateAgateware
I am facing the same problem with e.g. .datetime.fromtimestamp(-662688000) which is datetime.datetime(1949, 1, 1, 1, 0) on Windows and it works correctly on macOS and Linux. Is there any workaround for this issue?Hannis
@Hannis Added a possible workaround to the answer. I think the correct result is datetime.datetime(1949, 1, 1, 0, 0), not datetime.datetime(1949, 1, 1, 1, 0), isn't it? Perhaps your machine is configured in a UTC+1 timezone and you've used a localtime.Vociferate
Thank you. Yes you are correct it is datetime.datetime(1949, 1, 1, 0, 0). I copied the result from the console and am in UTC+1 so this is the reason for a different result.Hannis
@Hannis Ok, that explains it. Ni za kaj!Vociferate
R
13

@wim's answer is correct, but anyone else arriving here might be interested in testing it (adjust range if you wish):

import datetime
import platform
print(
    "Running on Python ver.{} on {} {}\n" \
    .format(
        platform.python_version(),
        platform.system(),
        platform.release()
        )
)
for timestamp in range(1, 100000000):
    try:
        dt = datetime.datetime.fromtimestamp(timestamp)
    except:
        pass
    else:
        break
print(
    "Smallest accepted Unix timestamp by {}: '{}' ({})" \
    .format(platform.system(), timestamp, dt)
)

What I got was:

A:\src\X.utilities>test.py
Running on Python ver.3.6.1 on Windows 7

Smallest accepted Unix timestamp by Windows: '86400' (1970-01-02 02:00:00)
Resistless answered 28/7, 2017 at 11:20 Comment(1)
Running on Python ver.3.9.1 on Windows 10 Smallest accepted Unix timestamp by Windows: '1' (1970-01-01 01:00:01)Aerostatic
D
1

Late contribution, but I think it's important to emphasize that this is 1) platform-specific and 2) that there might be a platform-agnostic solution.

quoting from the docs:

fromtimestamp() may raise OverflowError, if the timestamp is out of the range of values supported by the platform C localtime() or gmtime() functions, and OSError on localtime() or gmtime() failure. It’s common for this to be restricted to years in 1970 through 2038.

"restricted to years in 1970 through 2038" basically means just the positive range of a signed 32 bit integer representing seconds. Note that this is not a general limitation of Unix time. Nevertheless, negative numbers can fail, e.g. in the following code, Python 3.10 on Windows 10:

from datetime import datetime
print(datetime.fromtimestamp(-86400)) # 1969-12-31

>>>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

The platform-agnostic alternative would be

from datetime import datetime, timedelta
print(datetime(1970,1,1)+timedelta(seconds=-86400))

>>>
1969-12-31 00:00:00
Dentiform answered 27/3, 2023 at 7:16 Comment(0)
H
-9

A timestamp is the number of seconds since January 1st 1970, and this is always a positive value.

Hight answered 30/5, 2016 at 18:35 Comment(2)
–1 for the unnecessary condescension. Actually, using fromtimestamp with a negative number usually works fine, but it's platform-dependent.Vociferate
@Vociferate –1 for using –1 instead of -1Bledsoe

© 2022 - 2024 — McMap. All rights reserved.