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

gh-81708: Fixing the "Invalid argument" bug on datetime.timestamp() #15498

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

pingchaoc
Copy link

@pingchaoc pingchaoc commented Aug 26, 2019

Fixing the "Invalid argument" bug on datetime.timestamp()

I found a bug in the Python built-in library datetime. In the Windows os, from Python 3.6 to the latest version, datetime.timestamp() will report an "Invalid argument" error, even though it shouldn't.
For instance, when I try to get the timestamp of datetime(1970,1,2,6), the "Invalid argument" error occurs.
I checked the file "datetime.py", the timestamp() uses _mktime(u1) to return a timestmap and the _mktime(u1) employs the local(u1) to get the struct time. When u1 is negetive, the local(u1) throws the "Invalid argument" exception. Here are some codes in the datetime.py ,"u2 = u1 + (-max_fold_seconds, max_fold_seconds)[self.fold]; b = local(u2) - u2 ", self.fold is zero as default.
The u2 becomes the smallest argument for local(u), u2 is used for check if the time fold(Summer time or Winter time) exists. It seems there is no problems about Summer/Winter time around the Epoch (1970,1,1).
I added the simple judgement, which could make sure the "Invalid argument" do not happen when the datetime is near the Epoch.

https://bugs.python.org/issue37527

@the-knights-who-say-ni
Copy link

Hello, and thanks for your contribution!

I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA).

Unfortunately we couldn't find an account corresponding to your GitHub username on bugs.python.org (b.p.o) to verify you have signed the CLA (this might be simply due to a missing "GitHub Name" entry in your b.p.o account settings). This is necessary for legal reasons before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue.

You can check yourself to see if the CLA has been received.

Thanks again for your contribution, we look forward to reviewing it!

@ammaraskar
Copy link
Member

Thank you for your PR, would you mind following the guide here and attaching the bugs.python.org issue in the commit and PR messages: https://bugs.python.org/issue37527

Aside from that, here's some things you might wanna fix in the code. Add a regression test for this particular case on windows. Fix the existing failing tests. Note that the datetime module has a C implementation here that should be kept in sync with the Python version:

datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))

@pingchaoc
Copy link
Author

Thank you for your PR, would you mind following the guide here and attaching the bugs.python.org issue in the commit and PR messages: https://bugs.python.org/issue37527

Aside from that, here's some things you might wanna fix in the code. Add a regression test for this particular case on windows. Fix the existing failing tests. Note that the datetime module has a C implementation here that should be kept in sync with the Python version:

datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))

I konw a little about C. Fixing the datetime.c is too challenging for me.

@csabella csabella changed the title Fixing the "Invalid argument" bug on datetime.timestamp() bpo-37527: Fixing the "Invalid argument" bug on datetime.timestamp() Jan 10, 2020
@csabella
Copy link
Contributor

@pingchaoc, are you interested in continuing to work on this PR?

@csabella csabella added the stale Stale PR or inactive for long period of time. label May 28, 2020
@seljasen
Copy link

seljasen commented Oct 4, 2020

@ammaraskar
Copy link
Member

@seljasen Since this has been stale so long, I think you're safe to work an alternate patch for this. If you use @pingchaoc's original work, please add in a:

Co-authored-by: chenpingchao <pingchaoc@yeah.net>

into the CL description.

@Wouter1
Copy link

Wouter1 commented Jul 20, 2021

I have the same problem still on python 3.8.7 on windows. This is now almost 2 years later and datetime is a fundamental system function. Can I request higher priority for this?

how to reproduce:

from datetime import datetime
time=datetime.fromtimestamp(1.9)
datetime.timestamp(time)

@github-actions github-actions bot removed the stale Stale PR or inactive for long period of time. label Jul 30, 2022
@arhadthedev arhadthedev added the stdlib Python modules in the Lib dir label Mar 22, 2023
@arhadthedev arhadthedev changed the title bpo-37527: Fixing the "Invalid argument" bug on datetime.timestamp() gh-81708: Fixing the "Invalid argument" bug on datetime.timestamp() Mar 22, 2023
@bedevere-bot
Copy link

Most changes to Python require a NEWS entry.

Please add it using the blurb_it web app or the blurb command-line tool.

@arhadthedev
Copy link
Member

Probably also fixes gh-94414.

@arhadthedev arhadthedev marked this pull request as draft March 22, 2023 08:23
@arhadthedev
Copy link
Member

This PR breaks test.pythoninfo across all CI platforms. I tried to fix it last day but failed because I have no expertise in datetime module. @abalkin, @pganssle can this PR be salvaged? The issue addressed seems important to be resolved.

The only thing that I could do is to move an attached test into a proper location:

diff --git a/test.py b/test.py
deleted file mode 100644
index 0562011196..0000000000
--- a/test.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#  datetime.timestamp() fails when the 'datetime' is close to the Epoch
-#  Here is the test runs on win10 os, python3.7-3.9. My time is 'utc +8'
-
-from datetime import datetime
-
-def test(year,month,day,hour=0,minute=0,second=0):
-    t = datetime(year,month,day,hour)
-    try:
-        print(t.timestamp())
-    except Exception as e:
-        print(e)
-    return
-
-test(1970,1,1)
-test(1970,1,1,8)
:
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -6629,6 +6629,26 @@ def test_datetime_from_timestamp(self):
                     self.assertEqual(dt_orig, dt_rt)


+class EdgeCaseTests(unittest.TestCase):
+
+    def test_near_the_epoch(self):
+        # gh-81708: datetime.timestamp() may fail when the 'datetime'
+        # is close to the Epoch.
+        precisions = (
+            (1970, 1, 1, 0, 0, 0),
+            (1970, 1, 1, 8, 0, 0),
+            (1970, 1, 2, 7, 59, 59),
+            (1970, 1, 2, 8, 0, 0)  # this time is just okay
+        )
+        for date_tuple in precisions:
+            year, month, day, hour, minute, second = date_tuple
+            with self.subTest(date=date_tuple):
+                instance = datetime(year, month, day, hour)
+                self.assertIsNotNone(instance)
+                timestamp = instance.timestamp()
+                self.assertIsNotNone(timestamp)
+
+
 def load_tests(loader, standard_tests, pattern):
     standard_tests.addTest(ZoneInfoCompleteTest())
     return standard_tests
diff --git a/test.py b/test.py
deleted file mode 100644
index 0562011196..0000000000
--- a/test.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#  datetime.timestamp() fails when the 'datetime' is close to the Epoch
-#  Here is the test runs on win10 os, python3.7-3.9. My time is 'utc +8'
-
-from datetime import datetime
-
-def test(year,month,day,hour=0,minute=0,second=0):
-    t = datetime(year,month,day,hour)
-    try:
-        print(t.timestamp())
-    except Exception as e:
-        print(e)
-    return
-
-test(1970,1,1)
-test(1970,1,1,8)
-test(1970,1,2,7,59,59)
-test(1970,1,2,8)  # this time is just okay

@arhadthedev arhadthedev marked this pull request as ready for review March 23, 2023 03:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting review DO-NOT-MERGE stdlib Python modules in the Lib dir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants