Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

arrow.get(datetime.now()).humanize() == "6 hours ago" #944

Closed
zachriggle opened this issue Mar 10, 2021 · 3 comments · Fixed by #968
Closed

arrow.get(datetime.now()).humanize() == "6 hours ago" #944

zachriggle opened this issue Mar 10, 2021 · 3 comments · Fixed by #968
Labels

Comments

@zachriggle
Copy link

Issue Description

It looks like arrow is doing something weird timezone information when operating datetime objects, including datetime objects returned by e.g. dateparser.parse('now').

What is the appropriate incantation to get arrow and datetime to agree? I've managed to do it in one of my projects by using epochseconds, but would prefer to keep my dates as either datetime or arrow object representations.

I am in central standard time, so the "6 hours ago" seems to reflect my TZ offset from UTC, but even providing a ..., tzinfo= does not appear to do the correct thing.

Overall, the mixture of simple things that don't work is overwhelming, and there should maybe be some examples in the documentation for how to do this right (e.g. setting tzinfo on the datetime object makes arrow's object correct, but setting tzinfo on the arrow object does not).

date(1) vs datetime

As best I can tell, datetime.now() is correct, and lacks a specific timezone.

>>> import datetime, subprocess
>>> datetime.datetime.now()
datetime.datetime(2021, 3, 9, 19, 55, 36, 539945)
>>> subprocess.check_output('date', text=True)
'Tue Mar  9 19:55:39 CST 2021\n'

datetime vs arrow

This jives with the 6 hour time difference from UTC, but why does it say "6 hours ago"? Neither arrow nor datetime were provided with a timezone, so this seems odd.

>>> import arrow, datetime
>>> arrow.get(datetime.datetime.now()).humanize()
'6 hours ago'

datetime with tzinfo

This happens even with a custom timezone, unless the timezone is specified on the datetime object.

>>> import arrow, dateparser, dateutil, datetime
>>> tz = dateutil.tz.tzlocal()

# With the local timezone on arrow.get() does NOT work
>>> arrow.get(datetime.datetime.now(), tzinfo=tz).humanize()
'6 hours ago'

# With the local timezone on datetime.now() DOES work
>>> arrow.get(datetime.datetime.now(tz=tz)).humanize()
'just now'

# With a custom timezone (set to be GMT-6)
>>> mytz = dateutil.tz.tzoffset('MyTZ', datetime.timedelta(hours=6))
>>> mytz
tzoffset('MyTZ', 21600)
>>> arrow.get(datetime.datetime.now(), tzinfo=mytz).humanize()
'6 hours ago'

dateparser

Per the documentation:

dateparser relies on following libraries in some ways:
• tzlocal to reliably get local timezone.

However, this doesn't seem to work correctly either.

>>> import arrow, dateparser
>>> arrow.get(dateparser.parse('now')).humanize()
'6 hours ago'

dateparser with tzinfo

This happens regardless of whether tzinfo is specified.

>>> import arrow, dateparser, dateutil
>>> tz = dateutil.tz.tzlocal()
>>> tz
tzlocal()
>>> arrow.get(dateparser.parse('now'), tzinfo=tz).humanize()
'6 hours ago'

Unix Timestamps

It looks like there's an issue with timestamps as well. If I pass the timestamp directly to arrow.get(), it returns the correct value.

>>> dt = datetime.datetime.fromtimestamp(1615341484)
>>> dt
datetime.datetime(2021, 3, 9, 19, 58, 4)
>>> !date
Tue Mar  9 20:02:38 CST 2021

# We can see that arrow is correct in its humanize()
>>> arrow.get(1615341484).humanize()
'4 minutes ago'

# However, using the datetime derived from the timestamp exhibits the same issue
>>> arrow.get(dt).humanize()
'6 hours ago'

System Info

$ sw_vers
ProductName:	macOS
ProductVersion:	11.3
BuildVersion:	20E5172h
$ python3 --version
Python 3.8.2
$ python3 -m pip freeze | grep arrow
arrow==1.0.3
@zachriggle zachriggle added the bug label Mar 10, 2021
@systemcatch
Copy link
Collaborator

systemcatch commented Mar 14, 2021

Hey @zachriggle there definitely looks to be some weirdness going on with the tzinfo setting here. I will investigate this further.

Two other points, Arrow objects are never naive, they default to UTC if no tzinfo is provided. Also arrow.get(dateparser.parse('now')) is not officially supported but will probably work.

@systemcatch
Copy link
Collaborator

The problem is that the tzinfo supplied to arrow.get() is being ignored in certain cases, for example:

(arrow) chris@Z490:~/arrow$ python
Python 3.9.1 (default, Feb 17 2021, 16:56:42) 
[GCC 10.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import arrow
>>> import datetime
>>> arrow.get(datetime.datetime.now(), tzinfo="America/Chicago")
<Arrow [2021-03-17T21:33:42.404027+00:00]>
>>> arrow.get(datetime.datetime.now(), tzinfo="America/Chicago").tzinfo
tzutc()

It defaults to UTC which causes strange results.

The bug is in https://github.com/arrow-py/arrow/blob/master/arrow/factory.py#L241 where the tzinfo kwarg is dropped.

@zachriggle
Copy link
Author

zachriggle commented Mar 18, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants