user3426438
user3426438

Reputation:

Error22 - invalid argument on a simple datetime conversion?

I'm a bit stumped by this I'm not going to lie but I'm currently having an invalid argument error thrown at me every time I try to convert a 13 character epoch to a readable date. This works without issue earlier on within the script, the part is erroring out on is the following:

print (msgTime)
messageTime=datetime.utcfromtimestamp(msgTime)

The value of 'msgTime' is gathered from an SQL Database and is returned as : 1540406475702

The exact error I get is:

Traceback (most recent call last):
  File "script.py", line 380, in <module>
    messageTime=datetime.utcfromtimestamp(msgTime)
OSError: [Errno 22] Invalid argument

I know Its likely something silly or small but I just can't see what is up, does anyone have any ideas?

Upvotes: 0

Views: 496

Answers (2)

ykoavlil
ykoavlil

Reputation: 186

If you have a chance that the value can come in both seconds and milliseconds I would recommend doing something like this:

from datetime import datetime


def check(time_stamp):
    match len(str(time_stamp)):
        case 10:
            print(time_stamp, 'seconds')
            print(datetime.fromtimestamp(time_stamp))
        case 13:
            print(time_stamp, 'milliseconds')
            print(datetime.fromtimestamp(time_stamp / 1000))

check(1725062400000)
check(1725062400)

Result:

1725062400000 milliseconds

2024-08-31 05:00:00

1725062400 seconds

2024-08-31 05:00:00

Upvotes: 0

Chris Doyle
Chris Doyle

Reputation: 12155

The eopch time wont include milliseconds so currently would only be 10 digits long. Yours is 13, you can get rid of the extra milliseconds by floor dividing by 1000

from datetime import datetime
msgTime = 1540406475702
print (msgTime)
messageTime=datetime.utcfromtimestamp(msgTime//1000)
print(messageTime)

OUTPUT

1540406475702
2018-10-24 18:41:15

UPDATE

Having looked at the source code of datetime and how it implements fromtimestamp if you wanted to pass milliseconds you can do it by passing the values as a float where the 3 digits after the decimal point represents the milliseconds. Below is an extract from the datetime module

@classmethod
def _fromtimestamp(cls, t, utc, tz):
    """Construct a datetime from a POSIX timestamp (like time.time()).
    A timezone info object may be passed in as well.
    """
    frac, t = _math.modf(t)
    us = round(frac * 1e6)
    if us >= 1000000:
        t += 1
        us -= 1000000
    elif us < 0:
        t -= 1
        us += 1000000

    converter = _time.gmtime if utc else _time.localtime
    y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
    ss = min(ss, 59)    # clamp out leap seconds if the platform has them
    result = cls(y, m, d, hh, mm, ss, us, tz)

So you can pass milli / micro seconds if you pass them as the digits after the decimal place. Is it possible when this was working before that your epoch was second followed by a decimal place then the milliseconds?

from datetime import datetime
msgTime = 1540406475.702
print (msgTime)
messageTime=datetime.utcfromtimestamp(msgTime)
print(messageTime)

OUTPUT

1540406475.702
2018-10-24 18:41:15.702000

Upvotes: 1

Related Questions