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

error in Time transform of 9999-12-31 #1159

Open
funicia opened this issue Aug 4, 2023 · 4 comments
Open

error in Time transform of 9999-12-31 #1159

funicia opened this issue Aug 4, 2023 · 4 comments
Labels

Comments

@funicia
Copy link

funicia commented Aug 4, 2023

Issue Description

i want to change '9999-12-31' to timestamp, and also in anather scene, i need change the timestamp(253402214400) to datetime.
but I got confused when I test this :

 dt2=arrow.get('9999-12-31')
 dt2.timestamp()

then get:

253402214400.0

and change it to datetime:
arrow.get(253402214400.0)

but get :

<Arrow [1978-01-11T21:30:14.400000+00:00]>

this code should get result like of : "9999-12-31 "

So, It is a bug , or my code is not correct!

System Info

  • 🖥 OS name and version: winodws11 and wsl ubuntu
  • 🐍 Python version: python3.7
  • 🏹 Arrow version: 1.2.3
@funicia funicia added the bug label Aug 4, 2023
@yiransii
Copy link
Contributor

yiransii commented Aug 4, 2023

I am unsure what the intended behavior would be here as 9999 is an odd input year. I can take on this - but could someone verify the intended behavior here?

@funicia
Copy link
Author

funicia commented Aug 4, 2023

some system stored the timestamp of 9999 to mark the data will never be expired, and the passed date like 2022 means has expired 。And the BI System need to show as datetime like of 9999。so i need find a way to resolve it.

On linux, the datetime.fromtimestamp can do this correctly, but , this function will raise error on windows when the datetime over 2038. So I am finding a way to hanle this problem both run well on Linux and Window. At least, the arrow can transform 9999 to timestamp correctly.

By the way, the arrow can only tranform timestamp of 2999-12-31 to the correct datetime, timestamp of 3001 will be 1971 either.

@sanskark
Copy link

sanskark commented Oct 1, 2023

@funicia Have you solved this bug? If so can you share how you done it

@tonyk232
Copy link

tonyk232 commented Apr 6, 2024

@yiransii Just in case you would still want to work on this one, the root cause for this is not year 9999 being invalid, but there's a rather obscure bug.

When you construct an Arrow object from a timestamp, it calls normalize_timestamp from util.py. The first few lines:

def normalize_timestamp(timestamp: float) -> float:
    """Normalize millisecond and microsecond timestamps into normal timestamps."""
    if timestamp > MAX_TIMESTAMP:
        if timestamp < MAX_TIMESTAMP_MS:
            timestamp /= 1000

MAX_TIMESTAMP is from constants.py:

try:
    # Get max timestamp. Works on POSIX-based systems like Linux and macOS,
    # but will trigger an OverflowError, ValueError, or OSError on Windows
    _MAX_TIMESTAMP = datetime.max.timestamp()
except (OverflowError, ValueError, OSError):  # pragma: no cover
    # Fallback for Windows and 32-bit systems if initial max timestamp call fails

What happens is that despite the comment, datetime.max.timestamp() only works on Linux if the local timezone is UTC or UTC-xx:

$ TZ=UTC python3
>>> from datetime import datetime
>>> datetime.max.timestamp()
253402300800.0

$ TZ=Europe/Berlin python3
>>> from datetime import datetime
>>> datetime.max.timestamp()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: year 10000 is out of range

Going back to normalize_timestamp, this means 253402214400 gets divided by 1000, which then matches the original bug report:

>>> arrow.get(253402214.4)
<Arrow [1978-01-11T21:30:14.400000+00:00]>

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

No branches or pull requests

4 participants