-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
datetime.timestamp() doesn't have enough precision to represent datetime.max #91012
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
Comments
Reading the documentation, I don't understand how this is not possible : # get the max utc timestamp
ts = datetime.max.replace(tzinfo=timezone.utc).timestamp()
# similarly
ts2 = datetime(9999, 12, 31, 23, 59, 59, 999999, tzinfo=timezone.utc).timestamp() # timestamp value 253402300800 seems correct dt = datetime.fromtimestamp(ts, tz=timezone.utc)
dt = datetime.utcfromtimestamp(ts) It should be possible to get a datetime back from the initially converted timestamp, no? |
Please show us how they fail. |
a ValueError is raised : ValueError: year 10000 is out of range on dt = datetime.fromtimestamp(ts, tz=timezone.utc) or dt = datetime.utcfromtimestamp(ts) |
I see this in the python source code being tested (datetimetester.py), so I guess it is a rounding problem : # maximum timestamp: set seconds to zero to avoid rounding issues
max_dt = self.theclass.max.replace(tzinfo=timezone.utc,
second=0, microsecond=0)
max_ts = max_dt.timestamp()
# date 9999-12-31 23:59:00+00:00: timestamp 253402300740
self.assertEqual(self.theclass.fromtimestamp(max_ts, tz=timezone.utc),
max_dt) |
Probably so. You could step through the code to make sure that's what's going on. |
I looked at this a bit more in detail. converter = _time.gmtime if utc else _time.localtime
y, m, d, hh, mm, ss, weekday, jday, dst = converter(t) That will call the system gmtime_r(), which indeed returns Sat Jan 1 00:00:00 10000 I have not looked at the cpp implementation for that method and I am not sure if this is something that can be improved. |
The min range of the datetime is also affected:
|
I have noticed that the behavior of In reality, this does not matter, because timestamps that far away from the current date are essentially meaningless, but we should probably have well-defined limits so that people can reason well enough about their code. I propose that on all platforms that support it (e.g. not Windows):
|
I think it's important to note that the problem is not with the the thing is that in the Sorry if it's obvious |
we have a method def total_seconds(self):
"""Total seconds in the duration."""
return ((self.days * 86400 + self.seconds) * 10**6 + self.microseconds) / 10**6 it returns the rounded number of seconds, the question arose: should we do this? (maybe we should open new issue) in my opinion rounding up is the wrong approach in the module responsible for date/time another example: >>> days * 86400 + seconds
253402300799 # ok
>>> ((days * 86400 + seconds) * 10**6 + microseconds) / 10**6
253402300800.0 # not ok
>>> days, seconds, microseconds = Decimal(days), Decimal(seconds), Decimal(microseconds)
>>> ((days * 86400 + seconds) * 10**6 + microseconds) / 10**6
Decimal('253402300799.999999') |
We are hitting the limit of Python's float, causing rounding. >>> float("-30610222479.99999")
-30610222479.99999
>>> float("-30610222479.999999")
-30610222480.0 What if we dropped a digit off of |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I don't think we want to do that: it unnecessarily complicates the code and might have unintended effects. I don't think there's a practical problem here that needs addressing. |
The problem still exists, if a user specifies too many microseconds that float cannot handle -- it rounds into the next day. |
If too many microseconds are specified, and rounding is not wanted, that's an API misuse IMO. The same could be said for floats themselves. If you specify too many digits, then the result is rounded.
Note that this would exclude |
Do we just want to note this in the docs and close? |
I personally don't think it's worth a note in the docs. It's how floating point works. How many places would we make this notation? |
Maybe just once in the notes at the start "due to the limitations of double and Python's float microseconds may be rounded" though I still think there should be a better approach stopping the rounding. |
In the Ultimately, |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: