Skip to content

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

@zachriggle

Description

@zachriggle

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions