45

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.

FObersteiner
  • 22,500
  • 8
  • 42
  • 72
Jon Hartnett
  • 451
  • 1
  • 5
  • 4
  • 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 .. – Mohideen bin Mohammed May 28 '16 at 07:10
  • 3
    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. – Jon Hartnett May 28 '16 at 16:43
  • 1
    same issue for me was a [bug in python 3.6](https://stackoverflow.com/questions/42413138/python-3-6-datetime-fromtimestamp-throws-error-when-given-0) – dashesy Aug 15 '17 at 21:20

6 Answers6

69

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.

Josh
  • 2,658
  • 31
  • 36
  • 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. – Matt Apr 23 '18 at 01:47
24

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

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

EMAI
  • 694
  • 6
  • 14
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
wim
  • 338,267
  • 99
  • 616
  • 750
  • 4
    I faced this same problem on Windows 10 (and python 3.6.5), when timestamp was equal 0. – Edward Weinert Jul 04 '18 at 13:01
  • 3
    Just have to divide the timestamp by 1000. I tested over Windows 10 and Linux, both work and give the right answer. – palmtreesnative Apr 11 '19 at 18:44
  • Me as well @EdwardWeinert did you figure it out ? – Overdrivr May 25 '20 at 12:56
  • 1
    This is the correct answer for OP's case with a 1969 date – Pythonic Jan 31 '21 at 10:20
  • 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? – Primoz Feb 03 '21 at 15:12
  • 1
    @Primoz 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](https://en.wikipedia.org/wiki/UTC%2B01:00) timezone and you've used a localtime. – wim Feb 03 '21 at 16:03
  • 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. – Primoz Feb 03 '21 at 16:13
  • @Primoz Ok, that explains it. Ni za kaj! – wim Feb 03 '21 at 16:18
12

@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)
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Tammi
  • 421
  • 7
  • 12
  • 1
    `Running on Python ver.3.9.1 on Windows 10` `Smallest accepted Unix timestamp by Windows: '1' (1970-01-01 01:00:01)` – Polluks Mar 16 '21 at 14:36
0

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
FObersteiner
  • 22,500
  • 8
  • 42
  • 72
-9

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

cs95
  • 379,657
  • 97
  • 704
  • 746
sorin
  • 161,544
  • 178
  • 535
  • 806