You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6904 lines
218 KiB

Merged revisions 61239-61249,61252-61257,61260-61264,61269-61275,61278-61279,61285-61286,61288-61290,61298,61303-61305,61312-61314,61317,61329,61332,61344,61350-61351,61363-61376,61378-61379,61382-61383,61387-61388,61392,61395-61396,61402-61403 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r61239 | andrew.kuchling | 2008-03-05 01:44:41 +0100 (Wed, 05 Mar 2008) | 1 line Add more items; add fragmentary notes ........ r61240 | amaury.forgeotdarc | 2008-03-05 02:50:33 +0100 (Wed, 05 Mar 2008) | 13 lines Issue#2238: some syntax errors from *args or **kwargs expressions would give bogus error messages, because of untested exceptions:: >>> f(**g(1=2)) XXX undetected error Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable instead of the expected SyntaxError: keyword can't be an expression Will backport. ........ r61241 | neal.norwitz | 2008-03-05 06:10:48 +0100 (Wed, 05 Mar 2008) | 3 lines Remove the files/dirs after closing the DB so the tests work on Windows. Patch from Trent Nelson. Also simplified removing a file by using test_support. ........ r61242 | neal.norwitz | 2008-03-05 06:14:18 +0100 (Wed, 05 Mar 2008) | 3 lines Get this test to pass even when there is no sound card in the system. Patch from Trent Nelson. (I can't test this.) ........ r61243 | neal.norwitz | 2008-03-05 06:20:44 +0100 (Wed, 05 Mar 2008) | 3 lines Catch OSError when trying to remove a file in case removal fails. This should prevent a failure in tearDown masking any real test failure. ........ r61244 | neal.norwitz | 2008-03-05 06:38:06 +0100 (Wed, 05 Mar 2008) | 5 lines Make the timeout longer to give slow machines a chance to pass the test before timing out. This doesn't change the duration of the test under normal circumstances. This is targetted at fixing the spurious failures on the FreeBSD buildbot primarily. ........ r61245 | neal.norwitz | 2008-03-05 06:49:03 +0100 (Wed, 05 Mar 2008) | 1 line Tabs -> spaces ........ r61246 | neal.norwitz | 2008-03-05 06:50:20 +0100 (Wed, 05 Mar 2008) | 1 line Use -u urlfetch to run more tests ........ r61247 | neal.norwitz | 2008-03-05 06:51:20 +0100 (Wed, 05 Mar 2008) | 1 line test_smtplib sometimes reports leaks too, suppress it ........ r61248 | jeffrey.yasskin | 2008-03-05 07:19:56 +0100 (Wed, 05 Mar 2008) | 5 lines Fix test_socketserver on Windows after r61099 added several signal.alarm() calls (which don't exist on non-Unix platforms). Thanks to Trent Nelson for the report and patch. ........ r61249 | georg.brandl | 2008-03-05 08:10:35 +0100 (Wed, 05 Mar 2008) | 2 lines Fix some rst. ........ r61252 | thomas.heller | 2008-03-05 15:53:39 +0100 (Wed, 05 Mar 2008) | 2 lines News entry for yesterdays commit. ........ r61253 | thomas.heller | 2008-03-05 16:34:29 +0100 (Wed, 05 Mar 2008) | 3 lines Issue 1872: Changed the struct module typecode from 't' to '?', for compatibility with PEP3118. ........ r61254 | skip.montanaro | 2008-03-05 17:41:09 +0100 (Wed, 05 Mar 2008) | 4 lines Elaborate on the role of the altinstall target when installing multiple versions. ........ r61255 | georg.brandl | 2008-03-05 20:31:44 +0100 (Wed, 05 Mar 2008) | 2 lines #2239: PYTHONPATH delimiter is os.pathsep. ........ r61256 | raymond.hettinger | 2008-03-05 21:59:58 +0100 (Wed, 05 Mar 2008) | 1 line C implementation of itertools.permutations(). ........ r61257 | raymond.hettinger | 2008-03-05 22:04:32 +0100 (Wed, 05 Mar 2008) | 1 line Small code cleanup. ........ r61260 | martin.v.loewis | 2008-03-05 23:24:31 +0100 (Wed, 05 Mar 2008) | 2 lines cd PCbuild only after deleting all pyc files. ........ r61261 | raymond.hettinger | 2008-03-06 02:15:52 +0100 (Thu, 06 Mar 2008) | 1 line Add examples. ........ r61262 | andrew.kuchling | 2008-03-06 02:36:27 +0100 (Thu, 06 Mar 2008) | 1 line Add two items ........ r61263 | georg.brandl | 2008-03-06 07:47:18 +0100 (Thu, 06 Mar 2008) | 2 lines #1725737: ignore other VC directories other than CVS and SVN's too. ........ r61264 | martin.v.loewis | 2008-03-06 07:55:22 +0100 (Thu, 06 Mar 2008) | 4 lines Patch #2232: os.tmpfile might fail on Windows if the user has no permission to create files in the root directory. Will backport to 2.5. ........ r61269 | georg.brandl | 2008-03-06 08:19:15 +0100 (Thu, 06 Mar 2008) | 2 lines Expand on re.split behavior with captured expressions. ........ r61270 | georg.brandl | 2008-03-06 08:22:09 +0100 (Thu, 06 Mar 2008) | 2 lines Little clarification of assignments. ........ r61271 | georg.brandl | 2008-03-06 08:31:34 +0100 (Thu, 06 Mar 2008) | 2 lines Add isinstance/issubclass to tutorial. ........ r61272 | georg.brandl | 2008-03-06 08:34:52 +0100 (Thu, 06 Mar 2008) | 2 lines Add missing NEWS entry for r61263. ........ r61273 | georg.brandl | 2008-03-06 08:41:16 +0100 (Thu, 06 Mar 2008) | 2 lines #2225: return nonzero status code from py_compile if not all files could be compiled. ........ r61274 | georg.brandl | 2008-03-06 08:43:02 +0100 (Thu, 06 Mar 2008) | 2 lines #2220: handle matching failure more gracefully. ........ r61275 | georg.brandl | 2008-03-06 08:45:52 +0100 (Thu, 06 Mar 2008) | 2 lines Bug #2220: handle rlcompleter attribute match failure more gracefully. ........ r61278 | martin.v.loewis | 2008-03-06 14:49:47 +0100 (Thu, 06 Mar 2008) | 1 line Rely on x64 platform configuration when building _bsddb on AMD64. ........ r61279 | martin.v.loewis | 2008-03-06 14:50:28 +0100 (Thu, 06 Mar 2008) | 1 line Update db-4.4.20 build procedure. ........ r61285 | raymond.hettinger | 2008-03-06 21:52:01 +0100 (Thu, 06 Mar 2008) | 1 line More tests. ........ r61286 | raymond.hettinger | 2008-03-06 23:51:36 +0100 (Thu, 06 Mar 2008) | 1 line Issue 2246: itertools grouper object did not participate in GC (should be backported). ........ r61288 | raymond.hettinger | 2008-03-07 02:33:20 +0100 (Fri, 07 Mar 2008) | 1 line Tweak recipes and tests ........ r61289 | jeffrey.yasskin | 2008-03-07 07:22:15 +0100 (Fri, 07 Mar 2008) | 5 lines Progress on issue #1193577 by adding a polling .shutdown() method to SocketServers. The core of the patch was written by Pedro Werneck, but any bugs are mine. I've also rearranged the code for timeouts in order to avoid interfering with the shutdown poll. ........ r61290 | nick.coghlan | 2008-03-07 15:13:28 +0100 (Fri, 07 Mar 2008) | 1 line Speed up with statements by storing the __exit__ method on the stack instead of in a temp variable (bumps the magic number for pyc files) ........ r61298 | andrew.kuchling | 2008-03-07 22:09:23 +0100 (Fri, 07 Mar 2008) | 1 line Grammar fix ........ r61303 | georg.brandl | 2008-03-08 10:54:06 +0100 (Sat, 08 Mar 2008) | 2 lines #2253: fix continue vs. finally docs. ........ r61304 | marc-andre.lemburg | 2008-03-08 11:01:43 +0100 (Sat, 08 Mar 2008) | 3 lines Add new name for Mandrake: Mandriva. ........ r61305 | georg.brandl | 2008-03-08 11:05:24 +0100 (Sat, 08 Mar 2008) | 2 lines #1533486: fix types in refcount intro. ........ r61312 | facundo.batista | 2008-03-08 17:50:27 +0100 (Sat, 08 Mar 2008) | 5 lines Issue 1106316. post_mortem()'s parameter, traceback, is now optional: it defaults to the traceback of the exception that is currently being handled. ........ r61313 | jeffrey.yasskin | 2008-03-08 19:26:54 +0100 (Sat, 08 Mar 2008) | 2 lines Add tests for with and finally performance to pybench. ........ r61314 | jeffrey.yasskin | 2008-03-08 21:08:21 +0100 (Sat, 08 Mar 2008) | 2 lines Fix pybench for pythons < 2.6, tested back to 2.3. ........ r61317 | jeffrey.yasskin | 2008-03-08 22:35:15 +0100 (Sat, 08 Mar 2008) | 3 lines Well that was dumb. platform.python_implementation returns a function, not a string. ........ r61329 | georg.brandl | 2008-03-09 16:11:39 +0100 (Sun, 09 Mar 2008) | 2 lines #2249: document assertTrue and assertFalse. ........ r61332 | neal.norwitz | 2008-03-09 20:03:42 +0100 (Sun, 09 Mar 2008) | 4 lines Introduce a lock to fix a race condition which caused an exception in the test. Some buildbots were consistently failing (e.g., amd64). Also remove a couple of semi-colons. ........ r61344 | raymond.hettinger | 2008-03-11 01:19:07 +0100 (Tue, 11 Mar 2008) | 1 line Add recipe to docs. ........ r61350 | guido.van.rossum | 2008-03-11 22:18:06 +0100 (Tue, 11 Mar 2008) | 3 lines Fix the overflows in expandtabs(). "This time for sure!" (Exploit at request.) ........ r61351 | raymond.hettinger | 2008-03-11 22:37:46 +0100 (Tue, 11 Mar 2008) | 1 line Improve docs for itemgetter(). Show that it works with slices. ........ r61363 | georg.brandl | 2008-03-13 08:15:56 +0100 (Thu, 13 Mar 2008) | 2 lines #2265: fix example. ........ r61364 | georg.brandl | 2008-03-13 08:17:14 +0100 (Thu, 13 Mar 2008) | 2 lines #2270: fix typo. ........ r61365 | georg.brandl | 2008-03-13 08:21:41 +0100 (Thu, 13 Mar 2008) | 2 lines #1720705: add docs about import/threading interaction, wording by Nick. ........ r61366 | andrew.kuchling | 2008-03-13 12:07:35 +0100 (Thu, 13 Mar 2008) | 1 line Add class decorators ........ r61367 | raymond.hettinger | 2008-03-13 17:43:17 +0100 (Thu, 13 Mar 2008) | 1 line Add 2-to-3 support for the itertools moved to builtins or renamed. ........ r61368 | raymond.hettinger | 2008-03-13 17:43:59 +0100 (Thu, 13 Mar 2008) | 1 line Consistent tense. ........ r61369 | raymond.hettinger | 2008-03-13 20:03:51 +0100 (Thu, 13 Mar 2008) | 1 line Issue 2274: Add heapq.heappushpop(). ........ r61370 | raymond.hettinger | 2008-03-13 20:33:34 +0100 (Thu, 13 Mar 2008) | 1 line Simplify the nlargest() code using heappushpop(). ........ r61371 | brett.cannon | 2008-03-13 21:27:00 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_thread over to unittest. Commits GHOP 237. Thanks Benjamin Peterson for the patch. ........ r61372 | brett.cannon | 2008-03-13 21:33:10 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_tokenize to doctest. Done as GHOP 238 by Josip Dzolonga. ........ r61373 | brett.cannon | 2008-03-13 21:47:41 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_contains, test_crypt, and test_select to unittest. Patch from GHOP 294 by David Marek. ........ r61374 | brett.cannon | 2008-03-13 22:02:16 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_gdbm to use unittest. Closes issue #1960. Thanks Giampaolo Rodola. ........ r61375 | brett.cannon | 2008-03-13 22:09:28 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_fcntl to unittest. Closes issue #2055. Thanks Giampaolo Rodola. ........ r61376 | raymond.hettinger | 2008-03-14 06:03:44 +0100 (Fri, 14 Mar 2008) | 1 line Leave heapreplace() unchanged. ........ r61378 | martin.v.loewis | 2008-03-14 14:56:09 +0100 (Fri, 14 Mar 2008) | 2 lines Patch #2284: add -x64 option to rt.bat. ........ r61379 | martin.v.loewis | 2008-03-14 14:57:59 +0100 (Fri, 14 Mar 2008) | 2 lines Use -x64 flag. ........ r61382 | brett.cannon | 2008-03-14 15:03:10 +0100 (Fri, 14 Mar 2008) | 2 lines Remove a bad test. ........ r61383 | mark.dickinson | 2008-03-14 15:23:37 +0100 (Fri, 14 Mar 2008) | 9 lines Issue 705836: Fix struct.pack(">f", 1e40) to behave consistently across platforms: it should now raise OverflowError on all platforms. (Previously it raised OverflowError only on non IEEE 754 platforms.) Also fix the (already existing) test for this behaviour so that it actually raises TestFailed instead of just referencing it. ........ r61387 | thomas.heller | 2008-03-14 22:06:21 +0100 (Fri, 14 Mar 2008) | 1 line Remove unneeded initializer. ........ r61388 | martin.v.loewis | 2008-03-14 22:19:28 +0100 (Fri, 14 Mar 2008) | 2 lines Run debug version, cd to PCbuild. ........ r61392 | georg.brandl | 2008-03-15 00:10:34 +0100 (Sat, 15 Mar 2008) | 2 lines Remove obsolete paragraph. #2288. ........ r61395 | georg.brandl | 2008-03-15 01:20:19 +0100 (Sat, 15 Mar 2008) | 2 lines Fix lots of broken links in the docs, found by Sphinx' external link checker. ........ r61396 | skip.montanaro | 2008-03-15 03:32:49 +0100 (Sat, 15 Mar 2008) | 1 line note that fork and forkpty raise OSError on failure ........ r61402 | skip.montanaro | 2008-03-15 17:04:45 +0100 (Sat, 15 Mar 2008) | 1 line add %f format to datetime - issue 1158 ........ r61403 | skip.montanaro | 2008-03-15 17:07:11 +0100 (Sat, 15 Mar 2008) | 2 lines . ........
18 years ago
Merged revisions 61239-61249,61252-61257,61260-61264,61269-61275,61278-61279,61285-61286,61288-61290,61298,61303-61305,61312-61314,61317,61329,61332,61344,61350-61351,61363-61376,61378-61379,61382-61383,61387-61388,61392,61395-61396,61402-61403 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r61239 | andrew.kuchling | 2008-03-05 01:44:41 +0100 (Wed, 05 Mar 2008) | 1 line Add more items; add fragmentary notes ........ r61240 | amaury.forgeotdarc | 2008-03-05 02:50:33 +0100 (Wed, 05 Mar 2008) | 13 lines Issue#2238: some syntax errors from *args or **kwargs expressions would give bogus error messages, because of untested exceptions:: >>> f(**g(1=2)) XXX undetected error Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable instead of the expected SyntaxError: keyword can't be an expression Will backport. ........ r61241 | neal.norwitz | 2008-03-05 06:10:48 +0100 (Wed, 05 Mar 2008) | 3 lines Remove the files/dirs after closing the DB so the tests work on Windows. Patch from Trent Nelson. Also simplified removing a file by using test_support. ........ r61242 | neal.norwitz | 2008-03-05 06:14:18 +0100 (Wed, 05 Mar 2008) | 3 lines Get this test to pass even when there is no sound card in the system. Patch from Trent Nelson. (I can't test this.) ........ r61243 | neal.norwitz | 2008-03-05 06:20:44 +0100 (Wed, 05 Mar 2008) | 3 lines Catch OSError when trying to remove a file in case removal fails. This should prevent a failure in tearDown masking any real test failure. ........ r61244 | neal.norwitz | 2008-03-05 06:38:06 +0100 (Wed, 05 Mar 2008) | 5 lines Make the timeout longer to give slow machines a chance to pass the test before timing out. This doesn't change the duration of the test under normal circumstances. This is targetted at fixing the spurious failures on the FreeBSD buildbot primarily. ........ r61245 | neal.norwitz | 2008-03-05 06:49:03 +0100 (Wed, 05 Mar 2008) | 1 line Tabs -> spaces ........ r61246 | neal.norwitz | 2008-03-05 06:50:20 +0100 (Wed, 05 Mar 2008) | 1 line Use -u urlfetch to run more tests ........ r61247 | neal.norwitz | 2008-03-05 06:51:20 +0100 (Wed, 05 Mar 2008) | 1 line test_smtplib sometimes reports leaks too, suppress it ........ r61248 | jeffrey.yasskin | 2008-03-05 07:19:56 +0100 (Wed, 05 Mar 2008) | 5 lines Fix test_socketserver on Windows after r61099 added several signal.alarm() calls (which don't exist on non-Unix platforms). Thanks to Trent Nelson for the report and patch. ........ r61249 | georg.brandl | 2008-03-05 08:10:35 +0100 (Wed, 05 Mar 2008) | 2 lines Fix some rst. ........ r61252 | thomas.heller | 2008-03-05 15:53:39 +0100 (Wed, 05 Mar 2008) | 2 lines News entry for yesterdays commit. ........ r61253 | thomas.heller | 2008-03-05 16:34:29 +0100 (Wed, 05 Mar 2008) | 3 lines Issue 1872: Changed the struct module typecode from 't' to '?', for compatibility with PEP3118. ........ r61254 | skip.montanaro | 2008-03-05 17:41:09 +0100 (Wed, 05 Mar 2008) | 4 lines Elaborate on the role of the altinstall target when installing multiple versions. ........ r61255 | georg.brandl | 2008-03-05 20:31:44 +0100 (Wed, 05 Mar 2008) | 2 lines #2239: PYTHONPATH delimiter is os.pathsep. ........ r61256 | raymond.hettinger | 2008-03-05 21:59:58 +0100 (Wed, 05 Mar 2008) | 1 line C implementation of itertools.permutations(). ........ r61257 | raymond.hettinger | 2008-03-05 22:04:32 +0100 (Wed, 05 Mar 2008) | 1 line Small code cleanup. ........ r61260 | martin.v.loewis | 2008-03-05 23:24:31 +0100 (Wed, 05 Mar 2008) | 2 lines cd PCbuild only after deleting all pyc files. ........ r61261 | raymond.hettinger | 2008-03-06 02:15:52 +0100 (Thu, 06 Mar 2008) | 1 line Add examples. ........ r61262 | andrew.kuchling | 2008-03-06 02:36:27 +0100 (Thu, 06 Mar 2008) | 1 line Add two items ........ r61263 | georg.brandl | 2008-03-06 07:47:18 +0100 (Thu, 06 Mar 2008) | 2 lines #1725737: ignore other VC directories other than CVS and SVN's too. ........ r61264 | martin.v.loewis | 2008-03-06 07:55:22 +0100 (Thu, 06 Mar 2008) | 4 lines Patch #2232: os.tmpfile might fail on Windows if the user has no permission to create files in the root directory. Will backport to 2.5. ........ r61269 | georg.brandl | 2008-03-06 08:19:15 +0100 (Thu, 06 Mar 2008) | 2 lines Expand on re.split behavior with captured expressions. ........ r61270 | georg.brandl | 2008-03-06 08:22:09 +0100 (Thu, 06 Mar 2008) | 2 lines Little clarification of assignments. ........ r61271 | georg.brandl | 2008-03-06 08:31:34 +0100 (Thu, 06 Mar 2008) | 2 lines Add isinstance/issubclass to tutorial. ........ r61272 | georg.brandl | 2008-03-06 08:34:52 +0100 (Thu, 06 Mar 2008) | 2 lines Add missing NEWS entry for r61263. ........ r61273 | georg.brandl | 2008-03-06 08:41:16 +0100 (Thu, 06 Mar 2008) | 2 lines #2225: return nonzero status code from py_compile if not all files could be compiled. ........ r61274 | georg.brandl | 2008-03-06 08:43:02 +0100 (Thu, 06 Mar 2008) | 2 lines #2220: handle matching failure more gracefully. ........ r61275 | georg.brandl | 2008-03-06 08:45:52 +0100 (Thu, 06 Mar 2008) | 2 lines Bug #2220: handle rlcompleter attribute match failure more gracefully. ........ r61278 | martin.v.loewis | 2008-03-06 14:49:47 +0100 (Thu, 06 Mar 2008) | 1 line Rely on x64 platform configuration when building _bsddb on AMD64. ........ r61279 | martin.v.loewis | 2008-03-06 14:50:28 +0100 (Thu, 06 Mar 2008) | 1 line Update db-4.4.20 build procedure. ........ r61285 | raymond.hettinger | 2008-03-06 21:52:01 +0100 (Thu, 06 Mar 2008) | 1 line More tests. ........ r61286 | raymond.hettinger | 2008-03-06 23:51:36 +0100 (Thu, 06 Mar 2008) | 1 line Issue 2246: itertools grouper object did not participate in GC (should be backported). ........ r61288 | raymond.hettinger | 2008-03-07 02:33:20 +0100 (Fri, 07 Mar 2008) | 1 line Tweak recipes and tests ........ r61289 | jeffrey.yasskin | 2008-03-07 07:22:15 +0100 (Fri, 07 Mar 2008) | 5 lines Progress on issue #1193577 by adding a polling .shutdown() method to SocketServers. The core of the patch was written by Pedro Werneck, but any bugs are mine. I've also rearranged the code for timeouts in order to avoid interfering with the shutdown poll. ........ r61290 | nick.coghlan | 2008-03-07 15:13:28 +0100 (Fri, 07 Mar 2008) | 1 line Speed up with statements by storing the __exit__ method on the stack instead of in a temp variable (bumps the magic number for pyc files) ........ r61298 | andrew.kuchling | 2008-03-07 22:09:23 +0100 (Fri, 07 Mar 2008) | 1 line Grammar fix ........ r61303 | georg.brandl | 2008-03-08 10:54:06 +0100 (Sat, 08 Mar 2008) | 2 lines #2253: fix continue vs. finally docs. ........ r61304 | marc-andre.lemburg | 2008-03-08 11:01:43 +0100 (Sat, 08 Mar 2008) | 3 lines Add new name for Mandrake: Mandriva. ........ r61305 | georg.brandl | 2008-03-08 11:05:24 +0100 (Sat, 08 Mar 2008) | 2 lines #1533486: fix types in refcount intro. ........ r61312 | facundo.batista | 2008-03-08 17:50:27 +0100 (Sat, 08 Mar 2008) | 5 lines Issue 1106316. post_mortem()'s parameter, traceback, is now optional: it defaults to the traceback of the exception that is currently being handled. ........ r61313 | jeffrey.yasskin | 2008-03-08 19:26:54 +0100 (Sat, 08 Mar 2008) | 2 lines Add tests for with and finally performance to pybench. ........ r61314 | jeffrey.yasskin | 2008-03-08 21:08:21 +0100 (Sat, 08 Mar 2008) | 2 lines Fix pybench for pythons < 2.6, tested back to 2.3. ........ r61317 | jeffrey.yasskin | 2008-03-08 22:35:15 +0100 (Sat, 08 Mar 2008) | 3 lines Well that was dumb. platform.python_implementation returns a function, not a string. ........ r61329 | georg.brandl | 2008-03-09 16:11:39 +0100 (Sun, 09 Mar 2008) | 2 lines #2249: document assertTrue and assertFalse. ........ r61332 | neal.norwitz | 2008-03-09 20:03:42 +0100 (Sun, 09 Mar 2008) | 4 lines Introduce a lock to fix a race condition which caused an exception in the test. Some buildbots were consistently failing (e.g., amd64). Also remove a couple of semi-colons. ........ r61344 | raymond.hettinger | 2008-03-11 01:19:07 +0100 (Tue, 11 Mar 2008) | 1 line Add recipe to docs. ........ r61350 | guido.van.rossum | 2008-03-11 22:18:06 +0100 (Tue, 11 Mar 2008) | 3 lines Fix the overflows in expandtabs(). "This time for sure!" (Exploit at request.) ........ r61351 | raymond.hettinger | 2008-03-11 22:37:46 +0100 (Tue, 11 Mar 2008) | 1 line Improve docs for itemgetter(). Show that it works with slices. ........ r61363 | georg.brandl | 2008-03-13 08:15:56 +0100 (Thu, 13 Mar 2008) | 2 lines #2265: fix example. ........ r61364 | georg.brandl | 2008-03-13 08:17:14 +0100 (Thu, 13 Mar 2008) | 2 lines #2270: fix typo. ........ r61365 | georg.brandl | 2008-03-13 08:21:41 +0100 (Thu, 13 Mar 2008) | 2 lines #1720705: add docs about import/threading interaction, wording by Nick. ........ r61366 | andrew.kuchling | 2008-03-13 12:07:35 +0100 (Thu, 13 Mar 2008) | 1 line Add class decorators ........ r61367 | raymond.hettinger | 2008-03-13 17:43:17 +0100 (Thu, 13 Mar 2008) | 1 line Add 2-to-3 support for the itertools moved to builtins or renamed. ........ r61368 | raymond.hettinger | 2008-03-13 17:43:59 +0100 (Thu, 13 Mar 2008) | 1 line Consistent tense. ........ r61369 | raymond.hettinger | 2008-03-13 20:03:51 +0100 (Thu, 13 Mar 2008) | 1 line Issue 2274: Add heapq.heappushpop(). ........ r61370 | raymond.hettinger | 2008-03-13 20:33:34 +0100 (Thu, 13 Mar 2008) | 1 line Simplify the nlargest() code using heappushpop(). ........ r61371 | brett.cannon | 2008-03-13 21:27:00 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_thread over to unittest. Commits GHOP 237. Thanks Benjamin Peterson for the patch. ........ r61372 | brett.cannon | 2008-03-13 21:33:10 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_tokenize to doctest. Done as GHOP 238 by Josip Dzolonga. ........ r61373 | brett.cannon | 2008-03-13 21:47:41 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_contains, test_crypt, and test_select to unittest. Patch from GHOP 294 by David Marek. ........ r61374 | brett.cannon | 2008-03-13 22:02:16 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_gdbm to use unittest. Closes issue #1960. Thanks Giampaolo Rodola. ........ r61375 | brett.cannon | 2008-03-13 22:09:28 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_fcntl to unittest. Closes issue #2055. Thanks Giampaolo Rodola. ........ r61376 | raymond.hettinger | 2008-03-14 06:03:44 +0100 (Fri, 14 Mar 2008) | 1 line Leave heapreplace() unchanged. ........ r61378 | martin.v.loewis | 2008-03-14 14:56:09 +0100 (Fri, 14 Mar 2008) | 2 lines Patch #2284: add -x64 option to rt.bat. ........ r61379 | martin.v.loewis | 2008-03-14 14:57:59 +0100 (Fri, 14 Mar 2008) | 2 lines Use -x64 flag. ........ r61382 | brett.cannon | 2008-03-14 15:03:10 +0100 (Fri, 14 Mar 2008) | 2 lines Remove a bad test. ........ r61383 | mark.dickinson | 2008-03-14 15:23:37 +0100 (Fri, 14 Mar 2008) | 9 lines Issue 705836: Fix struct.pack(">f", 1e40) to behave consistently across platforms: it should now raise OverflowError on all platforms. (Previously it raised OverflowError only on non IEEE 754 platforms.) Also fix the (already existing) test for this behaviour so that it actually raises TestFailed instead of just referencing it. ........ r61387 | thomas.heller | 2008-03-14 22:06:21 +0100 (Fri, 14 Mar 2008) | 1 line Remove unneeded initializer. ........ r61388 | martin.v.loewis | 2008-03-14 22:19:28 +0100 (Fri, 14 Mar 2008) | 2 lines Run debug version, cd to PCbuild. ........ r61392 | georg.brandl | 2008-03-15 00:10:34 +0100 (Sat, 15 Mar 2008) | 2 lines Remove obsolete paragraph. #2288. ........ r61395 | georg.brandl | 2008-03-15 01:20:19 +0100 (Sat, 15 Mar 2008) | 2 lines Fix lots of broken links in the docs, found by Sphinx' external link checker. ........ r61396 | skip.montanaro | 2008-03-15 03:32:49 +0100 (Sat, 15 Mar 2008) | 1 line note that fork and forkpty raise OSError on failure ........ r61402 | skip.montanaro | 2008-03-15 17:04:45 +0100 (Sat, 15 Mar 2008) | 1 line add %f format to datetime - issue 1158 ........ r61403 | skip.montanaro | 2008-03-15 17:07:11 +0100 (Sat, 15 Mar 2008) | 2 lines . ........
18 years ago
Merged revisions 61239-61249,61252-61257,61260-61264,61269-61275,61278-61279,61285-61286,61288-61290,61298,61303-61305,61312-61314,61317,61329,61332,61344,61350-61351,61363-61376,61378-61379,61382-61383,61387-61388,61392,61395-61396,61402-61403 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r61239 | andrew.kuchling | 2008-03-05 01:44:41 +0100 (Wed, 05 Mar 2008) | 1 line Add more items; add fragmentary notes ........ r61240 | amaury.forgeotdarc | 2008-03-05 02:50:33 +0100 (Wed, 05 Mar 2008) | 13 lines Issue#2238: some syntax errors from *args or **kwargs expressions would give bogus error messages, because of untested exceptions:: >>> f(**g(1=2)) XXX undetected error Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable instead of the expected SyntaxError: keyword can't be an expression Will backport. ........ r61241 | neal.norwitz | 2008-03-05 06:10:48 +0100 (Wed, 05 Mar 2008) | 3 lines Remove the files/dirs after closing the DB so the tests work on Windows. Patch from Trent Nelson. Also simplified removing a file by using test_support. ........ r61242 | neal.norwitz | 2008-03-05 06:14:18 +0100 (Wed, 05 Mar 2008) | 3 lines Get this test to pass even when there is no sound card in the system. Patch from Trent Nelson. (I can't test this.) ........ r61243 | neal.norwitz | 2008-03-05 06:20:44 +0100 (Wed, 05 Mar 2008) | 3 lines Catch OSError when trying to remove a file in case removal fails. This should prevent a failure in tearDown masking any real test failure. ........ r61244 | neal.norwitz | 2008-03-05 06:38:06 +0100 (Wed, 05 Mar 2008) | 5 lines Make the timeout longer to give slow machines a chance to pass the test before timing out. This doesn't change the duration of the test under normal circumstances. This is targetted at fixing the spurious failures on the FreeBSD buildbot primarily. ........ r61245 | neal.norwitz | 2008-03-05 06:49:03 +0100 (Wed, 05 Mar 2008) | 1 line Tabs -> spaces ........ r61246 | neal.norwitz | 2008-03-05 06:50:20 +0100 (Wed, 05 Mar 2008) | 1 line Use -u urlfetch to run more tests ........ r61247 | neal.norwitz | 2008-03-05 06:51:20 +0100 (Wed, 05 Mar 2008) | 1 line test_smtplib sometimes reports leaks too, suppress it ........ r61248 | jeffrey.yasskin | 2008-03-05 07:19:56 +0100 (Wed, 05 Mar 2008) | 5 lines Fix test_socketserver on Windows after r61099 added several signal.alarm() calls (which don't exist on non-Unix platforms). Thanks to Trent Nelson for the report and patch. ........ r61249 | georg.brandl | 2008-03-05 08:10:35 +0100 (Wed, 05 Mar 2008) | 2 lines Fix some rst. ........ r61252 | thomas.heller | 2008-03-05 15:53:39 +0100 (Wed, 05 Mar 2008) | 2 lines News entry for yesterdays commit. ........ r61253 | thomas.heller | 2008-03-05 16:34:29 +0100 (Wed, 05 Mar 2008) | 3 lines Issue 1872: Changed the struct module typecode from 't' to '?', for compatibility with PEP3118. ........ r61254 | skip.montanaro | 2008-03-05 17:41:09 +0100 (Wed, 05 Mar 2008) | 4 lines Elaborate on the role of the altinstall target when installing multiple versions. ........ r61255 | georg.brandl | 2008-03-05 20:31:44 +0100 (Wed, 05 Mar 2008) | 2 lines #2239: PYTHONPATH delimiter is os.pathsep. ........ r61256 | raymond.hettinger | 2008-03-05 21:59:58 +0100 (Wed, 05 Mar 2008) | 1 line C implementation of itertools.permutations(). ........ r61257 | raymond.hettinger | 2008-03-05 22:04:32 +0100 (Wed, 05 Mar 2008) | 1 line Small code cleanup. ........ r61260 | martin.v.loewis | 2008-03-05 23:24:31 +0100 (Wed, 05 Mar 2008) | 2 lines cd PCbuild only after deleting all pyc files. ........ r61261 | raymond.hettinger | 2008-03-06 02:15:52 +0100 (Thu, 06 Mar 2008) | 1 line Add examples. ........ r61262 | andrew.kuchling | 2008-03-06 02:36:27 +0100 (Thu, 06 Mar 2008) | 1 line Add two items ........ r61263 | georg.brandl | 2008-03-06 07:47:18 +0100 (Thu, 06 Mar 2008) | 2 lines #1725737: ignore other VC directories other than CVS and SVN's too. ........ r61264 | martin.v.loewis | 2008-03-06 07:55:22 +0100 (Thu, 06 Mar 2008) | 4 lines Patch #2232: os.tmpfile might fail on Windows if the user has no permission to create files in the root directory. Will backport to 2.5. ........ r61269 | georg.brandl | 2008-03-06 08:19:15 +0100 (Thu, 06 Mar 2008) | 2 lines Expand on re.split behavior with captured expressions. ........ r61270 | georg.brandl | 2008-03-06 08:22:09 +0100 (Thu, 06 Mar 2008) | 2 lines Little clarification of assignments. ........ r61271 | georg.brandl | 2008-03-06 08:31:34 +0100 (Thu, 06 Mar 2008) | 2 lines Add isinstance/issubclass to tutorial. ........ r61272 | georg.brandl | 2008-03-06 08:34:52 +0100 (Thu, 06 Mar 2008) | 2 lines Add missing NEWS entry for r61263. ........ r61273 | georg.brandl | 2008-03-06 08:41:16 +0100 (Thu, 06 Mar 2008) | 2 lines #2225: return nonzero status code from py_compile if not all files could be compiled. ........ r61274 | georg.brandl | 2008-03-06 08:43:02 +0100 (Thu, 06 Mar 2008) | 2 lines #2220: handle matching failure more gracefully. ........ r61275 | georg.brandl | 2008-03-06 08:45:52 +0100 (Thu, 06 Mar 2008) | 2 lines Bug #2220: handle rlcompleter attribute match failure more gracefully. ........ r61278 | martin.v.loewis | 2008-03-06 14:49:47 +0100 (Thu, 06 Mar 2008) | 1 line Rely on x64 platform configuration when building _bsddb on AMD64. ........ r61279 | martin.v.loewis | 2008-03-06 14:50:28 +0100 (Thu, 06 Mar 2008) | 1 line Update db-4.4.20 build procedure. ........ r61285 | raymond.hettinger | 2008-03-06 21:52:01 +0100 (Thu, 06 Mar 2008) | 1 line More tests. ........ r61286 | raymond.hettinger | 2008-03-06 23:51:36 +0100 (Thu, 06 Mar 2008) | 1 line Issue 2246: itertools grouper object did not participate in GC (should be backported). ........ r61288 | raymond.hettinger | 2008-03-07 02:33:20 +0100 (Fri, 07 Mar 2008) | 1 line Tweak recipes and tests ........ r61289 | jeffrey.yasskin | 2008-03-07 07:22:15 +0100 (Fri, 07 Mar 2008) | 5 lines Progress on issue #1193577 by adding a polling .shutdown() method to SocketServers. The core of the patch was written by Pedro Werneck, but any bugs are mine. I've also rearranged the code for timeouts in order to avoid interfering with the shutdown poll. ........ r61290 | nick.coghlan | 2008-03-07 15:13:28 +0100 (Fri, 07 Mar 2008) | 1 line Speed up with statements by storing the __exit__ method on the stack instead of in a temp variable (bumps the magic number for pyc files) ........ r61298 | andrew.kuchling | 2008-03-07 22:09:23 +0100 (Fri, 07 Mar 2008) | 1 line Grammar fix ........ r61303 | georg.brandl | 2008-03-08 10:54:06 +0100 (Sat, 08 Mar 2008) | 2 lines #2253: fix continue vs. finally docs. ........ r61304 | marc-andre.lemburg | 2008-03-08 11:01:43 +0100 (Sat, 08 Mar 2008) | 3 lines Add new name for Mandrake: Mandriva. ........ r61305 | georg.brandl | 2008-03-08 11:05:24 +0100 (Sat, 08 Mar 2008) | 2 lines #1533486: fix types in refcount intro. ........ r61312 | facundo.batista | 2008-03-08 17:50:27 +0100 (Sat, 08 Mar 2008) | 5 lines Issue 1106316. post_mortem()'s parameter, traceback, is now optional: it defaults to the traceback of the exception that is currently being handled. ........ r61313 | jeffrey.yasskin | 2008-03-08 19:26:54 +0100 (Sat, 08 Mar 2008) | 2 lines Add tests for with and finally performance to pybench. ........ r61314 | jeffrey.yasskin | 2008-03-08 21:08:21 +0100 (Sat, 08 Mar 2008) | 2 lines Fix pybench for pythons < 2.6, tested back to 2.3. ........ r61317 | jeffrey.yasskin | 2008-03-08 22:35:15 +0100 (Sat, 08 Mar 2008) | 3 lines Well that was dumb. platform.python_implementation returns a function, not a string. ........ r61329 | georg.brandl | 2008-03-09 16:11:39 +0100 (Sun, 09 Mar 2008) | 2 lines #2249: document assertTrue and assertFalse. ........ r61332 | neal.norwitz | 2008-03-09 20:03:42 +0100 (Sun, 09 Mar 2008) | 4 lines Introduce a lock to fix a race condition which caused an exception in the test. Some buildbots were consistently failing (e.g., amd64). Also remove a couple of semi-colons. ........ r61344 | raymond.hettinger | 2008-03-11 01:19:07 +0100 (Tue, 11 Mar 2008) | 1 line Add recipe to docs. ........ r61350 | guido.van.rossum | 2008-03-11 22:18:06 +0100 (Tue, 11 Mar 2008) | 3 lines Fix the overflows in expandtabs(). "This time for sure!" (Exploit at request.) ........ r61351 | raymond.hettinger | 2008-03-11 22:37:46 +0100 (Tue, 11 Mar 2008) | 1 line Improve docs for itemgetter(). Show that it works with slices. ........ r61363 | georg.brandl | 2008-03-13 08:15:56 +0100 (Thu, 13 Mar 2008) | 2 lines #2265: fix example. ........ r61364 | georg.brandl | 2008-03-13 08:17:14 +0100 (Thu, 13 Mar 2008) | 2 lines #2270: fix typo. ........ r61365 | georg.brandl | 2008-03-13 08:21:41 +0100 (Thu, 13 Mar 2008) | 2 lines #1720705: add docs about import/threading interaction, wording by Nick. ........ r61366 | andrew.kuchling | 2008-03-13 12:07:35 +0100 (Thu, 13 Mar 2008) | 1 line Add class decorators ........ r61367 | raymond.hettinger | 2008-03-13 17:43:17 +0100 (Thu, 13 Mar 2008) | 1 line Add 2-to-3 support for the itertools moved to builtins or renamed. ........ r61368 | raymond.hettinger | 2008-03-13 17:43:59 +0100 (Thu, 13 Mar 2008) | 1 line Consistent tense. ........ r61369 | raymond.hettinger | 2008-03-13 20:03:51 +0100 (Thu, 13 Mar 2008) | 1 line Issue 2274: Add heapq.heappushpop(). ........ r61370 | raymond.hettinger | 2008-03-13 20:33:34 +0100 (Thu, 13 Mar 2008) | 1 line Simplify the nlargest() code using heappushpop(). ........ r61371 | brett.cannon | 2008-03-13 21:27:00 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_thread over to unittest. Commits GHOP 237. Thanks Benjamin Peterson for the patch. ........ r61372 | brett.cannon | 2008-03-13 21:33:10 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_tokenize to doctest. Done as GHOP 238 by Josip Dzolonga. ........ r61373 | brett.cannon | 2008-03-13 21:47:41 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_contains, test_crypt, and test_select to unittest. Patch from GHOP 294 by David Marek. ........ r61374 | brett.cannon | 2008-03-13 22:02:16 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_gdbm to use unittest. Closes issue #1960. Thanks Giampaolo Rodola. ........ r61375 | brett.cannon | 2008-03-13 22:09:28 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_fcntl to unittest. Closes issue #2055. Thanks Giampaolo Rodola. ........ r61376 | raymond.hettinger | 2008-03-14 06:03:44 +0100 (Fri, 14 Mar 2008) | 1 line Leave heapreplace() unchanged. ........ r61378 | martin.v.loewis | 2008-03-14 14:56:09 +0100 (Fri, 14 Mar 2008) | 2 lines Patch #2284: add -x64 option to rt.bat. ........ r61379 | martin.v.loewis | 2008-03-14 14:57:59 +0100 (Fri, 14 Mar 2008) | 2 lines Use -x64 flag. ........ r61382 | brett.cannon | 2008-03-14 15:03:10 +0100 (Fri, 14 Mar 2008) | 2 lines Remove a bad test. ........ r61383 | mark.dickinson | 2008-03-14 15:23:37 +0100 (Fri, 14 Mar 2008) | 9 lines Issue 705836: Fix struct.pack(">f", 1e40) to behave consistently across platforms: it should now raise OverflowError on all platforms. (Previously it raised OverflowError only on non IEEE 754 platforms.) Also fix the (already existing) test for this behaviour so that it actually raises TestFailed instead of just referencing it. ........ r61387 | thomas.heller | 2008-03-14 22:06:21 +0100 (Fri, 14 Mar 2008) | 1 line Remove unneeded initializer. ........ r61388 | martin.v.loewis | 2008-03-14 22:19:28 +0100 (Fri, 14 Mar 2008) | 2 lines Run debug version, cd to PCbuild. ........ r61392 | georg.brandl | 2008-03-15 00:10:34 +0100 (Sat, 15 Mar 2008) | 2 lines Remove obsolete paragraph. #2288. ........ r61395 | georg.brandl | 2008-03-15 01:20:19 +0100 (Sat, 15 Mar 2008) | 2 lines Fix lots of broken links in the docs, found by Sphinx' external link checker. ........ r61396 | skip.montanaro | 2008-03-15 03:32:49 +0100 (Sat, 15 Mar 2008) | 1 line note that fork and forkpty raise OSError on failure ........ r61402 | skip.montanaro | 2008-03-15 17:04:45 +0100 (Sat, 15 Mar 2008) | 1 line add %f format to datetime - issue 1158 ........ r61403 | skip.montanaro | 2008-03-15 17:07:11 +0100 (Sat, 15 Mar 2008) | 2 lines . ........
18 years ago
Merged revisions 61239-61249,61252-61257,61260-61264,61269-61275,61278-61279,61285-61286,61288-61290,61298,61303-61305,61312-61314,61317,61329,61332,61344,61350-61351,61363-61376,61378-61379,61382-61383,61387-61388,61392,61395-61396,61402-61403 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r61239 | andrew.kuchling | 2008-03-05 01:44:41 +0100 (Wed, 05 Mar 2008) | 1 line Add more items; add fragmentary notes ........ r61240 | amaury.forgeotdarc | 2008-03-05 02:50:33 +0100 (Wed, 05 Mar 2008) | 13 lines Issue#2238: some syntax errors from *args or **kwargs expressions would give bogus error messages, because of untested exceptions:: >>> f(**g(1=2)) XXX undetected error Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable instead of the expected SyntaxError: keyword can't be an expression Will backport. ........ r61241 | neal.norwitz | 2008-03-05 06:10:48 +0100 (Wed, 05 Mar 2008) | 3 lines Remove the files/dirs after closing the DB so the tests work on Windows. Patch from Trent Nelson. Also simplified removing a file by using test_support. ........ r61242 | neal.norwitz | 2008-03-05 06:14:18 +0100 (Wed, 05 Mar 2008) | 3 lines Get this test to pass even when there is no sound card in the system. Patch from Trent Nelson. (I can't test this.) ........ r61243 | neal.norwitz | 2008-03-05 06:20:44 +0100 (Wed, 05 Mar 2008) | 3 lines Catch OSError when trying to remove a file in case removal fails. This should prevent a failure in tearDown masking any real test failure. ........ r61244 | neal.norwitz | 2008-03-05 06:38:06 +0100 (Wed, 05 Mar 2008) | 5 lines Make the timeout longer to give slow machines a chance to pass the test before timing out. This doesn't change the duration of the test under normal circumstances. This is targetted at fixing the spurious failures on the FreeBSD buildbot primarily. ........ r61245 | neal.norwitz | 2008-03-05 06:49:03 +0100 (Wed, 05 Mar 2008) | 1 line Tabs -> spaces ........ r61246 | neal.norwitz | 2008-03-05 06:50:20 +0100 (Wed, 05 Mar 2008) | 1 line Use -u urlfetch to run more tests ........ r61247 | neal.norwitz | 2008-03-05 06:51:20 +0100 (Wed, 05 Mar 2008) | 1 line test_smtplib sometimes reports leaks too, suppress it ........ r61248 | jeffrey.yasskin | 2008-03-05 07:19:56 +0100 (Wed, 05 Mar 2008) | 5 lines Fix test_socketserver on Windows after r61099 added several signal.alarm() calls (which don't exist on non-Unix platforms). Thanks to Trent Nelson for the report and patch. ........ r61249 | georg.brandl | 2008-03-05 08:10:35 +0100 (Wed, 05 Mar 2008) | 2 lines Fix some rst. ........ r61252 | thomas.heller | 2008-03-05 15:53:39 +0100 (Wed, 05 Mar 2008) | 2 lines News entry for yesterdays commit. ........ r61253 | thomas.heller | 2008-03-05 16:34:29 +0100 (Wed, 05 Mar 2008) | 3 lines Issue 1872: Changed the struct module typecode from 't' to '?', for compatibility with PEP3118. ........ r61254 | skip.montanaro | 2008-03-05 17:41:09 +0100 (Wed, 05 Mar 2008) | 4 lines Elaborate on the role of the altinstall target when installing multiple versions. ........ r61255 | georg.brandl | 2008-03-05 20:31:44 +0100 (Wed, 05 Mar 2008) | 2 lines #2239: PYTHONPATH delimiter is os.pathsep. ........ r61256 | raymond.hettinger | 2008-03-05 21:59:58 +0100 (Wed, 05 Mar 2008) | 1 line C implementation of itertools.permutations(). ........ r61257 | raymond.hettinger | 2008-03-05 22:04:32 +0100 (Wed, 05 Mar 2008) | 1 line Small code cleanup. ........ r61260 | martin.v.loewis | 2008-03-05 23:24:31 +0100 (Wed, 05 Mar 2008) | 2 lines cd PCbuild only after deleting all pyc files. ........ r61261 | raymond.hettinger | 2008-03-06 02:15:52 +0100 (Thu, 06 Mar 2008) | 1 line Add examples. ........ r61262 | andrew.kuchling | 2008-03-06 02:36:27 +0100 (Thu, 06 Mar 2008) | 1 line Add two items ........ r61263 | georg.brandl | 2008-03-06 07:47:18 +0100 (Thu, 06 Mar 2008) | 2 lines #1725737: ignore other VC directories other than CVS and SVN's too. ........ r61264 | martin.v.loewis | 2008-03-06 07:55:22 +0100 (Thu, 06 Mar 2008) | 4 lines Patch #2232: os.tmpfile might fail on Windows if the user has no permission to create files in the root directory. Will backport to 2.5. ........ r61269 | georg.brandl | 2008-03-06 08:19:15 +0100 (Thu, 06 Mar 2008) | 2 lines Expand on re.split behavior with captured expressions. ........ r61270 | georg.brandl | 2008-03-06 08:22:09 +0100 (Thu, 06 Mar 2008) | 2 lines Little clarification of assignments. ........ r61271 | georg.brandl | 2008-03-06 08:31:34 +0100 (Thu, 06 Mar 2008) | 2 lines Add isinstance/issubclass to tutorial. ........ r61272 | georg.brandl | 2008-03-06 08:34:52 +0100 (Thu, 06 Mar 2008) | 2 lines Add missing NEWS entry for r61263. ........ r61273 | georg.brandl | 2008-03-06 08:41:16 +0100 (Thu, 06 Mar 2008) | 2 lines #2225: return nonzero status code from py_compile if not all files could be compiled. ........ r61274 | georg.brandl | 2008-03-06 08:43:02 +0100 (Thu, 06 Mar 2008) | 2 lines #2220: handle matching failure more gracefully. ........ r61275 | georg.brandl | 2008-03-06 08:45:52 +0100 (Thu, 06 Mar 2008) | 2 lines Bug #2220: handle rlcompleter attribute match failure more gracefully. ........ r61278 | martin.v.loewis | 2008-03-06 14:49:47 +0100 (Thu, 06 Mar 2008) | 1 line Rely on x64 platform configuration when building _bsddb on AMD64. ........ r61279 | martin.v.loewis | 2008-03-06 14:50:28 +0100 (Thu, 06 Mar 2008) | 1 line Update db-4.4.20 build procedure. ........ r61285 | raymond.hettinger | 2008-03-06 21:52:01 +0100 (Thu, 06 Mar 2008) | 1 line More tests. ........ r61286 | raymond.hettinger | 2008-03-06 23:51:36 +0100 (Thu, 06 Mar 2008) | 1 line Issue 2246: itertools grouper object did not participate in GC (should be backported). ........ r61288 | raymond.hettinger | 2008-03-07 02:33:20 +0100 (Fri, 07 Mar 2008) | 1 line Tweak recipes and tests ........ r61289 | jeffrey.yasskin | 2008-03-07 07:22:15 +0100 (Fri, 07 Mar 2008) | 5 lines Progress on issue #1193577 by adding a polling .shutdown() method to SocketServers. The core of the patch was written by Pedro Werneck, but any bugs are mine. I've also rearranged the code for timeouts in order to avoid interfering with the shutdown poll. ........ r61290 | nick.coghlan | 2008-03-07 15:13:28 +0100 (Fri, 07 Mar 2008) | 1 line Speed up with statements by storing the __exit__ method on the stack instead of in a temp variable (bumps the magic number for pyc files) ........ r61298 | andrew.kuchling | 2008-03-07 22:09:23 +0100 (Fri, 07 Mar 2008) | 1 line Grammar fix ........ r61303 | georg.brandl | 2008-03-08 10:54:06 +0100 (Sat, 08 Mar 2008) | 2 lines #2253: fix continue vs. finally docs. ........ r61304 | marc-andre.lemburg | 2008-03-08 11:01:43 +0100 (Sat, 08 Mar 2008) | 3 lines Add new name for Mandrake: Mandriva. ........ r61305 | georg.brandl | 2008-03-08 11:05:24 +0100 (Sat, 08 Mar 2008) | 2 lines #1533486: fix types in refcount intro. ........ r61312 | facundo.batista | 2008-03-08 17:50:27 +0100 (Sat, 08 Mar 2008) | 5 lines Issue 1106316. post_mortem()'s parameter, traceback, is now optional: it defaults to the traceback of the exception that is currently being handled. ........ r61313 | jeffrey.yasskin | 2008-03-08 19:26:54 +0100 (Sat, 08 Mar 2008) | 2 lines Add tests for with and finally performance to pybench. ........ r61314 | jeffrey.yasskin | 2008-03-08 21:08:21 +0100 (Sat, 08 Mar 2008) | 2 lines Fix pybench for pythons < 2.6, tested back to 2.3. ........ r61317 | jeffrey.yasskin | 2008-03-08 22:35:15 +0100 (Sat, 08 Mar 2008) | 3 lines Well that was dumb. platform.python_implementation returns a function, not a string. ........ r61329 | georg.brandl | 2008-03-09 16:11:39 +0100 (Sun, 09 Mar 2008) | 2 lines #2249: document assertTrue and assertFalse. ........ r61332 | neal.norwitz | 2008-03-09 20:03:42 +0100 (Sun, 09 Mar 2008) | 4 lines Introduce a lock to fix a race condition which caused an exception in the test. Some buildbots were consistently failing (e.g., amd64). Also remove a couple of semi-colons. ........ r61344 | raymond.hettinger | 2008-03-11 01:19:07 +0100 (Tue, 11 Mar 2008) | 1 line Add recipe to docs. ........ r61350 | guido.van.rossum | 2008-03-11 22:18:06 +0100 (Tue, 11 Mar 2008) | 3 lines Fix the overflows in expandtabs(). "This time for sure!" (Exploit at request.) ........ r61351 | raymond.hettinger | 2008-03-11 22:37:46 +0100 (Tue, 11 Mar 2008) | 1 line Improve docs for itemgetter(). Show that it works with slices. ........ r61363 | georg.brandl | 2008-03-13 08:15:56 +0100 (Thu, 13 Mar 2008) | 2 lines #2265: fix example. ........ r61364 | georg.brandl | 2008-03-13 08:17:14 +0100 (Thu, 13 Mar 2008) | 2 lines #2270: fix typo. ........ r61365 | georg.brandl | 2008-03-13 08:21:41 +0100 (Thu, 13 Mar 2008) | 2 lines #1720705: add docs about import/threading interaction, wording by Nick. ........ r61366 | andrew.kuchling | 2008-03-13 12:07:35 +0100 (Thu, 13 Mar 2008) | 1 line Add class decorators ........ r61367 | raymond.hettinger | 2008-03-13 17:43:17 +0100 (Thu, 13 Mar 2008) | 1 line Add 2-to-3 support for the itertools moved to builtins or renamed. ........ r61368 | raymond.hettinger | 2008-03-13 17:43:59 +0100 (Thu, 13 Mar 2008) | 1 line Consistent tense. ........ r61369 | raymond.hettinger | 2008-03-13 20:03:51 +0100 (Thu, 13 Mar 2008) | 1 line Issue 2274: Add heapq.heappushpop(). ........ r61370 | raymond.hettinger | 2008-03-13 20:33:34 +0100 (Thu, 13 Mar 2008) | 1 line Simplify the nlargest() code using heappushpop(). ........ r61371 | brett.cannon | 2008-03-13 21:27:00 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_thread over to unittest. Commits GHOP 237. Thanks Benjamin Peterson for the patch. ........ r61372 | brett.cannon | 2008-03-13 21:33:10 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_tokenize to doctest. Done as GHOP 238 by Josip Dzolonga. ........ r61373 | brett.cannon | 2008-03-13 21:47:41 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_contains, test_crypt, and test_select to unittest. Patch from GHOP 294 by David Marek. ........ r61374 | brett.cannon | 2008-03-13 22:02:16 +0100 (Thu, 13 Mar 2008) | 4 lines Move test_gdbm to use unittest. Closes issue #1960. Thanks Giampaolo Rodola. ........ r61375 | brett.cannon | 2008-03-13 22:09:28 +0100 (Thu, 13 Mar 2008) | 4 lines Convert test_fcntl to unittest. Closes issue #2055. Thanks Giampaolo Rodola. ........ r61376 | raymond.hettinger | 2008-03-14 06:03:44 +0100 (Fri, 14 Mar 2008) | 1 line Leave heapreplace() unchanged. ........ r61378 | martin.v.loewis | 2008-03-14 14:56:09 +0100 (Fri, 14 Mar 2008) | 2 lines Patch #2284: add -x64 option to rt.bat. ........ r61379 | martin.v.loewis | 2008-03-14 14:57:59 +0100 (Fri, 14 Mar 2008) | 2 lines Use -x64 flag. ........ r61382 | brett.cannon | 2008-03-14 15:03:10 +0100 (Fri, 14 Mar 2008) | 2 lines Remove a bad test. ........ r61383 | mark.dickinson | 2008-03-14 15:23:37 +0100 (Fri, 14 Mar 2008) | 9 lines Issue 705836: Fix struct.pack(">f", 1e40) to behave consistently across platforms: it should now raise OverflowError on all platforms. (Previously it raised OverflowError only on non IEEE 754 platforms.) Also fix the (already existing) test for this behaviour so that it actually raises TestFailed instead of just referencing it. ........ r61387 | thomas.heller | 2008-03-14 22:06:21 +0100 (Fri, 14 Mar 2008) | 1 line Remove unneeded initializer. ........ r61388 | martin.v.loewis | 2008-03-14 22:19:28 +0100 (Fri, 14 Mar 2008) | 2 lines Run debug version, cd to PCbuild. ........ r61392 | georg.brandl | 2008-03-15 00:10:34 +0100 (Sat, 15 Mar 2008) | 2 lines Remove obsolete paragraph. #2288. ........ r61395 | georg.brandl | 2008-03-15 01:20:19 +0100 (Sat, 15 Mar 2008) | 2 lines Fix lots of broken links in the docs, found by Sphinx' external link checker. ........ r61396 | skip.montanaro | 2008-03-15 03:32:49 +0100 (Sat, 15 Mar 2008) | 1 line note that fork and forkpty raise OSError on failure ........ r61402 | skip.montanaro | 2008-03-15 17:04:45 +0100 (Sat, 15 Mar 2008) | 1 line add %f format to datetime - issue 1158 ........ r61403 | skip.montanaro | 2008-03-15 17:07:11 +0100 (Sat, 15 Mar 2008) | 2 lines . ........
18 years ago
20 years ago
9 years ago
9 years ago
20 years ago
20 years ago
  1. /* C implementation for the date/time type documented at
  2. * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
  3. */
  4. /* bpo-35081: Defining this prevents including the C API capsule;
  5. * internal versions of the Py*_Check macros which do not require
  6. * the capsule are defined below */
  7. #define _PY_DATETIME_IMPL
  8. #include "Python.h"
  9. #include "pycore_long.h" // _PyLong_GetOne()
  10. #include "pycore_object.h" // _PyObject_Init()
  11. #include "datetime.h"
  12. #include "structmember.h" // PyMemberDef
  13. #include <time.h>
  14. #ifdef MS_WINDOWS
  15. # include <winsock2.h> /* struct timeval */
  16. #endif
  17. #define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType)
  18. #define PyDate_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DateType)
  19. #define PyDateTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateTimeType)
  20. #define PyDateTime_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DateTimeType)
  21. #define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType)
  22. #define PyTime_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TimeType)
  23. #define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType)
  24. #define PyDelta_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DeltaType)
  25. #define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType)
  26. #define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TZInfoType)
  27. #define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType)
  28. /*[clinic input]
  29. module datetime
  30. class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType"
  31. class datetime.date "PyDateTime_Date *" "&PyDateTime_DateType"
  32. class datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "&PyDateTime_IsoCalendarDateType"
  33. [clinic start generated code]*/
  34. /*[clinic end generated code: output=da39a3ee5e6b4b0d input=81bec0fa19837f63]*/
  35. #include "clinic/_datetimemodule.c.h"
  36. /* We require that C int be at least 32 bits, and use int virtually
  37. * everywhere. In just a few cases we use a temp long, where a Python
  38. * API returns a C long. In such cases, we have to ensure that the
  39. * final result fits in a C int (this can be an issue on 64-bit boxes).
  40. */
  41. #if SIZEOF_INT < 4
  42. # error "_datetime.c requires that C int have at least 32 bits"
  43. #endif
  44. #define MINYEAR 1
  45. #define MAXYEAR 9999
  46. #define MAXORDINAL 3652059 /* date(9999,12,31).toordinal() */
  47. /* Nine decimal digits is easy to communicate, and leaves enough room
  48. * so that two delta days can be added w/o fear of overflowing a signed
  49. * 32-bit int, and with plenty of room left over to absorb any possible
  50. * carries from adding seconds.
  51. */
  52. #define MAX_DELTA_DAYS 999999999
  53. /* Rename the long macros in datetime.h to more reasonable short names. */
  54. #define GET_YEAR PyDateTime_GET_YEAR
  55. #define GET_MONTH PyDateTime_GET_MONTH
  56. #define GET_DAY PyDateTime_GET_DAY
  57. #define DATE_GET_HOUR PyDateTime_DATE_GET_HOUR
  58. #define DATE_GET_MINUTE PyDateTime_DATE_GET_MINUTE
  59. #define DATE_GET_SECOND PyDateTime_DATE_GET_SECOND
  60. #define DATE_GET_MICROSECOND PyDateTime_DATE_GET_MICROSECOND
  61. #define DATE_GET_FOLD PyDateTime_DATE_GET_FOLD
  62. /* Date accessors for date and datetime. */
  63. #define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \
  64. ((o)->data[1] = ((v) & 0x00ff)))
  65. #define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v))
  66. #define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v))
  67. /* Date/Time accessors for datetime. */
  68. #define DATE_SET_HOUR(o, v) (PyDateTime_DATE_GET_HOUR(o) = (v))
  69. #define DATE_SET_MINUTE(o, v) (PyDateTime_DATE_GET_MINUTE(o) = (v))
  70. #define DATE_SET_SECOND(o, v) (PyDateTime_DATE_GET_SECOND(o) = (v))
  71. #define DATE_SET_MICROSECOND(o, v) \
  72. (((o)->data[7] = ((v) & 0xff0000) >> 16), \
  73. ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
  74. ((o)->data[9] = ((v) & 0x0000ff)))
  75. #define DATE_SET_FOLD(o, v) (PyDateTime_DATE_GET_FOLD(o) = (v))
  76. /* Time accessors for time. */
  77. #define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR
  78. #define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE
  79. #define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND
  80. #define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND
  81. #define TIME_GET_FOLD PyDateTime_TIME_GET_FOLD
  82. #define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v))
  83. #define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v))
  84. #define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v))
  85. #define TIME_SET_MICROSECOND(o, v) \
  86. (((o)->data[3] = ((v) & 0xff0000) >> 16), \
  87. ((o)->data[4] = ((v) & 0x00ff00) >> 8), \
  88. ((o)->data[5] = ((v) & 0x0000ff)))
  89. #define TIME_SET_FOLD(o, v) (PyDateTime_TIME_GET_FOLD(o) = (v))
  90. /* Delta accessors for timedelta. */
  91. #define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days)
  92. #define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds)
  93. #define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds)
  94. #define SET_TD_DAYS(o, v) ((o)->days = (v))
  95. #define SET_TD_SECONDS(o, v) ((o)->seconds = (v))
  96. #define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
  97. #define HASTZINFO _PyDateTime_HAS_TZINFO
  98. #define GET_TIME_TZINFO PyDateTime_TIME_GET_TZINFO
  99. #define GET_DT_TZINFO PyDateTime_DATE_GET_TZINFO
  100. /* M is a char or int claiming to be a valid month. The macro is equivalent
  101. * to the two-sided Python test
  102. * 1 <= M <= 12
  103. */
  104. #define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12)
  105. /* Forward declarations. */
  106. static PyTypeObject PyDateTime_DateType;
  107. static PyTypeObject PyDateTime_DateTimeType;
  108. static PyTypeObject PyDateTime_DeltaType;
  109. static PyTypeObject PyDateTime_IsoCalendarDateType;
  110. static PyTypeObject PyDateTime_TimeType;
  111. static PyTypeObject PyDateTime_TZInfoType;
  112. static PyTypeObject PyDateTime_TimeZoneType;
  113. static int check_tzinfo_subclass(PyObject *p);
  114. _Py_IDENTIFIER(as_integer_ratio);
  115. _Py_IDENTIFIER(fromutc);
  116. _Py_IDENTIFIER(isoformat);
  117. _Py_IDENTIFIER(strftime);
  118. /* ---------------------------------------------------------------------------
  119. * Math utilities.
  120. */
  121. /* k = i+j overflows iff k differs in sign from both inputs,
  122. * iff k^i has sign bit set and k^j has sign bit set,
  123. * iff (k^i)&(k^j) has sign bit set.
  124. */
  125. #define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
  126. ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
  127. /* Compute Python divmod(x, y), returning the quotient and storing the
  128. * remainder into *r. The quotient is the floor of x/y, and that's
  129. * the real point of this. C will probably truncate instead (C99
  130. * requires truncation; C89 left it implementation-defined).
  131. * Simplification: we *require* that y > 0 here. That's appropriate
  132. * for all the uses made of it. This simplifies the code and makes
  133. * the overflow case impossible (divmod(LONG_MIN, -1) is the only
  134. * overflow case).
  135. */
  136. static int
  137. divmod(int x, int y, int *r)
  138. {
  139. int quo;
  140. assert(y > 0);
  141. quo = x / y;
  142. *r = x - quo * y;
  143. if (*r < 0) {
  144. --quo;
  145. *r += y;
  146. }
  147. assert(0 <= *r && *r < y);
  148. return quo;
  149. }
  150. /* Nearest integer to m / n for integers m and n. Half-integer results
  151. * are rounded to even.
  152. */
  153. static PyObject *
  154. divide_nearest(PyObject *m, PyObject *n)
  155. {
  156. PyObject *result;
  157. PyObject *temp;
  158. temp = _PyLong_DivmodNear(m, n);
  159. if (temp == NULL)
  160. return NULL;
  161. result = PyTuple_GET_ITEM(temp, 0);
  162. Py_INCREF(result);
  163. Py_DECREF(temp);
  164. return result;
  165. }
  166. /* ---------------------------------------------------------------------------
  167. * General calendrical helper functions
  168. */
  169. /* For each month ordinal in 1..12, the number of days in that month,
  170. * and the number of days before that month in the same year. These
  171. * are correct for non-leap years only.
  172. */
  173. static const int _days_in_month[] = {
  174. 0, /* unused; this vector uses 1-based indexing */
  175. 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  176. };
  177. static const int _days_before_month[] = {
  178. 0, /* unused; this vector uses 1-based indexing */
  179. 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  180. };
  181. /* year -> 1 if leap year, else 0. */
  182. static int
  183. is_leap(int year)
  184. {
  185. /* Cast year to unsigned. The result is the same either way, but
  186. * C can generate faster code for unsigned mod than for signed
  187. * mod (especially for % 4 -- a good compiler should just grab
  188. * the last 2 bits when the LHS is unsigned).
  189. */
  190. const unsigned int ayear = (unsigned int)year;
  191. return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
  192. }
  193. /* year, month -> number of days in that month in that year */
  194. static int
  195. days_in_month(int year, int month)
  196. {
  197. assert(month >= 1);
  198. assert(month <= 12);
  199. if (month == 2 && is_leap(year))
  200. return 29;
  201. else
  202. return _days_in_month[month];
  203. }
  204. /* year, month -> number of days in year preceding first day of month */
  205. static int
  206. days_before_month(int year, int month)
  207. {
  208. int days;
  209. assert(month >= 1);
  210. assert(month <= 12);
  211. days = _days_before_month[month];
  212. if (month > 2 && is_leap(year))
  213. ++days;
  214. return days;
  215. }
  216. /* year -> number of days before January 1st of year. Remember that we
  217. * start with year 1, so days_before_year(1) == 0.
  218. */
  219. static int
  220. days_before_year(int year)
  221. {
  222. int y = year - 1;
  223. /* This is incorrect if year <= 0; we really want the floor
  224. * here. But so long as MINYEAR is 1, the smallest year this
  225. * can see is 1.
  226. */
  227. assert (year >= 1);
  228. return y*365 + y/4 - y/100 + y/400;
  229. }
  230. /* Number of days in 4, 100, and 400 year cycles. That these have
  231. * the correct values is asserted in the module init function.
  232. */
  233. #define DI4Y 1461 /* days_before_year(5); days in 4 years */
  234. #define DI100Y 36524 /* days_before_year(101); days in 100 years */
  235. #define DI400Y 146097 /* days_before_year(401); days in 400 years */
  236. /* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
  237. static void
  238. ord_to_ymd(int ordinal, int *year, int *month, int *day)
  239. {
  240. int n, n1, n4, n100, n400, leapyear, preceding;
  241. /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
  242. * leap years repeats exactly every 400 years. The basic strategy is
  243. * to find the closest 400-year boundary at or before ordinal, then
  244. * work with the offset from that boundary to ordinal. Life is much
  245. * clearer if we subtract 1 from ordinal first -- then the values
  246. * of ordinal at 400-year boundaries are exactly those divisible
  247. * by DI400Y:
  248. *
  249. * D M Y n n-1
  250. * -- --- ---- ---------- ----------------
  251. * 31 Dec -400 -DI400Y -DI400Y -1
  252. * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
  253. * ...
  254. * 30 Dec 000 -1 -2
  255. * 31 Dec 000 0 -1
  256. * 1 Jan 001 1 0 400-year boundary
  257. * 2 Jan 001 2 1
  258. * 3 Jan 001 3 2
  259. * ...
  260. * 31 Dec 400 DI400Y DI400Y -1
  261. * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
  262. */
  263. assert(ordinal >= 1);
  264. --ordinal;
  265. n400 = ordinal / DI400Y;
  266. n = ordinal % DI400Y;
  267. *year = n400 * 400 + 1;
  268. /* Now n is the (non-negative) offset, in days, from January 1 of
  269. * year, to the desired date. Now compute how many 100-year cycles
  270. * precede n.
  271. * Note that it's possible for n100 to equal 4! In that case 4 full
  272. * 100-year cycles precede the desired day, which implies the
  273. * desired day is December 31 at the end of a 400-year cycle.
  274. */
  275. n100 = n / DI100Y;
  276. n = n % DI100Y;
  277. /* Now compute how many 4-year cycles precede it. */
  278. n4 = n / DI4Y;
  279. n = n % DI4Y;
  280. /* And now how many single years. Again n1 can be 4, and again
  281. * meaning that the desired day is December 31 at the end of the
  282. * 4-year cycle.
  283. */
  284. n1 = n / 365;
  285. n = n % 365;
  286. *year += n100 * 100 + n4 * 4 + n1;
  287. if (n1 == 4 || n100 == 4) {
  288. assert(n == 0);
  289. *year -= 1;
  290. *month = 12;
  291. *day = 31;
  292. return;
  293. }
  294. /* Now the year is correct, and n is the offset from January 1. We
  295. * find the month via an estimate that's either exact or one too
  296. * large.
  297. */
  298. leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
  299. assert(leapyear == is_leap(*year));
  300. *month = (n + 50) >> 5;
  301. preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
  302. if (preceding > n) {
  303. /* estimate is too large */
  304. *month -= 1;
  305. preceding -= days_in_month(*year, *month);
  306. }
  307. n -= preceding;
  308. assert(0 <= n);
  309. assert(n < days_in_month(*year, *month));
  310. *day = n + 1;
  311. }
  312. /* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
  313. static int
  314. ymd_to_ord(int year, int month, int day)
  315. {
  316. return days_before_year(year) + days_before_month(year, month) + day;
  317. }
  318. /* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
  319. static int
  320. weekday(int year, int month, int day)
  321. {
  322. return (ymd_to_ord(year, month, day) + 6) % 7;
  323. }
  324. /* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
  325. * first calendar week containing a Thursday.
  326. */
  327. static int
  328. iso_week1_monday(int year)
  329. {
  330. int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
  331. /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
  332. int first_weekday = (first_day + 6) % 7;
  333. /* ordinal of closest Monday at or before 1/1 */
  334. int week1_monday = first_day - first_weekday;
  335. if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
  336. week1_monday += 7;
  337. return week1_monday;
  338. }
  339. /* ---------------------------------------------------------------------------
  340. * Range checkers.
  341. */
  342. /* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
  343. * If not, raise OverflowError and return -1.
  344. */
  345. static int
  346. check_delta_day_range(int days)
  347. {
  348. if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
  349. return 0;
  350. PyErr_Format(PyExc_OverflowError,
  351. "days=%d; must have magnitude <= %d",
  352. days, MAX_DELTA_DAYS);
  353. return -1;
  354. }
  355. /* Check that date arguments are in range. Return 0 if they are. If they
  356. * aren't, raise ValueError and return -1.
  357. */
  358. static int
  359. check_date_args(int year, int month, int day)
  360. {
  361. if (year < MINYEAR || year > MAXYEAR) {
  362. PyErr_Format(PyExc_ValueError, "year %i is out of range", year);
  363. return -1;
  364. }
  365. if (month < 1 || month > 12) {
  366. PyErr_SetString(PyExc_ValueError,
  367. "month must be in 1..12");
  368. return -1;
  369. }
  370. if (day < 1 || day > days_in_month(year, month)) {
  371. PyErr_SetString(PyExc_ValueError,
  372. "day is out of range for month");
  373. return -1;
  374. }
  375. return 0;
  376. }
  377. /* Check that time arguments are in range. Return 0 if they are. If they
  378. * aren't, raise ValueError and return -1.
  379. */
  380. static int
  381. check_time_args(int h, int m, int s, int us, int fold)
  382. {
  383. if (h < 0 || h > 23) {
  384. PyErr_SetString(PyExc_ValueError,
  385. "hour must be in 0..23");
  386. return -1;
  387. }
  388. if (m < 0 || m > 59) {
  389. PyErr_SetString(PyExc_ValueError,
  390. "minute must be in 0..59");
  391. return -1;
  392. }
  393. if (s < 0 || s > 59) {
  394. PyErr_SetString(PyExc_ValueError,
  395. "second must be in 0..59");
  396. return -1;
  397. }
  398. if (us < 0 || us > 999999) {
  399. PyErr_SetString(PyExc_ValueError,
  400. "microsecond must be in 0..999999");
  401. return -1;
  402. }
  403. if (fold != 0 && fold != 1) {
  404. PyErr_SetString(PyExc_ValueError,
  405. "fold must be either 0 or 1");
  406. return -1;
  407. }
  408. return 0;
  409. }
  410. /* ---------------------------------------------------------------------------
  411. * Normalization utilities.
  412. */
  413. /* One step of a mixed-radix conversion. A "hi" unit is equivalent to
  414. * factor "lo" units. factor must be > 0. If *lo is less than 0, or
  415. * at least factor, enough of *lo is converted into "hi" units so that
  416. * 0 <= *lo < factor. The input values must be such that int overflow
  417. * is impossible.
  418. */
  419. static void
  420. normalize_pair(int *hi, int *lo, int factor)
  421. {
  422. assert(factor > 0);
  423. assert(lo != hi);
  424. if (*lo < 0 || *lo >= factor) {
  425. const int num_hi = divmod(*lo, factor, lo);
  426. const int new_hi = *hi + num_hi;
  427. assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
  428. *hi = new_hi;
  429. }
  430. assert(0 <= *lo && *lo < factor);
  431. }
  432. /* Fiddle days (d), seconds (s), and microseconds (us) so that
  433. * 0 <= *s < 24*3600
  434. * 0 <= *us < 1000000
  435. * The input values must be such that the internals don't overflow.
  436. * The way this routine is used, we don't get close.
  437. */
  438. static void
  439. normalize_d_s_us(int *d, int *s, int *us)
  440. {
  441. if (*us < 0 || *us >= 1000000) {
  442. normalize_pair(s, us, 1000000);
  443. /* |s| can't be bigger than about
  444. * |original s| + |original us|/1000000 now.
  445. */
  446. }
  447. if (*s < 0 || *s >= 24*3600) {
  448. normalize_pair(d, s, 24*3600);
  449. /* |d| can't be bigger than about
  450. * |original d| +
  451. * (|original s| + |original us|/1000000) / (24*3600) now.
  452. */
  453. }
  454. assert(0 <= *s && *s < 24*3600);
  455. assert(0 <= *us && *us < 1000000);
  456. }
  457. /* Fiddle years (y), months (m), and days (d) so that
  458. * 1 <= *m <= 12
  459. * 1 <= *d <= days_in_month(*y, *m)
  460. * The input values must be such that the internals don't overflow.
  461. * The way this routine is used, we don't get close.
  462. */
  463. static int
  464. normalize_y_m_d(int *y, int *m, int *d)
  465. {
  466. int dim; /* # of days in month */
  467. /* In actual use, m is always the month component extracted from a
  468. * date/datetime object. Therefore it is always in [1, 12] range.
  469. */
  470. assert(1 <= *m && *m <= 12);
  471. /* Now only day can be out of bounds (year may also be out of bounds
  472. * for a datetime object, but we don't care about that here).
  473. * If day is out of bounds, what to do is arguable, but at least the
  474. * method here is principled and explainable.
  475. */
  476. dim = days_in_month(*y, *m);
  477. if (*d < 1 || *d > dim) {
  478. /* Move day-1 days from the first of the month. First try to
  479. * get off cheap if we're only one day out of range
  480. * (adjustments for timezone alone can't be worse than that).
  481. */
  482. if (*d == 0) {
  483. --*m;
  484. if (*m > 0)
  485. *d = days_in_month(*y, *m);
  486. else {
  487. --*y;
  488. *m = 12;
  489. *d = 31;
  490. }
  491. }
  492. else if (*d == dim + 1) {
  493. /* move forward a day */
  494. ++*m;
  495. *d = 1;
  496. if (*m > 12) {
  497. *m = 1;
  498. ++*y;
  499. }
  500. }
  501. else {
  502. int ordinal = ymd_to_ord(*y, *m, 1) +
  503. *d - 1;
  504. if (ordinal < 1 || ordinal > MAXORDINAL) {
  505. goto error;
  506. } else {
  507. ord_to_ymd(ordinal, y, m, d);
  508. return 0;
  509. }
  510. }
  511. }
  512. assert(*m > 0);
  513. assert(*d > 0);
  514. if (MINYEAR <= *y && *y <= MAXYEAR)
  515. return 0;
  516. error:
  517. PyErr_SetString(PyExc_OverflowError,
  518. "date value out of range");
  519. return -1;
  520. }
  521. /* Fiddle out-of-bounds months and days so that the result makes some kind
  522. * of sense. The parameters are both inputs and outputs. Returns < 0 on
  523. * failure, where failure means the adjusted year is out of bounds.
  524. */
  525. static int
  526. normalize_date(int *year, int *month, int *day)
  527. {
  528. return normalize_y_m_d(year, month, day);
  529. }
  530. /* Force all the datetime fields into range. The parameters are both
  531. * inputs and outputs. Returns < 0 on error.
  532. */
  533. static int
  534. normalize_datetime(int *year, int *month, int *day,
  535. int *hour, int *minute, int *second,
  536. int *microsecond)
  537. {
  538. normalize_pair(second, microsecond, 1000000);
  539. normalize_pair(minute, second, 60);
  540. normalize_pair(hour, minute, 60);
  541. normalize_pair(day, hour, 24);
  542. return normalize_date(year, month, day);
  543. }
  544. /* ---------------------------------------------------------------------------
  545. * Basic object allocation: tp_alloc implementations. These allocate
  546. * Python objects of the right size and type, and do the Python object-
  547. * initialization bit. If there's not enough memory, they return NULL after
  548. * setting MemoryError. All data members remain uninitialized trash.
  549. *
  550. * We abuse the tp_alloc "nitems" argument to communicate whether a tzinfo
  551. * member is needed. This is ugly, imprecise, and possibly insecure.
  552. * tp_basicsize for the time and datetime types is set to the size of the
  553. * struct that has room for the tzinfo member, so subclasses in Python will
  554. * allocate enough space for a tzinfo member whether or not one is actually
  555. * needed. That's the "ugly and imprecise" parts. The "possibly insecure"
  556. * part is that PyType_GenericAlloc() (which subclasses in Python end up
  557. * using) just happens today to effectively ignore the nitems argument
  558. * when tp_itemsize is 0, which it is for these type objects. If that
  559. * changes, perhaps the callers of tp_alloc slots in this file should
  560. * be changed to force a 0 nitems argument unless the type being allocated
  561. * is a base type implemented in this file (so that tp_alloc is time_alloc
  562. * or datetime_alloc below, which know about the nitems abuse).
  563. */
  564. static PyObject *
  565. time_alloc(PyTypeObject *type, Py_ssize_t aware)
  566. {
  567. size_t size = aware ? sizeof(PyDateTime_Time) : sizeof(_PyDateTime_BaseTime);
  568. PyObject *self = (PyObject *)PyObject_Malloc(size);
  569. if (self == NULL) {
  570. return PyErr_NoMemory();
  571. }
  572. _PyObject_Init(self, type);
  573. return self;
  574. }
  575. static PyObject *
  576. datetime_alloc(PyTypeObject *type, Py_ssize_t aware)
  577. {
  578. size_t size = aware ? sizeof(PyDateTime_DateTime) : sizeof(_PyDateTime_BaseDateTime);
  579. PyObject *self = (PyObject *)PyObject_Malloc(size);
  580. if (self == NULL) {
  581. return PyErr_NoMemory();
  582. }
  583. _PyObject_Init(self, type);
  584. return self;
  585. }
  586. /* ---------------------------------------------------------------------------
  587. * Helpers for setting object fields. These work on pointers to the
  588. * appropriate base class.
  589. */
  590. /* For date and datetime. */
  591. static void
  592. set_date_fields(PyDateTime_Date *self, int y, int m, int d)
  593. {
  594. self->hashcode = -1;
  595. SET_YEAR(self, y);
  596. SET_MONTH(self, m);
  597. SET_DAY(self, d);
  598. }
  599. /* ---------------------------------------------------------------------------
  600. * String parsing utilities and helper functions
  601. */
  602. static const char *
  603. parse_digits(const char *ptr, int *var, size_t num_digits)
  604. {
  605. for (size_t i = 0; i < num_digits; ++i) {
  606. unsigned int tmp = (unsigned int)(*(ptr++) - '0');
  607. if (tmp > 9) {
  608. return NULL;
  609. }
  610. *var *= 10;
  611. *var += (signed int)tmp;
  612. }
  613. return ptr;
  614. }
  615. static int
  616. parse_isoformat_date(const char *dtstr, int *year, int *month, int *day)
  617. {
  618. /* Parse the date components of the result of date.isoformat()
  619. *
  620. * Return codes:
  621. * 0: Success
  622. * -1: Failed to parse date component
  623. * -2: Failed to parse dateseparator
  624. */
  625. const char *p = dtstr;
  626. p = parse_digits(p, year, 4);
  627. if (NULL == p) {
  628. return -1;
  629. }
  630. if (*(p++) != '-') {
  631. return -2;
  632. }
  633. p = parse_digits(p, month, 2);
  634. if (NULL == p) {
  635. return -1;
  636. }
  637. if (*(p++) != '-') {
  638. return -2;
  639. }
  640. p = parse_digits(p, day, 2);
  641. if (p == NULL) {
  642. return -1;
  643. }
  644. return 0;
  645. }
  646. static int
  647. parse_hh_mm_ss_ff(const char *tstr, const char *tstr_end, int *hour,
  648. int *minute, int *second, int *microsecond)
  649. {
  650. const char *p = tstr;
  651. const char *p_end = tstr_end;
  652. int *vals[3] = {hour, minute, second};
  653. // Parse [HH[:MM[:SS]]]
  654. for (size_t i = 0; i < 3; ++i) {
  655. p = parse_digits(p, vals[i], 2);
  656. if (NULL == p) {
  657. return -3;
  658. }
  659. char c = *(p++);
  660. if (p >= p_end) {
  661. return c != '\0';
  662. }
  663. else if (c == ':') {
  664. continue;
  665. }
  666. else if (c == '.') {
  667. break;
  668. }
  669. else {
  670. return -4; // Malformed time separator
  671. }
  672. }
  673. // Parse .fff[fff]
  674. size_t len_remains = p_end - p;
  675. if (!(len_remains == 6 || len_remains == 3)) {
  676. return -3;
  677. }
  678. p = parse_digits(p, microsecond, len_remains);
  679. if (NULL == p) {
  680. return -3;
  681. }
  682. if (len_remains == 3) {
  683. *microsecond *= 1000;
  684. }
  685. // Return 1 if it's not the end of the string
  686. return *p != '\0';
  687. }
  688. static int
  689. parse_isoformat_time(const char *dtstr, size_t dtlen, int *hour, int *minute,
  690. int *second, int *microsecond, int *tzoffset,
  691. int *tzmicrosecond)
  692. {
  693. // Parse the time portion of a datetime.isoformat() string
  694. //
  695. // Return codes:
  696. // 0: Success (no tzoffset)
  697. // 1: Success (with tzoffset)
  698. // -3: Failed to parse time component
  699. // -4: Failed to parse time separator
  700. // -5: Malformed timezone string
  701. const char *p = dtstr;
  702. const char *p_end = dtstr + dtlen;
  703. const char *tzinfo_pos = p;
  704. do {
  705. if (*tzinfo_pos == '+' || *tzinfo_pos == '-') {
  706. break;
  707. }
  708. } while (++tzinfo_pos < p_end);
  709. int rv = parse_hh_mm_ss_ff(dtstr, tzinfo_pos, hour, minute, second,
  710. microsecond);
  711. if (rv < 0) {
  712. return rv;
  713. }
  714. else if (tzinfo_pos == p_end) {
  715. // We know that there's no time zone, so if there's stuff at the
  716. // end of the string it's an error.
  717. if (rv == 1) {
  718. return -5;
  719. }
  720. else {
  721. return 0;
  722. }
  723. }
  724. // Parse time zone component
  725. // Valid formats are:
  726. // - +HH:MM (len 6)
  727. // - +HH:MM:SS (len 9)
  728. // - +HH:MM:SS.ffffff (len 16)
  729. size_t tzlen = p_end - tzinfo_pos;
  730. if (!(tzlen == 6 || tzlen == 9 || tzlen == 16)) {
  731. return -5;
  732. }
  733. int tzsign = (*tzinfo_pos == '-') ? -1 : 1;
  734. tzinfo_pos++;
  735. int tzhour = 0, tzminute = 0, tzsecond = 0;
  736. rv = parse_hh_mm_ss_ff(tzinfo_pos, p_end, &tzhour, &tzminute, &tzsecond,
  737. tzmicrosecond);
  738. *tzoffset = tzsign * ((tzhour * 3600) + (tzminute * 60) + tzsecond);
  739. *tzmicrosecond *= tzsign;
  740. return rv ? -5 : 1;
  741. }
  742. /* ---------------------------------------------------------------------------
  743. * Create various objects, mostly without range checking.
  744. */
  745. /* Create a date instance with no range checking. */
  746. static PyObject *
  747. new_date_ex(int year, int month, int day, PyTypeObject *type)
  748. {
  749. PyDateTime_Date *self;
  750. if (check_date_args(year, month, day) < 0) {
  751. return NULL;
  752. }
  753. self = (PyDateTime_Date *)(type->tp_alloc(type, 0));
  754. if (self != NULL)
  755. set_date_fields(self, year, month, day);
  756. return (PyObject *)self;
  757. }
  758. #define new_date(year, month, day) \
  759. new_date_ex(year, month, day, &PyDateTime_DateType)
  760. // Forward declaration
  761. static PyObject *
  762. new_datetime_ex(int, int, int, int, int, int, int, PyObject *, PyTypeObject *);
  763. /* Create date instance with no range checking, or call subclass constructor */
  764. static PyObject *
  765. new_date_subclass_ex(int year, int month, int day, PyObject *cls)
  766. {
  767. PyObject *result;
  768. // We have "fast path" constructors for two subclasses: date and datetime
  769. if ((PyTypeObject *)cls == &PyDateTime_DateType) {
  770. result = new_date_ex(year, month, day, (PyTypeObject *)cls);
  771. }
  772. else if ((PyTypeObject *)cls == &PyDateTime_DateTimeType) {
  773. result = new_datetime_ex(year, month, day, 0, 0, 0, 0, Py_None,
  774. (PyTypeObject *)cls);
  775. }
  776. else {
  777. result = PyObject_CallFunction(cls, "iii", year, month, day);
  778. }
  779. return result;
  780. }
  781. /* Create a datetime instance with no range checking. */
  782. static PyObject *
  783. new_datetime_ex2(int year, int month, int day, int hour, int minute,
  784. int second, int usecond, PyObject *tzinfo, int fold, PyTypeObject *type)
  785. {
  786. PyDateTime_DateTime *self;
  787. char aware = tzinfo != Py_None;
  788. if (check_date_args(year, month, day) < 0) {
  789. return NULL;
  790. }
  791. if (check_time_args(hour, minute, second, usecond, fold) < 0) {
  792. return NULL;
  793. }
  794. if (check_tzinfo_subclass(tzinfo) < 0) {
  795. return NULL;
  796. }
  797. self = (PyDateTime_DateTime *) (type->tp_alloc(type, aware));
  798. if (self != NULL) {
  799. self->hastzinfo = aware;
  800. set_date_fields((PyDateTime_Date *)self, year, month, day);
  801. DATE_SET_HOUR(self, hour);
  802. DATE_SET_MINUTE(self, minute);
  803. DATE_SET_SECOND(self, second);
  804. DATE_SET_MICROSECOND(self, usecond);
  805. if (aware) {
  806. Py_INCREF(tzinfo);
  807. self->tzinfo = tzinfo;
  808. }
  809. DATE_SET_FOLD(self, fold);
  810. }
  811. return (PyObject *)self;
  812. }
  813. static PyObject *
  814. new_datetime_ex(int year, int month, int day, int hour, int minute,
  815. int second, int usecond, PyObject *tzinfo, PyTypeObject *type)
  816. {
  817. return new_datetime_ex2(year, month, day, hour, minute, second, usecond,
  818. tzinfo, 0, type);
  819. }
  820. #define new_datetime(y, m, d, hh, mm, ss, us, tzinfo, fold) \
  821. new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, \
  822. &PyDateTime_DateTimeType)
  823. static PyObject *
  824. new_datetime_subclass_fold_ex(int year, int month, int day, int hour, int minute,
  825. int second, int usecond, PyObject *tzinfo,
  826. int fold, PyObject *cls) {
  827. PyObject* dt;
  828. if ((PyTypeObject*)cls == &PyDateTime_DateTimeType) {
  829. // Use the fast path constructor
  830. dt = new_datetime(year, month, day, hour, minute, second, usecond,
  831. tzinfo, fold);
  832. } else {
  833. // Subclass
  834. dt = PyObject_CallFunction(cls, "iiiiiiiO",
  835. year,
  836. month,
  837. day,
  838. hour,
  839. minute,
  840. second,
  841. usecond,
  842. tzinfo);
  843. }
  844. return dt;
  845. }
  846. static PyObject *
  847. new_datetime_subclass_ex(int year, int month, int day, int hour, int minute,
  848. int second, int usecond, PyObject *tzinfo,
  849. PyObject *cls) {
  850. return new_datetime_subclass_fold_ex(year, month, day, hour, minute,
  851. second, usecond, tzinfo, 0,
  852. cls);
  853. }
  854. /* Create a time instance with no range checking. */
  855. static PyObject *
  856. new_time_ex2(int hour, int minute, int second, int usecond,
  857. PyObject *tzinfo, int fold, PyTypeObject *type)
  858. {
  859. PyDateTime_Time *self;
  860. char aware = tzinfo != Py_None;
  861. if (check_time_args(hour, minute, second, usecond, fold) < 0) {
  862. return NULL;
  863. }
  864. if (check_tzinfo_subclass(tzinfo) < 0) {
  865. return NULL;
  866. }
  867. self = (PyDateTime_Time *) (type->tp_alloc(type, aware));
  868. if (self != NULL) {
  869. self->hastzinfo = aware;
  870. self->hashcode = -1;
  871. TIME_SET_HOUR(self, hour);
  872. TIME_SET_MINUTE(self, minute);
  873. TIME_SET_SECOND(self, second);
  874. TIME_SET_MICROSECOND(self, usecond);
  875. if (aware) {
  876. Py_INCREF(tzinfo);
  877. self->tzinfo = tzinfo;
  878. }
  879. TIME_SET_FOLD(self, fold);
  880. }
  881. return (PyObject *)self;
  882. }
  883. static PyObject *
  884. new_time_ex(int hour, int minute, int second, int usecond,
  885. PyObject *tzinfo, PyTypeObject *type)
  886. {
  887. return new_time_ex2(hour, minute, second, usecond, tzinfo, 0, type);
  888. }
  889. #define new_time(hh, mm, ss, us, tzinfo, fold) \
  890. new_time_ex2(hh, mm, ss, us, tzinfo, fold, &PyDateTime_TimeType)
  891. /* Create a timedelta instance. Normalize the members iff normalize is
  892. * true. Passing false is a speed optimization, if you know for sure
  893. * that seconds and microseconds are already in their proper ranges. In any
  894. * case, raises OverflowError and returns NULL if the normalized days is out
  895. * of range).
  896. */
  897. static PyObject *
  898. new_delta_ex(int days, int seconds, int microseconds, int normalize,
  899. PyTypeObject *type)
  900. {
  901. PyDateTime_Delta *self;
  902. if (normalize)
  903. normalize_d_s_us(&days, &seconds, &microseconds);
  904. assert(0 <= seconds && seconds < 24*3600);
  905. assert(0 <= microseconds && microseconds < 1000000);
  906. if (check_delta_day_range(days) < 0)
  907. return NULL;
  908. self = (PyDateTime_Delta *) (type->tp_alloc(type, 0));
  909. if (self != NULL) {
  910. self->hashcode = -1;
  911. SET_TD_DAYS(self, days);
  912. SET_TD_SECONDS(self, seconds);
  913. SET_TD_MICROSECONDS(self, microseconds);
  914. }
  915. return (PyObject *) self;
  916. }
  917. #define new_delta(d, s, us, normalize) \
  918. new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType)
  919. typedef struct
  920. {
  921. PyObject_HEAD
  922. PyObject *offset;
  923. PyObject *name;
  924. } PyDateTime_TimeZone;
  925. /* The interned UTC timezone instance */
  926. static PyObject *PyDateTime_TimeZone_UTC;
  927. /* The interned Epoch datetime instance */
  928. static PyObject *PyDateTime_Epoch;
  929. /* Create new timezone instance checking offset range. This
  930. function does not check the name argument. Caller must assure
  931. that offset is a timedelta instance and name is either NULL
  932. or a unicode object. */
  933. static PyObject *
  934. create_timezone(PyObject *offset, PyObject *name)
  935. {
  936. PyDateTime_TimeZone *self;
  937. PyTypeObject *type = &PyDateTime_TimeZoneType;
  938. assert(offset != NULL);
  939. assert(PyDelta_Check(offset));
  940. assert(name == NULL || PyUnicode_Check(name));
  941. self = (PyDateTime_TimeZone *)(type->tp_alloc(type, 0));
  942. if (self == NULL) {
  943. return NULL;
  944. }
  945. Py_INCREF(offset);
  946. self->offset = offset;
  947. Py_XINCREF(name);
  948. self->name = name;
  949. return (PyObject *)self;
  950. }
  951. static int delta_bool(PyDateTime_Delta *self);
  952. static PyObject *
  953. new_timezone(PyObject *offset, PyObject *name)
  954. {
  955. assert(offset != NULL);
  956. assert(PyDelta_Check(offset));
  957. assert(name == NULL || PyUnicode_Check(name));
  958. if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) {
  959. Py_INCREF(PyDateTime_TimeZone_UTC);
  960. return PyDateTime_TimeZone_UTC;
  961. }
  962. if ((GET_TD_DAYS(offset) == -1 &&
  963. GET_TD_SECONDS(offset) == 0 &&
  964. GET_TD_MICROSECONDS(offset) < 1) ||
  965. GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) {
  966. PyErr_Format(PyExc_ValueError, "offset must be a timedelta"
  967. " strictly between -timedelta(hours=24) and"
  968. " timedelta(hours=24),"
  969. " not %R.", offset);
  970. return NULL;
  971. }
  972. return create_timezone(offset, name);
  973. }
  974. /* ---------------------------------------------------------------------------
  975. * tzinfo helpers.
  976. */
  977. /* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
  978. * raise TypeError and return -1.
  979. */
  980. static int
  981. check_tzinfo_subclass(PyObject *p)
  982. {
  983. if (p == Py_None || PyTZInfo_Check(p))
  984. return 0;
  985. PyErr_Format(PyExc_TypeError,
  986. "tzinfo argument must be None or of a tzinfo subclass, "
  987. "not type '%s'",
  988. Py_TYPE(p)->tp_name);
  989. return -1;
  990. }
  991. /* If self has a tzinfo member, return a BORROWED reference to it. Else
  992. * return NULL, which is NOT AN ERROR. There are no error returns here,
  993. * and the caller must not decref the result.
  994. */
  995. static PyObject *
  996. get_tzinfo_member(PyObject *self)
  997. {
  998. PyObject *tzinfo = NULL;
  999. if (PyDateTime_Check(self) && HASTZINFO(self))
  1000. tzinfo = ((PyDateTime_DateTime *)self)->tzinfo;
  1001. else if (PyTime_Check(self) && HASTZINFO(self))
  1002. tzinfo = ((PyDateTime_Time *)self)->tzinfo;
  1003. return tzinfo;
  1004. }
  1005. /* Call getattr(tzinfo, name)(tzinfoarg), and check the result. tzinfo must
  1006. * be an instance of the tzinfo class. If the method returns None, this
  1007. * returns None. If the method doesn't return None or timedelta, TypeError is
  1008. * raised and this returns NULL. If it returns a timedelta and the value is
  1009. * out of range or isn't a whole number of minutes, ValueError is raised and
  1010. * this returns NULL. Else result is returned.
  1011. */
  1012. static PyObject *
  1013. call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg)
  1014. {
  1015. PyObject *offset;
  1016. assert(tzinfo != NULL);
  1017. assert(PyTZInfo_Check(tzinfo) || tzinfo == Py_None);
  1018. assert(tzinfoarg != NULL);
  1019. if (tzinfo == Py_None)
  1020. Py_RETURN_NONE;
  1021. offset = PyObject_CallMethod(tzinfo, name, "O", tzinfoarg);
  1022. if (offset == Py_None || offset == NULL)
  1023. return offset;
  1024. if (PyDelta_Check(offset)) {
  1025. if ((GET_TD_DAYS(offset) == -1 &&
  1026. GET_TD_SECONDS(offset) == 0 &&
  1027. GET_TD_MICROSECONDS(offset) < 1) ||
  1028. GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) {
  1029. Py_DECREF(offset);
  1030. PyErr_Format(PyExc_ValueError, "offset must be a timedelta"
  1031. " strictly between -timedelta(hours=24) and"
  1032. " timedelta(hours=24).");
  1033. return NULL;
  1034. }
  1035. }
  1036. else {
  1037. PyErr_Format(PyExc_TypeError,
  1038. "tzinfo.%s() must return None or "
  1039. "timedelta, not '%.200s'",
  1040. name, Py_TYPE(offset)->tp_name);
  1041. Py_DECREF(offset);
  1042. return NULL;
  1043. }
  1044. return offset;
  1045. }
  1046. /* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
  1047. * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
  1048. * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
  1049. * doesn't return None or timedelta, TypeError is raised and this returns -1.
  1050. * If utcoffset() returns an out of range timedelta,
  1051. * ValueError is raised and this returns -1. Else *none is
  1052. * set to 0 and the offset is returned (as timedelta, positive east of UTC).
  1053. */
  1054. static PyObject *
  1055. call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg)
  1056. {
  1057. return call_tzinfo_method(tzinfo, "utcoffset", tzinfoarg);
  1058. }
  1059. /* Call tzinfo.dst(tzinfoarg), and extract an integer from the
  1060. * result. tzinfo must be an instance of the tzinfo class. If dst()
  1061. * returns None, call_dst returns 0 and sets *none to 1. If dst()
  1062. * doesn't return None or timedelta, TypeError is raised and this
  1063. * returns -1. If dst() returns an invalid timedelta for a UTC offset,
  1064. * ValueError is raised and this returns -1. Else *none is set to 0 and
  1065. * the offset is returned (as timedelta, positive east of UTC).
  1066. */
  1067. static PyObject *
  1068. call_dst(PyObject *tzinfo, PyObject *tzinfoarg)
  1069. {
  1070. return call_tzinfo_method(tzinfo, "dst", tzinfoarg);
  1071. }
  1072. /* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
  1073. * an instance of the tzinfo class or None. If tzinfo isn't None, and
  1074. * tzname() doesn't return None or a string, TypeError is raised and this
  1075. * returns NULL. If the result is a string, we ensure it is a Unicode
  1076. * string.
  1077. */
  1078. static PyObject *
  1079. call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
  1080. {
  1081. PyObject *result;
  1082. _Py_IDENTIFIER(tzname);
  1083. assert(tzinfo != NULL);
  1084. assert(check_tzinfo_subclass(tzinfo) >= 0);
  1085. assert(tzinfoarg != NULL);
  1086. if (tzinfo == Py_None)
  1087. Py_RETURN_NONE;
  1088. result = _PyObject_CallMethodIdOneArg(tzinfo, &PyId_tzname, tzinfoarg);
  1089. if (result == NULL || result == Py_None)
  1090. return result;
  1091. if (!PyUnicode_Check(result)) {
  1092. PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
  1093. "return None or a string, not '%s'",
  1094. Py_TYPE(result)->tp_name);
  1095. Py_DECREF(result);
  1096. result = NULL;
  1097. }
  1098. return result;
  1099. }
  1100. /* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
  1101. * stuff
  1102. * ", tzinfo=" + repr(tzinfo)
  1103. * before the closing ")".
  1104. */
  1105. static PyObject *
  1106. append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
  1107. {
  1108. PyObject *temp;
  1109. assert(PyUnicode_Check(repr));
  1110. assert(tzinfo);
  1111. if (tzinfo == Py_None)
  1112. return repr;
  1113. /* Get rid of the trailing ')'. */
  1114. assert(PyUnicode_READ_CHAR(repr, PyUnicode_GET_LENGTH(repr)-1) == ')');
  1115. temp = PyUnicode_Substring(repr, 0, PyUnicode_GET_LENGTH(repr) - 1);
  1116. Py_DECREF(repr);
  1117. if (temp == NULL)
  1118. return NULL;
  1119. repr = PyUnicode_FromFormat("%U, tzinfo=%R)", temp, tzinfo);
  1120. Py_DECREF(temp);
  1121. return repr;
  1122. }
  1123. /* repr is like "someclass(arg1, arg2)". If fold isn't 0,
  1124. * stuff
  1125. * ", fold=" + repr(tzinfo)
  1126. * before the closing ")".
  1127. */
  1128. static PyObject *
  1129. append_keyword_fold(PyObject *repr, int fold)
  1130. {
  1131. PyObject *temp;
  1132. assert(PyUnicode_Check(repr));
  1133. if (fold == 0)
  1134. return repr;
  1135. /* Get rid of the trailing ')'. */
  1136. assert(PyUnicode_READ_CHAR(repr, PyUnicode_GET_LENGTH(repr)-1) == ')');
  1137. temp = PyUnicode_Substring(repr, 0, PyUnicode_GET_LENGTH(repr) - 1);
  1138. Py_DECREF(repr);
  1139. if (temp == NULL)
  1140. return NULL;
  1141. repr = PyUnicode_FromFormat("%U, fold=%d)", temp, fold);
  1142. Py_DECREF(temp);
  1143. return repr;
  1144. }
  1145. static inline PyObject *
  1146. tzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds)
  1147. {
  1148. PyObject *tzinfo;
  1149. if (rv == 1) {
  1150. // Create a timezone from offset in seconds (0 returns UTC)
  1151. if (tzoffset == 0) {
  1152. Py_INCREF(PyDateTime_TimeZone_UTC);
  1153. return PyDateTime_TimeZone_UTC;
  1154. }
  1155. PyObject *delta = new_delta(0, tzoffset, tz_useconds, 1);
  1156. if (delta == NULL) {
  1157. return NULL;
  1158. }
  1159. tzinfo = new_timezone(delta, NULL);
  1160. Py_DECREF(delta);
  1161. }
  1162. else {
  1163. tzinfo = Py_None;
  1164. Py_INCREF(Py_None);
  1165. }
  1166. return tzinfo;
  1167. }
  1168. /* ---------------------------------------------------------------------------
  1169. * String format helpers.
  1170. */
  1171. static PyObject *
  1172. format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds)
  1173. {
  1174. static const char * const DayNames[] = {
  1175. "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
  1176. };
  1177. static const char * const MonthNames[] = {
  1178. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1179. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  1180. };
  1181. int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
  1182. return PyUnicode_FromFormat("%s %s %2d %02d:%02d:%02d %04d",
  1183. DayNames[wday], MonthNames[GET_MONTH(date)-1],
  1184. GET_DAY(date), hours, minutes, seconds,
  1185. GET_YEAR(date));
  1186. }
  1187. static PyObject *delta_negative(PyDateTime_Delta *self);
  1188. /* Add formatted UTC offset string to buf. buf has no more than
  1189. * buflen bytes remaining. The UTC offset is gotten by calling
  1190. * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
  1191. * *buf, and that's all. Else the returned value is checked for sanity (an
  1192. * integer in range), and if that's OK it's converted to an hours & minutes
  1193. * string of the form
  1194. * sign HH sep MM [sep SS [. UUUUUU]]
  1195. * Returns 0 if everything is OK. If the return value from utcoffset() is
  1196. * bogus, an appropriate exception is set and -1 is returned.
  1197. */
  1198. static int
  1199. format_utcoffset(char *buf, size_t buflen, const char *sep,
  1200. PyObject *tzinfo, PyObject *tzinfoarg)
  1201. {
  1202. PyObject *offset;
  1203. int hours, minutes, seconds, microseconds;
  1204. char sign;
  1205. assert(buflen >= 1);
  1206. offset = call_utcoffset(tzinfo, tzinfoarg);
  1207. if (offset == NULL)
  1208. return -1;
  1209. if (offset == Py_None) {
  1210. Py_DECREF(offset);
  1211. *buf = '\0';
  1212. return 0;
  1213. }
  1214. /* Offset is normalized, so it is negative if days < 0 */
  1215. if (GET_TD_DAYS(offset) < 0) {
  1216. sign = '-';
  1217. Py_SETREF(offset, delta_negative((PyDateTime_Delta *)offset));
  1218. if (offset == NULL)
  1219. return -1;
  1220. }
  1221. else {
  1222. sign = '+';
  1223. }
  1224. /* Offset is not negative here. */
  1225. microseconds = GET_TD_MICROSECONDS(offset);
  1226. seconds = GET_TD_SECONDS(offset);
  1227. Py_DECREF(offset);
  1228. minutes = divmod(seconds, 60, &seconds);
  1229. hours = divmod(minutes, 60, &minutes);
  1230. if (microseconds) {
  1231. PyOS_snprintf(buf, buflen, "%c%02d%s%02d%s%02d.%06d", sign,
  1232. hours, sep, minutes, sep, seconds, microseconds);
  1233. return 0;
  1234. }
  1235. if (seconds) {
  1236. PyOS_snprintf(buf, buflen, "%c%02d%s%02d%s%02d", sign, hours,
  1237. sep, minutes, sep, seconds);
  1238. return 0;
  1239. }
  1240. PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
  1241. return 0;
  1242. }
  1243. static PyObject *
  1244. make_Zreplacement(PyObject *object, PyObject *tzinfoarg)
  1245. {
  1246. PyObject *temp;
  1247. PyObject *tzinfo = get_tzinfo_member(object);
  1248. PyObject *Zreplacement = PyUnicode_FromStringAndSize(NULL, 0);
  1249. _Py_IDENTIFIER(replace);
  1250. if (Zreplacement == NULL)
  1251. return NULL;
  1252. if (tzinfo == Py_None || tzinfo == NULL)
  1253. return Zreplacement;
  1254. assert(tzinfoarg != NULL);
  1255. temp = call_tzname(tzinfo, tzinfoarg);
  1256. if (temp == NULL)
  1257. goto Error;
  1258. if (temp == Py_None) {
  1259. Py_DECREF(temp);
  1260. return Zreplacement;
  1261. }
  1262. assert(PyUnicode_Check(temp));
  1263. /* Since the tzname is getting stuffed into the
  1264. * format, we have to double any % signs so that
  1265. * strftime doesn't treat them as format codes.
  1266. */
  1267. Py_DECREF(Zreplacement);
  1268. Zreplacement = _PyObject_CallMethodId(temp, &PyId_replace, "ss", "%", "%%");
  1269. Py_DECREF(temp);
  1270. if (Zreplacement == NULL)
  1271. return NULL;
  1272. if (!PyUnicode_Check(Zreplacement)) {
  1273. PyErr_SetString(PyExc_TypeError,
  1274. "tzname.replace() did not return a string");
  1275. goto Error;
  1276. }
  1277. return Zreplacement;
  1278. Error:
  1279. Py_DECREF(Zreplacement);
  1280. return NULL;
  1281. }
  1282. static PyObject *
  1283. make_freplacement(PyObject *object)
  1284. {
  1285. char freplacement[64];
  1286. if (PyTime_Check(object))
  1287. sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object));
  1288. else if (PyDateTime_Check(object))
  1289. sprintf(freplacement, "%06d", DATE_GET_MICROSECOND(object));
  1290. else
  1291. sprintf(freplacement, "%06d", 0);
  1292. return PyBytes_FromStringAndSize(freplacement, strlen(freplacement));
  1293. }
  1294. /* I sure don't want to reproduce the strftime code from the time module,
  1295. * so this imports the module and calls it. All the hair is due to
  1296. * giving special meanings to the %z, %Z and %f format codes via a
  1297. * preprocessing step on the format string.
  1298. * tzinfoarg is the argument to pass to the object's tzinfo method, if
  1299. * needed.
  1300. */
  1301. static PyObject *
  1302. wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
  1303. PyObject *tzinfoarg)
  1304. {
  1305. PyObject *result = NULL; /* guilty until proved innocent */
  1306. PyObject *zreplacement = NULL; /* py string, replacement for %z */
  1307. PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
  1308. PyObject *freplacement = NULL; /* py string, replacement for %f */
  1309. const char *pin; /* pointer to next char in input format */
  1310. Py_ssize_t flen; /* length of input format */
  1311. char ch; /* next char in input format */
  1312. PyObject *newfmt = NULL; /* py string, the output format */
  1313. char *pnew; /* pointer to available byte in output format */
  1314. size_t totalnew; /* number bytes total in output format buffer,
  1315. exclusive of trailing \0 */
  1316. size_t usednew; /* number bytes used so far in output format buffer */
  1317. const char *ptoappend; /* ptr to string to append to output buffer */
  1318. Py_ssize_t ntoappend; /* # of bytes to append to output buffer */
  1319. assert(object && format && timetuple);
  1320. assert(PyUnicode_Check(format));
  1321. /* Convert the input format to a C string and size */
  1322. pin = PyUnicode_AsUTF8AndSize(format, &flen);
  1323. if (!pin)
  1324. return NULL;
  1325. /* Scan the input format, looking for %z/%Z/%f escapes, building
  1326. * a new format. Since computing the replacements for those codes
  1327. * is expensive, don't unless they're actually used.
  1328. */
  1329. if (flen > INT_MAX - 1) {
  1330. PyErr_NoMemory();
  1331. goto Done;
  1332. }
  1333. totalnew = flen + 1; /* realistic if no %z/%Z */
  1334. newfmt = PyBytes_FromStringAndSize(NULL, totalnew);
  1335. if (newfmt == NULL) goto Done;
  1336. pnew = PyBytes_AsString(newfmt);
  1337. usednew = 0;
  1338. while ((ch = *pin++) != '\0') {
  1339. if (ch != '%') {
  1340. ptoappend = pin - 1;
  1341. ntoappend = 1;
  1342. }
  1343. else if ((ch = *pin++) == '\0') {
  1344. /* Null byte follows %, copy only '%'.
  1345. *
  1346. * Back the pin up one char so that we catch the null check
  1347. * the next time through the loop.*/
  1348. pin--;
  1349. ptoappend = pin - 1;
  1350. ntoappend = 1;
  1351. }
  1352. /* A % has been seen and ch is the character after it. */
  1353. else if (ch == 'z') {
  1354. if (zreplacement == NULL) {
  1355. /* format utcoffset */
  1356. char buf[100];
  1357. PyObject *tzinfo = get_tzinfo_member(object);
  1358. zreplacement = PyBytes_FromStringAndSize("", 0);
  1359. if (zreplacement == NULL) goto Done;
  1360. if (tzinfo != Py_None && tzinfo != NULL) {
  1361. assert(tzinfoarg != NULL);
  1362. if (format_utcoffset(buf,
  1363. sizeof(buf),
  1364. "",
  1365. tzinfo,
  1366. tzinfoarg) < 0)
  1367. goto Done;
  1368. Py_DECREF(zreplacement);
  1369. zreplacement =
  1370. PyBytes_FromStringAndSize(buf,
  1371. strlen(buf));
  1372. if (zreplacement == NULL)
  1373. goto Done;
  1374. }
  1375. }
  1376. assert(zreplacement != NULL);
  1377. ptoappend = PyBytes_AS_STRING(zreplacement);
  1378. ntoappend = PyBytes_GET_SIZE(zreplacement);
  1379. }
  1380. else if (ch == 'Z') {
  1381. /* format tzname */
  1382. if (Zreplacement == NULL) {
  1383. Zreplacement = make_Zreplacement(object,
  1384. tzinfoarg);
  1385. if (Zreplacement == NULL)
  1386. goto Done;
  1387. }
  1388. assert(Zreplacement != NULL);
  1389. assert(PyUnicode_Check(Zreplacement));
  1390. ptoappend = PyUnicode_AsUTF8AndSize(Zreplacement,
  1391. &ntoappend);
  1392. if (ptoappend == NULL)
  1393. goto Done;
  1394. }
  1395. else if (ch == 'f') {
  1396. /* format microseconds */
  1397. if (freplacement == NULL) {
  1398. freplacement = make_freplacement(object);
  1399. if (freplacement == NULL)
  1400. goto Done;
  1401. }
  1402. assert(freplacement != NULL);
  1403. assert(PyBytes_Check(freplacement));
  1404. ptoappend = PyBytes_AS_STRING(freplacement);
  1405. ntoappend = PyBytes_GET_SIZE(freplacement);
  1406. }
  1407. else {
  1408. /* percent followed by neither z nor Z */
  1409. ptoappend = pin - 2;
  1410. ntoappend = 2;
  1411. }
  1412. /* Append the ntoappend chars starting at ptoappend to
  1413. * the new format.
  1414. */
  1415. if (ntoappend == 0)
  1416. continue;
  1417. assert(ptoappend != NULL);
  1418. assert(ntoappend > 0);
  1419. while (usednew + ntoappend > totalnew) {
  1420. if (totalnew > (PY_SSIZE_T_MAX >> 1)) { /* overflow */
  1421. PyErr_NoMemory();
  1422. goto Done;
  1423. }
  1424. totalnew <<= 1;
  1425. if (_PyBytes_Resize(&newfmt, totalnew) < 0)
  1426. goto Done;
  1427. pnew = PyBytes_AsString(newfmt) + usednew;
  1428. }
  1429. memcpy(pnew, ptoappend, ntoappend);
  1430. pnew += ntoappend;
  1431. usednew += ntoappend;
  1432. assert(usednew <= totalnew);
  1433. } /* end while() */
  1434. if (_PyBytes_Resize(&newfmt, usednew) < 0)
  1435. goto Done;
  1436. {
  1437. PyObject *format;
  1438. PyObject *time = PyImport_ImportModuleNoBlock("time");
  1439. if (time == NULL)
  1440. goto Done;
  1441. format = PyUnicode_FromString(PyBytes_AS_STRING(newfmt));
  1442. if (format != NULL) {
  1443. result = _PyObject_CallMethodIdObjArgs(time, &PyId_strftime,
  1444. format, timetuple, NULL);
  1445. Py_DECREF(format);
  1446. }
  1447. Py_DECREF(time);
  1448. }
  1449. Done:
  1450. Py_XDECREF(freplacement);
  1451. Py_XDECREF(zreplacement);
  1452. Py_XDECREF(Zreplacement);
  1453. Py_XDECREF(newfmt);
  1454. return result;
  1455. }
  1456. /* ---------------------------------------------------------------------------
  1457. * Wrap functions from the time module. These aren't directly available
  1458. * from C. Perhaps they should be.
  1459. */
  1460. /* Call time.time() and return its result (a Python float). */
  1461. static PyObject *
  1462. time_time(void)
  1463. {
  1464. PyObject *result = NULL;
  1465. PyObject *time = PyImport_ImportModuleNoBlock("time");
  1466. if (time != NULL) {
  1467. _Py_IDENTIFIER(time);
  1468. result = _PyObject_CallMethodIdNoArgs(time, &PyId_time);
  1469. Py_DECREF(time);
  1470. }
  1471. return result;
  1472. }
  1473. /* Build a time.struct_time. The weekday and day number are automatically
  1474. * computed from the y,m,d args.
  1475. */
  1476. static PyObject *
  1477. build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
  1478. {
  1479. PyObject *time;
  1480. PyObject *result;
  1481. _Py_IDENTIFIER(struct_time);
  1482. PyObject *args;
  1483. time = PyImport_ImportModuleNoBlock("time");
  1484. if (time == NULL) {
  1485. return NULL;
  1486. }
  1487. args = Py_BuildValue("iiiiiiiii",
  1488. y, m, d,
  1489. hh, mm, ss,
  1490. weekday(y, m, d),
  1491. days_before_month(y, m) + d,
  1492. dstflag);
  1493. if (args == NULL) {
  1494. Py_DECREF(time);
  1495. return NULL;
  1496. }
  1497. result = _PyObject_CallMethodIdOneArg(time, &PyId_struct_time, args);
  1498. Py_DECREF(time);
  1499. Py_DECREF(args);
  1500. return result;
  1501. }
  1502. /* ---------------------------------------------------------------------------
  1503. * Miscellaneous helpers.
  1504. */
  1505. /* The comparisons here all most naturally compute a cmp()-like result.
  1506. * This little helper turns that into a bool result for rich comparisons.
  1507. */
  1508. static PyObject *
  1509. diff_to_bool(int diff, int op)
  1510. {
  1511. Py_RETURN_RICHCOMPARE(diff, 0, op);
  1512. }
  1513. /* Raises a "can't compare" TypeError and returns NULL. */
  1514. static PyObject *
  1515. cmperror(PyObject *a, PyObject *b)
  1516. {
  1517. PyErr_Format(PyExc_TypeError,
  1518. "can't compare %s to %s",
  1519. Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
  1520. return NULL;
  1521. }
  1522. /* ---------------------------------------------------------------------------
  1523. * Cached Python objects; these are set by the module init function.
  1524. */
  1525. /* Conversion factors. */
  1526. static PyObject *us_per_ms = NULL; /* 1000 */
  1527. static PyObject *us_per_second = NULL; /* 1000000 */
  1528. static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
  1529. static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python int */
  1530. static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python int */
  1531. static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python int */
  1532. static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
  1533. /* ---------------------------------------------------------------------------
  1534. * Class implementations.
  1535. */
  1536. /*
  1537. * PyDateTime_Delta implementation.
  1538. */
  1539. /* Convert a timedelta to a number of us,
  1540. * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
  1541. * as a Python int.
  1542. * Doing mixed-radix arithmetic by hand instead is excruciating in C,
  1543. * due to ubiquitous overflow possibilities.
  1544. */
  1545. static PyObject *
  1546. delta_to_microseconds(PyDateTime_Delta *self)
  1547. {
  1548. PyObject *x1 = NULL;
  1549. PyObject *x2 = NULL;
  1550. PyObject *x3 = NULL;
  1551. PyObject *result = NULL;
  1552. x1 = PyLong_FromLong(GET_TD_DAYS(self));
  1553. if (x1 == NULL)
  1554. goto Done;
  1555. x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
  1556. if (x2 == NULL)
  1557. goto Done;
  1558. Py_DECREF(x1);
  1559. x1 = NULL;
  1560. /* x2 has days in seconds */
  1561. x1 = PyLong_FromLong(GET_TD_SECONDS(self)); /* seconds */
  1562. if (x1 == NULL)
  1563. goto Done;
  1564. x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
  1565. if (x3 == NULL)
  1566. goto Done;
  1567. Py_DECREF(x1);
  1568. Py_DECREF(x2);
  1569. /* x1 = */ x2 = NULL;
  1570. /* x3 has days+seconds in seconds */
  1571. x1 = PyNumber_Multiply(x3, us_per_second); /* us */
  1572. if (x1 == NULL)
  1573. goto Done;
  1574. Py_DECREF(x3);
  1575. x3 = NULL;
  1576. /* x1 has days+seconds in us */
  1577. x2 = PyLong_FromLong(GET_TD_MICROSECONDS(self));
  1578. if (x2 == NULL)
  1579. goto Done;
  1580. result = PyNumber_Add(x1, x2);
  1581. assert(result == NULL || PyLong_CheckExact(result));
  1582. Done:
  1583. Py_XDECREF(x1);
  1584. Py_XDECREF(x2);
  1585. Py_XDECREF(x3);
  1586. return result;
  1587. }
  1588. static PyObject *
  1589. checked_divmod(PyObject *a, PyObject *b)
  1590. {
  1591. PyObject *result = PyNumber_Divmod(a, b);
  1592. if (result != NULL) {
  1593. if (!PyTuple_Check(result)) {
  1594. PyErr_Format(PyExc_TypeError,
  1595. "divmod() returned non-tuple (type %.200s)",
  1596. Py_TYPE(result)->tp_name);
  1597. Py_DECREF(result);
  1598. return NULL;
  1599. }
  1600. if (PyTuple_GET_SIZE(result) != 2) {
  1601. PyErr_Format(PyExc_TypeError,
  1602. "divmod() returned a tuple of size %zd",
  1603. PyTuple_GET_SIZE(result));
  1604. Py_DECREF(result);
  1605. return NULL;
  1606. }
  1607. }
  1608. return result;
  1609. }
  1610. /* Convert a number of us (as a Python int) to a timedelta.
  1611. */
  1612. static PyObject *
  1613. microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
  1614. {
  1615. int us;
  1616. int s;
  1617. int d;
  1618. PyObject *tuple = NULL;
  1619. PyObject *num = NULL;
  1620. PyObject *result = NULL;
  1621. tuple = checked_divmod(pyus, us_per_second);
  1622. if (tuple == NULL) {
  1623. goto Done;
  1624. }
  1625. num = PyTuple_GET_ITEM(tuple, 1); /* us */
  1626. us = _PyLong_AsInt(num);
  1627. num = NULL;
  1628. if (us == -1 && PyErr_Occurred()) {
  1629. goto Done;
  1630. }
  1631. if (!(0 <= us && us < 1000000)) {
  1632. goto BadDivmod;
  1633. }
  1634. num = PyTuple_GET_ITEM(tuple, 0); /* leftover seconds */
  1635. Py_INCREF(num);
  1636. Py_DECREF(tuple);
  1637. tuple = checked_divmod(num, seconds_per_day);
  1638. if (tuple == NULL)
  1639. goto Done;
  1640. Py_DECREF(num);
  1641. num = PyTuple_GET_ITEM(tuple, 1); /* seconds */
  1642. s = _PyLong_AsInt(num);
  1643. num = NULL;
  1644. if (s == -1 && PyErr_Occurred()) {
  1645. goto Done;
  1646. }
  1647. if (!(0 <= s && s < 24*3600)) {
  1648. goto BadDivmod;
  1649. }
  1650. num = PyTuple_GET_ITEM(tuple, 0); /* leftover days */
  1651. Py_INCREF(num);
  1652. d = _PyLong_AsInt(num);
  1653. if (d == -1 && PyErr_Occurred()) {
  1654. goto Done;
  1655. }
  1656. result = new_delta_ex(d, s, us, 0, type);
  1657. Done:
  1658. Py_XDECREF(tuple);
  1659. Py_XDECREF(num);
  1660. return result;
  1661. BadDivmod:
  1662. PyErr_SetString(PyExc_TypeError,
  1663. "divmod() returned a value out of range");
  1664. goto Done;
  1665. }
  1666. #define microseconds_to_delta(pymicros) \
  1667. microseconds_to_delta_ex(pymicros, &PyDateTime_DeltaType)
  1668. static PyObject *
  1669. multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
  1670. {
  1671. PyObject *pyus_in;
  1672. PyObject *pyus_out;
  1673. PyObject *result;
  1674. pyus_in = delta_to_microseconds(delta);
  1675. if (pyus_in == NULL)
  1676. return NULL;
  1677. pyus_out = PyNumber_Multiply(intobj, pyus_in);
  1678. Py_DECREF(pyus_in);
  1679. if (pyus_out == NULL)
  1680. return NULL;
  1681. result = microseconds_to_delta(pyus_out);
  1682. Py_DECREF(pyus_out);
  1683. return result;
  1684. }
  1685. static PyObject *
  1686. get_float_as_integer_ratio(PyObject *floatobj)
  1687. {
  1688. PyObject *ratio;
  1689. assert(floatobj && PyFloat_Check(floatobj));
  1690. ratio = _PyObject_CallMethodIdNoArgs(floatobj, &PyId_as_integer_ratio);
  1691. if (ratio == NULL) {
  1692. return NULL;
  1693. }
  1694. if (!PyTuple_Check(ratio)) {
  1695. PyErr_Format(PyExc_TypeError,
  1696. "unexpected return type from as_integer_ratio(): "
  1697. "expected tuple, got '%.200s'",
  1698. Py_TYPE(ratio)->tp_name);
  1699. Py_DECREF(ratio);
  1700. return NULL;
  1701. }
  1702. if (PyTuple_Size(ratio) != 2) {
  1703. PyErr_SetString(PyExc_ValueError,
  1704. "as_integer_ratio() must return a 2-tuple");
  1705. Py_DECREF(ratio);
  1706. return NULL;
  1707. }
  1708. return ratio;
  1709. }
  1710. /* op is 0 for multiplication, 1 for division */
  1711. static PyObject *
  1712. multiply_truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *floatobj, int op)
  1713. {
  1714. PyObject *result = NULL;
  1715. PyObject *pyus_in = NULL, *temp, *pyus_out;
  1716. PyObject *ratio = NULL;
  1717. pyus_in = delta_to_microseconds(delta);
  1718. if (pyus_in == NULL)
  1719. return NULL;
  1720. ratio = get_float_as_integer_ratio(floatobj);
  1721. if (ratio == NULL) {
  1722. goto error;
  1723. }
  1724. temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, op));
  1725. Py_DECREF(pyus_in);
  1726. pyus_in = NULL;
  1727. if (temp == NULL)
  1728. goto error;
  1729. pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, !op));
  1730. Py_DECREF(temp);
  1731. if (pyus_out == NULL)
  1732. goto error;
  1733. result = microseconds_to_delta(pyus_out);
  1734. Py_DECREF(pyus_out);
  1735. error:
  1736. Py_XDECREF(pyus_in);
  1737. Py_XDECREF(ratio);
  1738. return result;
  1739. }
  1740. static PyObject *
  1741. divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
  1742. {
  1743. PyObject *pyus_in;
  1744. PyObject *pyus_out;
  1745. PyObject *result;
  1746. pyus_in = delta_to_microseconds(delta);
  1747. if (pyus_in == NULL)
  1748. return NULL;
  1749. pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
  1750. Py_DECREF(pyus_in);
  1751. if (pyus_out == NULL)
  1752. return NULL;
  1753. result = microseconds_to_delta(pyus_out);
  1754. Py_DECREF(pyus_out);
  1755. return result;
  1756. }
  1757. static PyObject *
  1758. divide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right)
  1759. {
  1760. PyObject *pyus_left;
  1761. PyObject *pyus_right;
  1762. PyObject *result;
  1763. pyus_left = delta_to_microseconds(left);
  1764. if (pyus_left == NULL)
  1765. return NULL;
  1766. pyus_right = delta_to_microseconds(right);
  1767. if (pyus_right == NULL) {
  1768. Py_DECREF(pyus_left);
  1769. return NULL;
  1770. }
  1771. result = PyNumber_FloorDivide(pyus_left, pyus_right);
  1772. Py_DECREF(pyus_left);
  1773. Py_DECREF(pyus_right);
  1774. return result;
  1775. }
  1776. static PyObject *
  1777. truedivide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right)
  1778. {
  1779. PyObject *pyus_left;
  1780. PyObject *pyus_right;
  1781. PyObject *result;
  1782. pyus_left = delta_to_microseconds(left);
  1783. if (pyus_left == NULL)
  1784. return NULL;
  1785. pyus_right = delta_to_microseconds(right);
  1786. if (pyus_right == NULL) {
  1787. Py_DECREF(pyus_left);
  1788. return NULL;
  1789. }
  1790. result = PyNumber_TrueDivide(pyus_left, pyus_right);
  1791. Py_DECREF(pyus_left);
  1792. Py_DECREF(pyus_right);
  1793. return result;
  1794. }
  1795. static PyObject *
  1796. truedivide_timedelta_int(PyDateTime_Delta *delta, PyObject *i)
  1797. {
  1798. PyObject *result;
  1799. PyObject *pyus_in, *pyus_out;
  1800. pyus_in = delta_to_microseconds(delta);
  1801. if (pyus_in == NULL)
  1802. return NULL;
  1803. pyus_out = divide_nearest(pyus_in, i);
  1804. Py_DECREF(pyus_in);
  1805. if (pyus_out == NULL)
  1806. return NULL;
  1807. result = microseconds_to_delta(pyus_out);
  1808. Py_DECREF(pyus_out);
  1809. return result;
  1810. }
  1811. static PyObject *
  1812. delta_add(PyObject *left, PyObject *right)
  1813. {
  1814. PyObject *result = Py_NotImplemented;
  1815. if (PyDelta_Check(left) && PyDelta_Check(right)) {
  1816. /* delta + delta */
  1817. /* The C-level additions can't overflow because of the
  1818. * invariant bounds.
  1819. */
  1820. int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
  1821. int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
  1822. int microseconds = GET_TD_MICROSECONDS(left) +
  1823. GET_TD_MICROSECONDS(right);
  1824. result = new_delta(days, seconds, microseconds, 1);
  1825. }
  1826. if (result == Py_NotImplemented)
  1827. Py_INCREF(result);
  1828. return result;
  1829. }
  1830. static PyObject *
  1831. delta_negative(PyDateTime_Delta *self)
  1832. {
  1833. return new_delta(-GET_TD_DAYS(self),
  1834. -GET_TD_SECONDS(self),
  1835. -GET_TD_MICROSECONDS(self),
  1836. 1);
  1837. }
  1838. static PyObject *
  1839. delta_positive(PyDateTime_Delta *self)
  1840. {
  1841. /* Could optimize this (by returning self) if this isn't a
  1842. * subclass -- but who uses unary + ? Approximately nobody.
  1843. */
  1844. return new_delta(GET_TD_DAYS(self),
  1845. GET_TD_SECONDS(self),
  1846. GET_TD_MICROSECONDS(self),
  1847. 0);
  1848. }
  1849. static PyObject *
  1850. delta_abs(PyDateTime_Delta *self)
  1851. {
  1852. PyObject *result;
  1853. assert(GET_TD_MICROSECONDS(self) >= 0);
  1854. assert(GET_TD_SECONDS(self) >= 0);
  1855. if (GET_TD_DAYS(self) < 0)
  1856. result = delta_negative(self);
  1857. else
  1858. result = delta_positive(self);
  1859. return result;
  1860. }
  1861. static PyObject *
  1862. delta_subtract(PyObject *left, PyObject *right)
  1863. {
  1864. PyObject *result = Py_NotImplemented;
  1865. if (PyDelta_Check(left) && PyDelta_Check(right)) {
  1866. /* delta - delta */
  1867. /* The C-level additions can't overflow because of the
  1868. * invariant bounds.
  1869. */
  1870. int days = GET_TD_DAYS(left) - GET_TD_DAYS(right);
  1871. int seconds = GET_TD_SECONDS(left) - GET_TD_SECONDS(right);
  1872. int microseconds = GET_TD_MICROSECONDS(left) -
  1873. GET_TD_MICROSECONDS(right);
  1874. result = new_delta(days, seconds, microseconds, 1);
  1875. }
  1876. if (result == Py_NotImplemented)
  1877. Py_INCREF(result);
  1878. return result;
  1879. }
  1880. static int
  1881. delta_cmp(PyObject *self, PyObject *other)
  1882. {
  1883. int diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
  1884. if (diff == 0) {
  1885. diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
  1886. if (diff == 0)
  1887. diff = GET_TD_MICROSECONDS(self) -
  1888. GET_TD_MICROSECONDS(other);
  1889. }
  1890. return diff;
  1891. }
  1892. static PyObject *
  1893. delta_richcompare(PyObject *self, PyObject *other, int op)
  1894. {
  1895. if (PyDelta_Check(other)) {
  1896. int diff = delta_cmp(self, other);
  1897. return diff_to_bool(diff, op);
  1898. }
  1899. else {
  1900. Py_RETURN_NOTIMPLEMENTED;
  1901. }
  1902. }
  1903. static PyObject *delta_getstate(PyDateTime_Delta *self);
  1904. static Py_hash_t
  1905. delta_hash(PyDateTime_Delta *self)
  1906. {
  1907. if (self->hashcode == -1) {
  1908. PyObject *temp = delta_getstate(self);
  1909. if (temp != NULL) {
  1910. self->hashcode = PyObject_Hash(temp);
  1911. Py_DECREF(temp);
  1912. }
  1913. }
  1914. return self->hashcode;
  1915. }
  1916. static PyObject *
  1917. delta_multiply(PyObject *left, PyObject *right)
  1918. {
  1919. PyObject *result = Py_NotImplemented;
  1920. if (PyDelta_Check(left)) {
  1921. /* delta * ??? */
  1922. if (PyLong_Check(right))
  1923. result = multiply_int_timedelta(right,
  1924. (PyDateTime_Delta *) left);
  1925. else if (PyFloat_Check(right))
  1926. result = multiply_truedivide_timedelta_float(
  1927. (PyDateTime_Delta *) left, right, 0);
  1928. }
  1929. else if (PyLong_Check(left))
  1930. result = multiply_int_timedelta(left,
  1931. (PyDateTime_Delta *) right);
  1932. else if (PyFloat_Check(left))
  1933. result = multiply_truedivide_timedelta_float(
  1934. (PyDateTime_Delta *) right, left, 0);
  1935. if (result == Py_NotImplemented)
  1936. Py_INCREF(result);
  1937. return result;
  1938. }
  1939. static PyObject *
  1940. delta_divide(PyObject *left, PyObject *right)
  1941. {
  1942. PyObject *result = Py_NotImplemented;
  1943. if (PyDelta_Check(left)) {
  1944. /* delta * ??? */
  1945. if (PyLong_Check(right))
  1946. result = divide_timedelta_int(
  1947. (PyDateTime_Delta *)left,
  1948. right);
  1949. else if (PyDelta_Check(right))
  1950. result = divide_timedelta_timedelta(
  1951. (PyDateTime_Delta *)left,
  1952. (PyDateTime_Delta *)right);
  1953. }
  1954. if (result == Py_NotImplemented)
  1955. Py_INCREF(result);
  1956. return result;
  1957. }
  1958. static PyObject *
  1959. delta_truedivide(PyObject *left, PyObject *right)
  1960. {
  1961. PyObject *result = Py_NotImplemented;
  1962. if (PyDelta_Check(left)) {
  1963. if (PyDelta_Check(right))
  1964. result = truedivide_timedelta_timedelta(
  1965. (PyDateTime_Delta *)left,
  1966. (PyDateTime_Delta *)right);
  1967. else if (PyFloat_Check(right))
  1968. result = multiply_truedivide_timedelta_float(
  1969. (PyDateTime_Delta *)left, right, 1);
  1970. else if (PyLong_Check(right))
  1971. result = truedivide_timedelta_int(
  1972. (PyDateTime_Delta *)left, right);
  1973. }
  1974. if (result == Py_NotImplemented)
  1975. Py_INCREF(result);
  1976. return result;
  1977. }
  1978. static PyObject *
  1979. delta_remainder(PyObject *left, PyObject *right)
  1980. {
  1981. PyObject *pyus_left;
  1982. PyObject *pyus_right;
  1983. PyObject *pyus_remainder;
  1984. PyObject *remainder;
  1985. if (!PyDelta_Check(left) || !PyDelta_Check(right))
  1986. Py_RETURN_NOTIMPLEMENTED;
  1987. pyus_left = delta_to_microseconds((PyDateTime_Delta *)left);
  1988. if (pyus_left == NULL)
  1989. return NULL;
  1990. pyus_right = delta_to_microseconds((PyDateTime_Delta *)right);
  1991. if (pyus_right == NULL) {
  1992. Py_DECREF(pyus_left);
  1993. return NULL;
  1994. }
  1995. pyus_remainder = PyNumber_Remainder(pyus_left, pyus_right);
  1996. Py_DECREF(pyus_left);
  1997. Py_DECREF(pyus_right);
  1998. if (pyus_remainder == NULL)
  1999. return NULL;
  2000. remainder = microseconds_to_delta(pyus_remainder);
  2001. Py_DECREF(pyus_remainder);
  2002. if (remainder == NULL)
  2003. return NULL;
  2004. return remainder;
  2005. }
  2006. static PyObject *
  2007. delta_divmod(PyObject *left, PyObject *right)
  2008. {
  2009. PyObject *pyus_left;
  2010. PyObject *pyus_right;
  2011. PyObject *divmod;
  2012. PyObject *delta;
  2013. PyObject *result;
  2014. if (!PyDelta_Check(left) || !PyDelta_Check(right))
  2015. Py_RETURN_NOTIMPLEMENTED;
  2016. pyus_left = delta_to_microseconds((PyDateTime_Delta *)left);
  2017. if (pyus_left == NULL)
  2018. return NULL;
  2019. pyus_right = delta_to_microseconds((PyDateTime_Delta *)right);
  2020. if (pyus_right == NULL) {
  2021. Py_DECREF(pyus_left);
  2022. return NULL;
  2023. }
  2024. divmod = checked_divmod(pyus_left, pyus_right);
  2025. Py_DECREF(pyus_left);
  2026. Py_DECREF(pyus_right);
  2027. if (divmod == NULL)
  2028. return NULL;
  2029. delta = microseconds_to_delta(PyTuple_GET_ITEM(divmod, 1));
  2030. if (delta == NULL) {
  2031. Py_DECREF(divmod);
  2032. return NULL;
  2033. }
  2034. result = PyTuple_Pack(2, PyTuple_GET_ITEM(divmod, 0), delta);
  2035. Py_DECREF(delta);
  2036. Py_DECREF(divmod);
  2037. return result;
  2038. }
  2039. /* Fold in the value of the tag ("seconds", "weeks", etc) component of a
  2040. * timedelta constructor. sofar is the # of microseconds accounted for
  2041. * so far, and there are factor microseconds per current unit, the number
  2042. * of which is given by num. num * factor is added to sofar in a
  2043. * numerically careful way, and that's the result. Any fractional
  2044. * microseconds left over (this can happen if num is a float type) are
  2045. * added into *leftover.
  2046. * Note that there are many ways this can give an error (NULL) return.
  2047. */
  2048. static PyObject *
  2049. accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
  2050. double *leftover)
  2051. {
  2052. PyObject *prod;
  2053. PyObject *sum;
  2054. assert(num != NULL);
  2055. if (PyLong_Check(num)) {
  2056. prod = PyNumber_Multiply(num, factor);
  2057. if (prod == NULL)
  2058. return NULL;
  2059. sum = PyNumber_Add(sofar, prod);
  2060. Py_DECREF(prod);
  2061. return sum;
  2062. }
  2063. if (PyFloat_Check(num)) {
  2064. double dnum;
  2065. double fracpart;
  2066. double intpart;
  2067. PyObject *x;
  2068. PyObject *y;
  2069. /* The Plan: decompose num into an integer part and a
  2070. * fractional part, num = intpart + fracpart.
  2071. * Then num * factor ==
  2072. * intpart * factor + fracpart * factor
  2073. * and the LHS can be computed exactly in long arithmetic.
  2074. * The RHS is again broken into an int part and frac part.
  2075. * and the frac part is added into *leftover.
  2076. */
  2077. dnum = PyFloat_AsDouble(num);
  2078. if (dnum == -1.0 && PyErr_Occurred())
  2079. return NULL;
  2080. fracpart = modf(dnum, &intpart);
  2081. x = PyLong_FromDouble(intpart);
  2082. if (x == NULL)
  2083. return NULL;
  2084. prod = PyNumber_Multiply(x, factor);
  2085. Py_DECREF(x);
  2086. if (prod == NULL)
  2087. return NULL;
  2088. sum = PyNumber_Add(sofar, prod);
  2089. Py_DECREF(prod);
  2090. if (sum == NULL)
  2091. return NULL;
  2092. if (fracpart == 0.0)
  2093. return sum;
  2094. /* So far we've lost no information. Dealing with the
  2095. * fractional part requires float arithmetic, and may
  2096. * lose a little info.
  2097. */
  2098. assert(PyLong_CheckExact(factor));
  2099. dnum = PyLong_AsDouble(factor);
  2100. dnum *= fracpart;
  2101. fracpart = modf(dnum, &intpart);
  2102. x = PyLong_FromDouble(intpart);
  2103. if (x == NULL) {
  2104. Py_DECREF(sum);
  2105. return NULL;
  2106. }
  2107. y = PyNumber_Add(sum, x);
  2108. Py_DECREF(sum);
  2109. Py_DECREF(x);
  2110. *leftover += fracpart;
  2111. return y;
  2112. }
  2113. PyErr_Format(PyExc_TypeError,
  2114. "unsupported type for timedelta %s component: %s",
  2115. tag, Py_TYPE(num)->tp_name);
  2116. return NULL;
  2117. }
  2118. static PyObject *
  2119. delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
  2120. {
  2121. PyObject *self = NULL;
  2122. /* Argument objects. */
  2123. PyObject *day = NULL;
  2124. PyObject *second = NULL;
  2125. PyObject *us = NULL;
  2126. PyObject *ms = NULL;
  2127. PyObject *minute = NULL;
  2128. PyObject *hour = NULL;
  2129. PyObject *week = NULL;
  2130. PyObject *x = NULL; /* running sum of microseconds */
  2131. PyObject *y = NULL; /* temp sum of microseconds */
  2132. double leftover_us = 0.0;
  2133. static char *keywords[] = {
  2134. "days", "seconds", "microseconds", "milliseconds",
  2135. "minutes", "hours", "weeks", NULL
  2136. };
  2137. if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
  2138. keywords,
  2139. &day, &second, &us,
  2140. &ms, &minute, &hour, &week) == 0)
  2141. goto Done;
  2142. x = PyLong_FromLong(0);
  2143. if (x == NULL)
  2144. goto Done;
  2145. #define CLEANUP \
  2146. Py_DECREF(x); \
  2147. x = y; \
  2148. if (x == NULL) \
  2149. goto Done
  2150. if (us) {
  2151. y = accum("microseconds", x, us, _PyLong_GetOne(), &leftover_us);
  2152. CLEANUP;
  2153. }
  2154. if (ms) {
  2155. y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
  2156. CLEANUP;
  2157. }
  2158. if (second) {
  2159. y = accum("seconds", x, second, us_per_second, &leftover_us);
  2160. CLEANUP;
  2161. }
  2162. if (minute) {
  2163. y = accum("minutes", x, minute, us_per_minute, &leftover_us);
  2164. CLEANUP;
  2165. }
  2166. if (hour) {
  2167. y = accum("hours", x, hour, us_per_hour, &leftover_us);
  2168. CLEANUP;
  2169. }
  2170. if (day) {
  2171. y = accum("days", x, day, us_per_day, &leftover_us);
  2172. CLEANUP;
  2173. }
  2174. if (week) {
  2175. y = accum("weeks", x, week, us_per_week, &leftover_us);
  2176. CLEANUP;
  2177. }
  2178. if (leftover_us) {
  2179. /* Round to nearest whole # of us, and add into x. */
  2180. double whole_us = round(leftover_us);
  2181. int x_is_odd;
  2182. PyObject *temp;
  2183. if (fabs(whole_us - leftover_us) == 0.5) {
  2184. /* We're exactly halfway between two integers. In order
  2185. * to do round-half-to-even, we must determine whether x
  2186. * is odd. Note that x is odd when it's last bit is 1. The
  2187. * code below uses bitwise and operation to check the last
  2188. * bit. */
  2189. temp = PyNumber_And(x, _PyLong_GetOne()); /* temp <- x & 1 */
  2190. if (temp == NULL) {
  2191. Py_DECREF(x);
  2192. goto Done;
  2193. }
  2194. x_is_odd = PyObject_IsTrue(temp);
  2195. Py_DECREF(temp);
  2196. if (x_is_odd == -1) {
  2197. Py_DECREF(x);
  2198. goto Done;
  2199. }
  2200. whole_us = 2.0 * round((leftover_us + x_is_odd) * 0.5) - x_is_odd;
  2201. }
  2202. temp = PyLong_FromLong((long)whole_us);
  2203. if (temp == NULL) {
  2204. Py_DECREF(x);
  2205. goto Done;
  2206. }
  2207. y = PyNumber_Add(x, temp);
  2208. Py_DECREF(temp);
  2209. CLEANUP;
  2210. }
  2211. self = microseconds_to_delta_ex(x, type);
  2212. Py_DECREF(x);
  2213. Done:
  2214. return self;
  2215. #undef CLEANUP
  2216. }
  2217. static int
  2218. delta_bool(PyDateTime_Delta *self)
  2219. {
  2220. return (GET_TD_DAYS(self) != 0
  2221. || GET_TD_SECONDS(self) != 0
  2222. || GET_TD_MICROSECONDS(self) != 0);
  2223. }
  2224. static PyObject *
  2225. delta_repr(PyDateTime_Delta *self)
  2226. {
  2227. PyObject *args = PyUnicode_FromString("");
  2228. if (args == NULL) {
  2229. return NULL;
  2230. }
  2231. const char *sep = "";
  2232. if (GET_TD_DAYS(self) != 0) {
  2233. Py_SETREF(args, PyUnicode_FromFormat("days=%d", GET_TD_DAYS(self)));
  2234. if (args == NULL) {
  2235. return NULL;
  2236. }
  2237. sep = ", ";
  2238. }
  2239. if (GET_TD_SECONDS(self) != 0) {
  2240. Py_SETREF(args, PyUnicode_FromFormat("%U%sseconds=%d", args, sep,
  2241. GET_TD_SECONDS(self)));
  2242. if (args == NULL) {
  2243. return NULL;
  2244. }
  2245. sep = ", ";
  2246. }
  2247. if (GET_TD_MICROSECONDS(self) != 0) {
  2248. Py_SETREF(args, PyUnicode_FromFormat("%U%smicroseconds=%d", args, sep,
  2249. GET_TD_MICROSECONDS(self)));
  2250. if (args == NULL) {
  2251. return NULL;
  2252. }
  2253. }
  2254. if (PyUnicode_GET_LENGTH(args) == 0) {
  2255. Py_SETREF(args, PyUnicode_FromString("0"));
  2256. if (args == NULL) {
  2257. return NULL;
  2258. }
  2259. }
  2260. PyObject *repr = PyUnicode_FromFormat("%s(%S)", Py_TYPE(self)->tp_name,
  2261. args);
  2262. Py_DECREF(args);
  2263. return repr;
  2264. }
  2265. static PyObject *
  2266. delta_str(PyDateTime_Delta *self)
  2267. {
  2268. int us = GET_TD_MICROSECONDS(self);
  2269. int seconds = GET_TD_SECONDS(self);
  2270. int minutes = divmod(seconds, 60, &seconds);
  2271. int hours = divmod(minutes, 60, &minutes);
  2272. int days = GET_TD_DAYS(self);
  2273. if (days) {
  2274. if (us)
  2275. return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d.%06d",
  2276. days, (days == 1 || days == -1) ? "" : "s",
  2277. hours, minutes, seconds, us);
  2278. else
  2279. return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d",
  2280. days, (days == 1 || days == -1) ? "" : "s",
  2281. hours, minutes, seconds);
  2282. } else {
  2283. if (us)
  2284. return PyUnicode_FromFormat("%d:%02d:%02d.%06d",
  2285. hours, minutes, seconds, us);
  2286. else
  2287. return PyUnicode_FromFormat("%d:%02d:%02d",
  2288. hours, minutes, seconds);
  2289. }
  2290. }
  2291. /* Pickle support, a simple use of __reduce__. */
  2292. /* __getstate__ isn't exposed */
  2293. static PyObject *
  2294. delta_getstate(PyDateTime_Delta *self)
  2295. {
  2296. return Py_BuildValue("iii", GET_TD_DAYS(self),
  2297. GET_TD_SECONDS(self),
  2298. GET_TD_MICROSECONDS(self));
  2299. }
  2300. static PyObject *
  2301. delta_total_seconds(PyObject *self, PyObject *Py_UNUSED(ignored))
  2302. {
  2303. PyObject *total_seconds;
  2304. PyObject *total_microseconds;
  2305. total_microseconds = delta_to_microseconds((PyDateTime_Delta *)self);
  2306. if (total_microseconds == NULL)
  2307. return NULL;
  2308. total_seconds = PyNumber_TrueDivide(total_microseconds, us_per_second);
  2309. Py_DECREF(total_microseconds);
  2310. return total_seconds;
  2311. }
  2312. static PyObject *
  2313. delta_reduce(PyDateTime_Delta* self, PyObject *Py_UNUSED(ignored))
  2314. {
  2315. return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self));
  2316. }
  2317. #define OFFSET(field) offsetof(PyDateTime_Delta, field)
  2318. static PyMemberDef delta_members[] = {
  2319. {"days", T_INT, OFFSET(days), READONLY,
  2320. PyDoc_STR("Number of days.")},
  2321. {"seconds", T_INT, OFFSET(seconds), READONLY,
  2322. PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
  2323. {"microseconds", T_INT, OFFSET(microseconds), READONLY,
  2324. PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
  2325. {NULL}
  2326. };
  2327. static PyMethodDef delta_methods[] = {
  2328. {"total_seconds", delta_total_seconds, METH_NOARGS,
  2329. PyDoc_STR("Total seconds in the duration.")},
  2330. {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
  2331. PyDoc_STR("__reduce__() -> (cls, state)")},
  2332. {NULL, NULL},
  2333. };
  2334. static const char delta_doc[] =
  2335. PyDoc_STR("Difference between two datetime values.\n\n"
  2336. "timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, "
  2337. "minutes=0, hours=0, weeks=0)\n\n"
  2338. "All arguments are optional and default to 0.\n"
  2339. "Arguments may be integers or floats, and may be positive or negative.");
  2340. static PyNumberMethods delta_as_number = {
  2341. delta_add, /* nb_add */
  2342. delta_subtract, /* nb_subtract */
  2343. delta_multiply, /* nb_multiply */
  2344. delta_remainder, /* nb_remainder */
  2345. delta_divmod, /* nb_divmod */
  2346. 0, /* nb_power */
  2347. (unaryfunc)delta_negative, /* nb_negative */
  2348. (unaryfunc)delta_positive, /* nb_positive */
  2349. (unaryfunc)delta_abs, /* nb_absolute */
  2350. (inquiry)delta_bool, /* nb_bool */
  2351. 0, /*nb_invert*/
  2352. 0, /*nb_lshift*/
  2353. 0, /*nb_rshift*/
  2354. 0, /*nb_and*/
  2355. 0, /*nb_xor*/
  2356. 0, /*nb_or*/
  2357. 0, /*nb_int*/
  2358. 0, /*nb_reserved*/
  2359. 0, /*nb_float*/
  2360. 0, /*nb_inplace_add*/
  2361. 0, /*nb_inplace_subtract*/
  2362. 0, /*nb_inplace_multiply*/
  2363. 0, /*nb_inplace_remainder*/
  2364. 0, /*nb_inplace_power*/
  2365. 0, /*nb_inplace_lshift*/
  2366. 0, /*nb_inplace_rshift*/
  2367. 0, /*nb_inplace_and*/
  2368. 0, /*nb_inplace_xor*/
  2369. 0, /*nb_inplace_or*/
  2370. delta_divide, /* nb_floor_divide */
  2371. delta_truedivide, /* nb_true_divide */
  2372. 0, /* nb_inplace_floor_divide */
  2373. 0, /* nb_inplace_true_divide */
  2374. };
  2375. static PyTypeObject PyDateTime_DeltaType = {
  2376. PyVarObject_HEAD_INIT(NULL, 0)
  2377. "datetime.timedelta", /* tp_name */
  2378. sizeof(PyDateTime_Delta), /* tp_basicsize */
  2379. 0, /* tp_itemsize */
  2380. 0, /* tp_dealloc */
  2381. 0, /* tp_vectorcall_offset */
  2382. 0, /* tp_getattr */
  2383. 0, /* tp_setattr */
  2384. 0, /* tp_as_async */
  2385. (reprfunc)delta_repr, /* tp_repr */
  2386. &delta_as_number, /* tp_as_number */
  2387. 0, /* tp_as_sequence */
  2388. 0, /* tp_as_mapping */
  2389. (hashfunc)delta_hash, /* tp_hash */
  2390. 0, /* tp_call */
  2391. (reprfunc)delta_str, /* tp_str */
  2392. PyObject_GenericGetAttr, /* tp_getattro */
  2393. 0, /* tp_setattro */
  2394. 0, /* tp_as_buffer */
  2395. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  2396. delta_doc, /* tp_doc */
  2397. 0, /* tp_traverse */
  2398. 0, /* tp_clear */
  2399. delta_richcompare, /* tp_richcompare */
  2400. 0, /* tp_weaklistoffset */
  2401. 0, /* tp_iter */
  2402. 0, /* tp_iternext */
  2403. delta_methods, /* tp_methods */
  2404. delta_members, /* tp_members */
  2405. 0, /* tp_getset */
  2406. 0, /* tp_base */
  2407. 0, /* tp_dict */
  2408. 0, /* tp_descr_get */
  2409. 0, /* tp_descr_set */
  2410. 0, /* tp_dictoffset */
  2411. 0, /* tp_init */
  2412. 0, /* tp_alloc */
  2413. delta_new, /* tp_new */
  2414. 0, /* tp_free */
  2415. };
  2416. /*
  2417. * PyDateTime_Date implementation.
  2418. */
  2419. /* Accessor properties. */
  2420. static PyObject *
  2421. date_year(PyDateTime_Date *self, void *unused)
  2422. {
  2423. return PyLong_FromLong(GET_YEAR(self));
  2424. }
  2425. static PyObject *
  2426. date_month(PyDateTime_Date *self, void *unused)
  2427. {
  2428. return PyLong_FromLong(GET_MONTH(self));
  2429. }
  2430. static PyObject *
  2431. date_day(PyDateTime_Date *self, void *unused)
  2432. {
  2433. return PyLong_FromLong(GET_DAY(self));
  2434. }
  2435. static PyGetSetDef date_getset[] = {
  2436. {"year", (getter)date_year},
  2437. {"month", (getter)date_month},
  2438. {"day", (getter)date_day},
  2439. {NULL}
  2440. };
  2441. /* Constructors. */
  2442. static char *date_kws[] = {"year", "month", "day", NULL};
  2443. static PyObject *
  2444. date_from_pickle(PyTypeObject *type, PyObject *state)
  2445. {
  2446. PyDateTime_Date *me;
  2447. me = (PyDateTime_Date *) (type->tp_alloc(type, 0));
  2448. if (me != NULL) {
  2449. const char *pdata = PyBytes_AS_STRING(state);
  2450. memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE);
  2451. me->hashcode = -1;
  2452. }
  2453. return (PyObject *)me;
  2454. }
  2455. static PyObject *
  2456. date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
  2457. {
  2458. PyObject *self = NULL;
  2459. int year;
  2460. int month;
  2461. int day;
  2462. /* Check for invocation from pickle with __getstate__ state */
  2463. if (PyTuple_GET_SIZE(args) == 1) {
  2464. PyObject *state = PyTuple_GET_ITEM(args, 0);
  2465. if (PyBytes_Check(state)) {
  2466. if (PyBytes_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE &&
  2467. MONTH_IS_SANE(PyBytes_AS_STRING(state)[2]))
  2468. {
  2469. return date_from_pickle(type, state);
  2470. }
  2471. }
  2472. else if (PyUnicode_Check(state)) {
  2473. if (PyUnicode_READY(state)) {
  2474. return NULL;
  2475. }
  2476. if (PyUnicode_GET_LENGTH(state) == _PyDateTime_DATE_DATASIZE &&
  2477. MONTH_IS_SANE(PyUnicode_READ_CHAR(state, 2)))
  2478. {
  2479. state = PyUnicode_AsLatin1String(state);
  2480. if (state == NULL) {
  2481. if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
  2482. /* More informative error message. */
  2483. PyErr_SetString(PyExc_ValueError,
  2484. "Failed to encode latin1 string when unpickling "
  2485. "a date object. "
  2486. "pickle.load(data, encoding='latin1') is assumed.");
  2487. }
  2488. return NULL;
  2489. }
  2490. self = date_from_pickle(type, state);
  2491. Py_DECREF(state);
  2492. return self;
  2493. }
  2494. }
  2495. }
  2496. if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
  2497. &year, &month, &day)) {
  2498. self = new_date_ex(year, month, day, type);
  2499. }
  2500. return self;
  2501. }
  2502. static PyObject *
  2503. date_fromtimestamp(PyObject *cls, PyObject *obj)
  2504. {
  2505. struct tm tm;
  2506. time_t t;
  2507. if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_FLOOR) == -1)
  2508. return NULL;
  2509. if (_PyTime_localtime(t, &tm) != 0)
  2510. return NULL;
  2511. return new_date_subclass_ex(tm.tm_year + 1900,
  2512. tm.tm_mon + 1,
  2513. tm.tm_mday,
  2514. cls);
  2515. }
  2516. /* Return new date from current time.
  2517. * We say this is equivalent to fromtimestamp(time.time()), and the
  2518. * only way to be sure of that is to *call* time.time(). That's not
  2519. * generally the same as calling C's time.
  2520. */
  2521. static PyObject *
  2522. date_today(PyObject *cls, PyObject *dummy)
  2523. {
  2524. PyObject *time;
  2525. PyObject *result;
  2526. _Py_IDENTIFIER(fromtimestamp);
  2527. time = time_time();
  2528. if (time == NULL)
  2529. return NULL;
  2530. /* Note well: today() is a class method, so this may not call
  2531. * date.fromtimestamp. For example, it may call
  2532. * datetime.fromtimestamp. That's why we need all the accuracy
  2533. * time.time() delivers; if someone were gonzo about optimization,
  2534. * date.today() could get away with plain C time().
  2535. */
  2536. result = _PyObject_CallMethodIdOneArg(cls, &PyId_fromtimestamp, time);
  2537. Py_DECREF(time);
  2538. return result;
  2539. }
  2540. /*[clinic input]
  2541. @classmethod
  2542. datetime.date.fromtimestamp
  2543. timestamp: object
  2544. /
  2545. Create a date from a POSIX timestamp.
  2546. The timestamp is a number, e.g. created via time.time(), that is interpreted
  2547. as local time.
  2548. [clinic start generated code]*/
  2549. static PyObject *
  2550. datetime_date_fromtimestamp(PyTypeObject *type, PyObject *timestamp)
  2551. /*[clinic end generated code: output=fd045fda58168869 input=eabb3fe7f40491fe]*/
  2552. {
  2553. return date_fromtimestamp((PyObject *) type, timestamp);
  2554. }
  2555. /* bpo-36025: This is a wrapper for API compatibility with the public C API,
  2556. * which expects a function that takes an *args tuple, whereas the argument
  2557. * clinic generates code that takes METH_O.
  2558. */
  2559. static PyObject *
  2560. datetime_date_fromtimestamp_capi(PyObject *cls, PyObject *args)
  2561. {
  2562. PyObject *timestamp;
  2563. PyObject *result = NULL;
  2564. if (PyArg_UnpackTuple(args, "fromtimestamp", 1, 1, &timestamp)) {
  2565. result = date_fromtimestamp(cls, timestamp);
  2566. }
  2567. return result;
  2568. }
  2569. /* Return new date from proleptic Gregorian ordinal. Raises ValueError if
  2570. * the ordinal is out of range.
  2571. */
  2572. static PyObject *
  2573. date_fromordinal(PyObject *cls, PyObject *args)
  2574. {
  2575. PyObject *result = NULL;
  2576. int ordinal;
  2577. if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
  2578. int year;
  2579. int month;
  2580. int day;
  2581. if (ordinal < 1)
  2582. PyErr_SetString(PyExc_ValueError, "ordinal must be "
  2583. ">= 1");
  2584. else {
  2585. ord_to_ymd(ordinal, &year, &month, &day);
  2586. result = new_date_subclass_ex(year, month, day, cls);
  2587. }
  2588. }
  2589. return result;
  2590. }
  2591. /* Return the new date from a string as generated by date.isoformat() */
  2592. static PyObject *
  2593. date_fromisoformat(PyObject *cls, PyObject *dtstr)
  2594. {
  2595. assert(dtstr != NULL);
  2596. if (!PyUnicode_Check(dtstr)) {
  2597. PyErr_SetString(PyExc_TypeError,
  2598. "fromisoformat: argument must be str");
  2599. return NULL;
  2600. }
  2601. Py_ssize_t len;
  2602. const char *dt_ptr = PyUnicode_AsUTF8AndSize(dtstr, &len);
  2603. if (dt_ptr == NULL) {
  2604. goto invalid_string_error;
  2605. }
  2606. int year = 0, month = 0, day = 0;
  2607. int rv;
  2608. if (len == 10) {
  2609. rv = parse_isoformat_date(dt_ptr, &year, &month, &day);
  2610. }
  2611. else {
  2612. rv = -1;
  2613. }
  2614. if (rv < 0) {
  2615. goto invalid_string_error;
  2616. }
  2617. return new_date_subclass_ex(year, month, day, cls);
  2618. invalid_string_error:
  2619. PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", dtstr);
  2620. return NULL;
  2621. }
  2622. static PyObject *
  2623. date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw)
  2624. {
  2625. static char *keywords[] = {
  2626. "year", "week", "day", NULL
  2627. };
  2628. int year, week, day;
  2629. if (PyArg_ParseTupleAndKeywords(args, kw, "iii:fromisocalendar",
  2630. keywords,
  2631. &year, &week, &day) == 0) {
  2632. if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
  2633. PyErr_Format(PyExc_ValueError,
  2634. "ISO calendar component out of range");
  2635. }
  2636. return NULL;
  2637. }
  2638. // Year is bounded to 0 < year < 10000 because 9999-12-31 is (9999, 52, 5)
  2639. if (year < MINYEAR || year > MAXYEAR) {
  2640. PyErr_Format(PyExc_ValueError, "Year is out of range: %d", year);
  2641. return NULL;
  2642. }
  2643. if (week <= 0 || week >= 53) {
  2644. int out_of_range = 1;
  2645. if (week == 53) {
  2646. // ISO years have 53 weeks in it on years starting with a Thursday
  2647. // and on leap years starting on Wednesday
  2648. int first_weekday = weekday(year, 1, 1);
  2649. if (first_weekday == 3 || (first_weekday == 2 && is_leap(year))) {
  2650. out_of_range = 0;
  2651. }
  2652. }
  2653. if (out_of_range) {
  2654. PyErr_Format(PyExc_ValueError, "Invalid week: %d", week);
  2655. return NULL;
  2656. }
  2657. }
  2658. if (day <= 0 || day >= 8) {
  2659. PyErr_Format(PyExc_ValueError, "Invalid day: %d (range is [1, 7])",
  2660. day);
  2661. return NULL;
  2662. }
  2663. // Convert (Y, W, D) to (Y, M, D) in-place
  2664. int day_1 = iso_week1_monday(year);
  2665. int month = week;
  2666. int day_offset = (month - 1)*7 + day - 1;
  2667. ord_to_ymd(day_1 + day_offset, &year, &month, &day);
  2668. return new_date_subclass_ex(year, month, day, cls);
  2669. }
  2670. /*
  2671. * Date arithmetic.
  2672. */
  2673. /* date + timedelta -> date. If arg negate is true, subtract the timedelta
  2674. * instead.
  2675. */
  2676. static PyObject *
  2677. add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
  2678. {
  2679. PyObject *result = NULL;
  2680. int year = GET_YEAR(date);
  2681. int month = GET_MONTH(date);
  2682. int deltadays = GET_TD_DAYS(delta);
  2683. /* C-level overflow is impossible because |deltadays| < 1e9. */
  2684. int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
  2685. if (normalize_date(&year, &month, &day) >= 0)
  2686. result = new_date_subclass_ex(year, month, day,
  2687. (PyObject* )Py_TYPE(date));
  2688. return result;
  2689. }
  2690. static PyObject *
  2691. date_add(PyObject *left, PyObject *right)
  2692. {
  2693. if (PyDateTime_Check(left) || PyDateTime_Check(right))
  2694. Py_RETURN_NOTIMPLEMENTED;
  2695. if (PyDate_Check(left)) {
  2696. /* date + ??? */
  2697. if (PyDelta_Check(right))
  2698. /* date + delta */
  2699. return add_date_timedelta((PyDateTime_Date *) left,
  2700. (PyDateTime_Delta *) right,
  2701. 0);
  2702. }
  2703. else {
  2704. /* ??? + date
  2705. * 'right' must be one of us, or we wouldn't have been called
  2706. */
  2707. if (PyDelta_Check(left))
  2708. /* delta + date */
  2709. return add_date_timedelta((PyDateTime_Date *) right,
  2710. (PyDateTime_Delta *) left,
  2711. 0);
  2712. }
  2713. Py_RETURN_NOTIMPLEMENTED;
  2714. }
  2715. static PyObject *
  2716. date_subtract(PyObject *left, PyObject *right)
  2717. {
  2718. if (PyDateTime_Check(left) || PyDateTime_Check(right))
  2719. Py_RETURN_NOTIMPLEMENTED;
  2720. if (PyDate_Check(left)) {
  2721. if (PyDate_Check(right)) {
  2722. /* date - date */
  2723. int left_ord = ymd_to_ord(GET_YEAR(left),
  2724. GET_MONTH(left),
  2725. GET_DAY(left));
  2726. int right_ord = ymd_to_ord(GET_YEAR(right),
  2727. GET_MONTH(right),
  2728. GET_DAY(right));
  2729. return new_delta(left_ord - right_ord, 0, 0, 0);
  2730. }
  2731. if (PyDelta_Check(right)) {
  2732. /* date - delta */
  2733. return add_date_timedelta((PyDateTime_Date *) left,
  2734. (PyDateTime_Delta *) right,
  2735. 1);
  2736. }
  2737. }
  2738. Py_RETURN_NOTIMPLEMENTED;
  2739. }
  2740. /* Various ways to turn a date into a string. */
  2741. static PyObject *
  2742. date_repr(PyDateTime_Date *self)
  2743. {
  2744. return PyUnicode_FromFormat("%s(%d, %d, %d)",
  2745. Py_TYPE(self)->tp_name,
  2746. GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
  2747. }
  2748. static PyObject *
  2749. date_isoformat(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
  2750. {
  2751. return PyUnicode_FromFormat("%04d-%02d-%02d",
  2752. GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
  2753. }
  2754. /* str() calls the appropriate isoformat() method. */
  2755. static PyObject *
  2756. date_str(PyDateTime_Date *self)
  2757. {
  2758. return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
  2759. }
  2760. static PyObject *
  2761. date_ctime(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
  2762. {
  2763. return format_ctime(self, 0, 0, 0);
  2764. }
  2765. static PyObject *
  2766. date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
  2767. {
  2768. /* This method can be inherited, and needs to call the
  2769. * timetuple() method appropriate to self's class.
  2770. */
  2771. PyObject *result;
  2772. PyObject *tuple;
  2773. PyObject *format;
  2774. _Py_IDENTIFIER(timetuple);
  2775. static char *keywords[] = {"format", NULL};
  2776. if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords,
  2777. &format))
  2778. return NULL;
  2779. tuple = _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_timetuple);
  2780. if (tuple == NULL)
  2781. return NULL;
  2782. result = wrap_strftime((PyObject *)self, format, tuple,
  2783. (PyObject *)self);
  2784. Py_DECREF(tuple);
  2785. return result;
  2786. }
  2787. static PyObject *
  2788. date_format(PyDateTime_Date *self, PyObject *args)
  2789. {
  2790. PyObject *format;
  2791. if (!PyArg_ParseTuple(args, "U:__format__", &format))
  2792. return NULL;
  2793. /* if the format is zero length, return str(self) */
  2794. if (PyUnicode_GetLength(format) == 0)
  2795. return PyObject_Str((PyObject *)self);
  2796. return _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId_strftime,
  2797. format);
  2798. }
  2799. /* ISO methods. */
  2800. static PyObject *
  2801. date_isoweekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
  2802. {
  2803. int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
  2804. return PyLong_FromLong(dow + 1);
  2805. }
  2806. PyDoc_STRVAR(iso_calendar_date__doc__,
  2807. "The result of date.isocalendar() or datetime.isocalendar()\n\n\
  2808. This object may be accessed either as a tuple of\n\
  2809. ((year, week, weekday)\n\
  2810. or via the object attributes as named in the above tuple.");
  2811. typedef struct {
  2812. PyTupleObject tuple;
  2813. } PyDateTime_IsoCalendarDate;
  2814. static PyObject *
  2815. iso_calendar_date_repr(PyDateTime_IsoCalendarDate *self)
  2816. {
  2817. PyObject* year = PyTuple_GetItem((PyObject *)self, 0);
  2818. if (year == NULL) {
  2819. return NULL;
  2820. }
  2821. PyObject* week = PyTuple_GetItem((PyObject *)self, 1);
  2822. if (week == NULL) {
  2823. return NULL;
  2824. }
  2825. PyObject* weekday = PyTuple_GetItem((PyObject *)self, 2);
  2826. if (weekday == NULL) {
  2827. return NULL;
  2828. }
  2829. return PyUnicode_FromFormat("%.200s(year=%S, week=%S, weekday=%S)",
  2830. Py_TYPE(self)->tp_name, year, week, weekday);
  2831. }
  2832. static PyObject *
  2833. iso_calendar_date_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
  2834. {
  2835. // Construct the tuple that this reduces to
  2836. PyObject * reduce_tuple = Py_BuildValue(
  2837. "O((OOO))", &PyTuple_Type,
  2838. PyTuple_GET_ITEM(self, 0),
  2839. PyTuple_GET_ITEM(self, 1),
  2840. PyTuple_GET_ITEM(self, 2)
  2841. );
  2842. return reduce_tuple;
  2843. }
  2844. static PyObject *
  2845. iso_calendar_date_year(PyDateTime_IsoCalendarDate *self, void *unused)
  2846. {
  2847. PyObject *year = PyTuple_GetItem((PyObject *)self, 0);
  2848. if (year == NULL) {
  2849. return NULL;
  2850. }
  2851. Py_INCREF(year);
  2852. return year;
  2853. }
  2854. static PyObject *
  2855. iso_calendar_date_week(PyDateTime_IsoCalendarDate *self, void *unused)
  2856. {
  2857. PyObject *week = PyTuple_GetItem((PyObject *)self, 1);
  2858. if (week == NULL) {
  2859. return NULL;
  2860. }
  2861. Py_INCREF(week);
  2862. return week;
  2863. }
  2864. static PyObject *
  2865. iso_calendar_date_weekday(PyDateTime_IsoCalendarDate *self, void *unused)
  2866. {
  2867. PyObject *weekday = PyTuple_GetItem((PyObject *)self, 2);
  2868. if (weekday == NULL) {
  2869. return NULL;
  2870. }
  2871. Py_INCREF(weekday);
  2872. return weekday;
  2873. }
  2874. static PyGetSetDef iso_calendar_date_getset[] = {
  2875. {"year", (getter)iso_calendar_date_year},
  2876. {"week", (getter)iso_calendar_date_week},
  2877. {"weekday", (getter)iso_calendar_date_weekday},
  2878. {NULL}
  2879. };
  2880. static PyMethodDef iso_calendar_date_methods[] = {
  2881. {"__reduce__", (PyCFunction)iso_calendar_date_reduce, METH_NOARGS,
  2882. PyDoc_STR("__reduce__() -> (cls, state)")},
  2883. {NULL, NULL},
  2884. };
  2885. static PyTypeObject PyDateTime_IsoCalendarDateType = {
  2886. PyVarObject_HEAD_INIT(NULL, 0)
  2887. .tp_name = "datetime.IsoCalendarDate",
  2888. .tp_basicsize = sizeof(PyDateTime_IsoCalendarDate),
  2889. .tp_repr = (reprfunc) iso_calendar_date_repr,
  2890. .tp_flags = Py_TPFLAGS_DEFAULT,
  2891. .tp_doc = iso_calendar_date__doc__,
  2892. .tp_methods = iso_calendar_date_methods,
  2893. .tp_getset = iso_calendar_date_getset,
  2894. // .tp_base = &PyTuple_Type, // filled in PyInit__datetime
  2895. .tp_new = iso_calendar_date_new,
  2896. };
  2897. /*[clinic input]
  2898. @classmethod
  2899. datetime.IsoCalendarDate.__new__ as iso_calendar_date_new
  2900. year: int
  2901. week: int
  2902. weekday: int
  2903. [clinic start generated code]*/
  2904. static PyObject *
  2905. iso_calendar_date_new_impl(PyTypeObject *type, int year, int week,
  2906. int weekday)
  2907. /*[clinic end generated code: output=383d33d8dc7183a2 input=4f2c663c9d19c4ee]*/
  2908. {
  2909. PyDateTime_IsoCalendarDate *self;
  2910. self = (PyDateTime_IsoCalendarDate *) type->tp_alloc(type, 3);
  2911. if (self == NULL) {
  2912. return NULL;
  2913. }
  2914. PyTuple_SET_ITEM(self, 0, PyLong_FromLong(year));
  2915. PyTuple_SET_ITEM(self, 1, PyLong_FromLong(week));
  2916. PyTuple_SET_ITEM(self, 2, PyLong_FromLong(weekday));
  2917. return (PyObject *)self;
  2918. }
  2919. static PyObject *
  2920. date_isocalendar(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
  2921. {
  2922. int year = GET_YEAR(self);
  2923. int week1_monday = iso_week1_monday(year);
  2924. int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
  2925. int week;
  2926. int day;
  2927. week = divmod(today - week1_monday, 7, &day);
  2928. if (week < 0) {
  2929. --year;
  2930. week1_monday = iso_week1_monday(year);
  2931. week = divmod(today - week1_monday, 7, &day);
  2932. }
  2933. else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
  2934. ++year;
  2935. week = 0;
  2936. }
  2937. PyObject* v = iso_calendar_date_new_impl(&PyDateTime_IsoCalendarDateType,
  2938. year, week + 1, day + 1);
  2939. if (v == NULL) {
  2940. return NULL;
  2941. }
  2942. return v;
  2943. }
  2944. /* Miscellaneous methods. */
  2945. static PyObject *
  2946. date_richcompare(PyObject *self, PyObject *other, int op)
  2947. {
  2948. if (PyDate_Check(other)) {
  2949. int diff = memcmp(((PyDateTime_Date *)self)->data,
  2950. ((PyDateTime_Date *)other)->data,
  2951. _PyDateTime_DATE_DATASIZE);
  2952. return diff_to_bool(diff, op);
  2953. }
  2954. else
  2955. Py_RETURN_NOTIMPLEMENTED;
  2956. }
  2957. static PyObject *
  2958. date_timetuple(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
  2959. {
  2960. return build_struct_time(GET_YEAR(self),
  2961. GET_MONTH(self),
  2962. GET_DAY(self),
  2963. 0, 0, 0, -1);
  2964. }
  2965. static PyObject *
  2966. date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
  2967. {
  2968. PyObject *clone;
  2969. PyObject *tuple;
  2970. int year = GET_YEAR(self);
  2971. int month = GET_MONTH(self);
  2972. int day = GET_DAY(self);
  2973. if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
  2974. &year, &month, &day))
  2975. return NULL;
  2976. tuple = Py_BuildValue("iii", year, month, day);
  2977. if (tuple == NULL)
  2978. return NULL;
  2979. clone = date_new(Py_TYPE(self), tuple, NULL);
  2980. Py_DECREF(tuple);
  2981. return clone;
  2982. }
  2983. static Py_hash_t
  2984. generic_hash(unsigned char *data, int len)
  2985. {
  2986. return _Py_HashBytes(data, len);
  2987. }
  2988. static PyObject *date_getstate(PyDateTime_Date *self);
  2989. static Py_hash_t
  2990. date_hash(PyDateTime_Date *self)
  2991. {
  2992. if (self->hashcode == -1) {
  2993. self->hashcode = generic_hash(
  2994. (unsigned char *)self->data, _PyDateTime_DATE_DATASIZE);
  2995. }
  2996. return self->hashcode;
  2997. }
  2998. static PyObject *
  2999. date_toordinal(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
  3000. {
  3001. return PyLong_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
  3002. GET_DAY(self)));
  3003. }
  3004. static PyObject *
  3005. date_weekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
  3006. {
  3007. int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
  3008. return PyLong_FromLong(dow);
  3009. }
  3010. /* Pickle support, a simple use of __reduce__. */
  3011. /* __getstate__ isn't exposed */
  3012. static PyObject *
  3013. date_getstate(PyDateTime_Date *self)
  3014. {
  3015. PyObject* field;
  3016. field = PyBytes_FromStringAndSize((char*)self->data,
  3017. _PyDateTime_DATE_DATASIZE);
  3018. return Py_BuildValue("(N)", field);
  3019. }
  3020. static PyObject *
  3021. date_reduce(PyDateTime_Date *self, PyObject *arg)
  3022. {
  3023. return Py_BuildValue("(ON)", Py_TYPE(self), date_getstate(self));
  3024. }
  3025. static PyMethodDef date_methods[] = {
  3026. /* Class methods: */
  3027. DATETIME_DATE_FROMTIMESTAMP_METHODDEF
  3028. {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
  3029. METH_CLASS,
  3030. PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
  3031. "ordinal.")},
  3032. {"fromisoformat", (PyCFunction)date_fromisoformat, METH_O |
  3033. METH_CLASS,
  3034. PyDoc_STR("str -> Construct a date from the output of date.isoformat()")},
  3035. {"fromisocalendar", (PyCFunction)(void(*)(void))date_fromisocalendar,
  3036. METH_VARARGS | METH_KEYWORDS | METH_CLASS,
  3037. PyDoc_STR("int, int, int -> Construct a date from the ISO year, week "
  3038. "number and weekday.\n\n"
  3039. "This is the inverse of the date.isocalendar() function")},
  3040. {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
  3041. PyDoc_STR("Current date or datetime: same as "
  3042. "self.__class__.fromtimestamp(time.time()).")},
  3043. /* Instance methods: */
  3044. {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
  3045. PyDoc_STR("Return ctime() style string.")},
  3046. {"strftime", (PyCFunction)(void(*)(void))date_strftime, METH_VARARGS | METH_KEYWORDS,
  3047. PyDoc_STR("format -> strftime() style string.")},
  3048. {"__format__", (PyCFunction)date_format, METH_VARARGS,
  3049. PyDoc_STR("Formats self with strftime.")},
  3050. {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
  3051. PyDoc_STR("Return time tuple, compatible with time.localtime().")},
  3052. {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
  3053. PyDoc_STR("Return a named tuple containing ISO year, week number, and "
  3054. "weekday.")},
  3055. {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
  3056. PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
  3057. {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
  3058. PyDoc_STR("Return the day of the week represented by the date.\n"
  3059. "Monday == 1 ... Sunday == 7")},
  3060. {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
  3061. PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
  3062. "1 is day 1.")},
  3063. {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
  3064. PyDoc_STR("Return the day of the week represented by the date.\n"
  3065. "Monday == 0 ... Sunday == 6")},
  3066. {"replace", (PyCFunction)(void(*)(void))date_replace, METH_VARARGS | METH_KEYWORDS,
  3067. PyDoc_STR("Return date with new specified fields.")},
  3068. {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS,
  3069. PyDoc_STR("__reduce__() -> (cls, state)")},
  3070. {NULL, NULL}
  3071. };
  3072. static const char date_doc[] =
  3073. PyDoc_STR("date(year, month, day) --> date object");
  3074. static PyNumberMethods date_as_number = {
  3075. date_add, /* nb_add */
  3076. date_subtract, /* nb_subtract */
  3077. 0, /* nb_multiply */
  3078. 0, /* nb_remainder */
  3079. 0, /* nb_divmod */
  3080. 0, /* nb_power */
  3081. 0, /* nb_negative */
  3082. 0, /* nb_positive */
  3083. 0, /* nb_absolute */
  3084. 0, /* nb_bool */
  3085. };
  3086. static PyTypeObject PyDateTime_DateType = {
  3087. PyVarObject_HEAD_INIT(NULL, 0)
  3088. "datetime.date", /* tp_name */
  3089. sizeof(PyDateTime_Date), /* tp_basicsize */
  3090. 0, /* tp_itemsize */
  3091. 0, /* tp_dealloc */
  3092. 0, /* tp_vectorcall_offset */
  3093. 0, /* tp_getattr */
  3094. 0, /* tp_setattr */
  3095. 0, /* tp_as_async */
  3096. (reprfunc)date_repr, /* tp_repr */
  3097. &date_as_number, /* tp_as_number */
  3098. 0, /* tp_as_sequence */
  3099. 0, /* tp_as_mapping */
  3100. (hashfunc)date_hash, /* tp_hash */
  3101. 0, /* tp_call */
  3102. (reprfunc)date_str, /* tp_str */
  3103. PyObject_GenericGetAttr, /* tp_getattro */
  3104. 0, /* tp_setattro */
  3105. 0, /* tp_as_buffer */
  3106. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  3107. date_doc, /* tp_doc */
  3108. 0, /* tp_traverse */
  3109. 0, /* tp_clear */
  3110. date_richcompare, /* tp_richcompare */
  3111. 0, /* tp_weaklistoffset */
  3112. 0, /* tp_iter */
  3113. 0, /* tp_iternext */
  3114. date_methods, /* tp_methods */
  3115. 0, /* tp_members */
  3116. date_getset, /* tp_getset */
  3117. 0, /* tp_base */
  3118. 0, /* tp_dict */
  3119. 0, /* tp_descr_get */
  3120. 0, /* tp_descr_set */
  3121. 0, /* tp_dictoffset */
  3122. 0, /* tp_init */
  3123. 0, /* tp_alloc */
  3124. date_new, /* tp_new */
  3125. 0, /* tp_free */
  3126. };
  3127. /*
  3128. * PyDateTime_TZInfo implementation.
  3129. */
  3130. /* This is a pure abstract base class, so doesn't do anything beyond
  3131. * raising NotImplemented exceptions. Real tzinfo classes need
  3132. * to derive from this. This is mostly for clarity, and for efficiency in
  3133. * datetime and time constructors (their tzinfo arguments need to
  3134. * be subclasses of this tzinfo class, which is easy and quick to check).
  3135. *
  3136. * Note: For reasons having to do with pickling of subclasses, we have
  3137. * to allow tzinfo objects to be instantiated. This wasn't an issue
  3138. * in the Python implementation (__init__() could raise NotImplementedError
  3139. * there without ill effect), but doing so in the C implementation hit a
  3140. * brick wall.
  3141. */
  3142. static PyObject *
  3143. tzinfo_nogo(const char* methodname)
  3144. {
  3145. PyErr_Format(PyExc_NotImplementedError,
  3146. "a tzinfo subclass must implement %s()",
  3147. methodname);
  3148. return NULL;
  3149. }
  3150. /* Methods. A subclass must implement these. */
  3151. static PyObject *
  3152. tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
  3153. {
  3154. return tzinfo_nogo("tzname");
  3155. }
  3156. static PyObject *
  3157. tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
  3158. {
  3159. return tzinfo_nogo("utcoffset");
  3160. }
  3161. static PyObject *
  3162. tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
  3163. {
  3164. return tzinfo_nogo("dst");
  3165. }
  3166. static PyObject *add_datetime_timedelta(PyDateTime_DateTime *date,
  3167. PyDateTime_Delta *delta,
  3168. int factor);
  3169. static PyObject *datetime_utcoffset(PyObject *self, PyObject *);
  3170. static PyObject *datetime_dst(PyObject *self, PyObject *);
  3171. static PyObject *
  3172. tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt)
  3173. {
  3174. PyObject *result = NULL;
  3175. PyObject *off = NULL, *dst = NULL;
  3176. PyDateTime_Delta *delta = NULL;
  3177. if (!PyDateTime_Check(dt)) {
  3178. PyErr_SetString(PyExc_TypeError,
  3179. "fromutc: argument must be a datetime");
  3180. return NULL;
  3181. }
  3182. if (GET_DT_TZINFO(dt) != (PyObject *)self) {
  3183. PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
  3184. "is not self");
  3185. return NULL;
  3186. }
  3187. off = datetime_utcoffset(dt, NULL);
  3188. if (off == NULL)
  3189. return NULL;
  3190. if (off == Py_None) {
  3191. PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
  3192. "utcoffset() result required");
  3193. goto Fail;
  3194. }
  3195. dst = datetime_dst(dt, NULL);
  3196. if (dst == NULL)
  3197. goto Fail;
  3198. if (dst == Py_None) {
  3199. PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
  3200. "dst() result required");
  3201. goto Fail;
  3202. }
  3203. delta = (PyDateTime_Delta *)delta_subtract(off, dst);
  3204. if (delta == NULL)
  3205. goto Fail;
  3206. result = add_datetime_timedelta((PyDateTime_DateTime *)dt, delta, 1);
  3207. if (result == NULL)
  3208. goto Fail;
  3209. Py_DECREF(dst);
  3210. dst = call_dst(GET_DT_TZINFO(dt), result);
  3211. if (dst == NULL)
  3212. goto Fail;
  3213. if (dst == Py_None)
  3214. goto Inconsistent;
  3215. if (delta_bool((PyDateTime_Delta *)dst) != 0) {
  3216. Py_SETREF(result, add_datetime_timedelta((PyDateTime_DateTime *)result,
  3217. (PyDateTime_Delta *)dst, 1));
  3218. if (result == NULL)
  3219. goto Fail;
  3220. }
  3221. Py_DECREF(delta);
  3222. Py_DECREF(dst);
  3223. Py_DECREF(off);
  3224. return result;
  3225. Inconsistent:
  3226. PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave "
  3227. "inconsistent results; cannot convert");
  3228. /* fall through to failure */
  3229. Fail:
  3230. Py_XDECREF(off);
  3231. Py_XDECREF(dst);
  3232. Py_XDECREF(delta);
  3233. Py_XDECREF(result);
  3234. return NULL;
  3235. }
  3236. /*
  3237. * Pickle support. This is solely so that tzinfo subclasses can use
  3238. * pickling -- tzinfo itself is supposed to be uninstantiable.
  3239. */
  3240. static PyObject *
  3241. tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
  3242. {
  3243. PyObject *args, *state;
  3244. PyObject *getinitargs, *getstate;
  3245. _Py_IDENTIFIER(__getinitargs__);
  3246. _Py_IDENTIFIER(__getstate__);
  3247. if (_PyObject_LookupAttrId(self, &PyId___getinitargs__, &getinitargs) < 0) {
  3248. return NULL;
  3249. }
  3250. if (getinitargs != NULL) {
  3251. args = PyObject_CallNoArgs(getinitargs);
  3252. Py_DECREF(getinitargs);
  3253. }
  3254. else {
  3255. args = PyTuple_New(0);
  3256. }
  3257. if (args == NULL) {
  3258. return NULL;
  3259. }
  3260. if (_PyObject_LookupAttrId(self, &PyId___getstate__, &getstate) < 0) {
  3261. Py_DECREF(args);
  3262. return NULL;
  3263. }
  3264. if (getstate != NULL) {
  3265. state = PyObject_CallNoArgs(getstate);
  3266. Py_DECREF(getstate);
  3267. if (state == NULL) {
  3268. Py_DECREF(args);
  3269. return NULL;
  3270. }
  3271. }
  3272. else {
  3273. PyObject **dictptr;
  3274. state = Py_None;
  3275. dictptr = _PyObject_GetDictPtr(self);
  3276. if (dictptr && *dictptr && PyDict_GET_SIZE(*dictptr)) {
  3277. state = *dictptr;
  3278. }
  3279. Py_INCREF(state);
  3280. }
  3281. if (state == Py_None) {
  3282. Py_DECREF(state);
  3283. return Py_BuildValue("(ON)", Py_TYPE(self), args);
  3284. }
  3285. else
  3286. return Py_BuildValue("(ONN)", Py_TYPE(self), args, state);
  3287. }
  3288. static PyMethodDef tzinfo_methods[] = {
  3289. {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
  3290. PyDoc_STR("datetime -> string name of time zone.")},
  3291. {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
  3292. PyDoc_STR("datetime -> timedelta showing offset from UTC, negative "
  3293. "values indicating West of UTC")},
  3294. {"dst", (PyCFunction)tzinfo_dst, METH_O,
  3295. PyDoc_STR("datetime -> DST offset as timedelta positive east of UTC.")},
  3296. {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O,
  3297. PyDoc_STR("datetime in UTC -> datetime in local time.")},
  3298. {"__reduce__", tzinfo_reduce, METH_NOARGS,
  3299. PyDoc_STR("-> (cls, state)")},
  3300. {NULL, NULL}
  3301. };
  3302. static const char tzinfo_doc[] =
  3303. PyDoc_STR("Abstract base class for time zone info objects.");
  3304. static PyTypeObject PyDateTime_TZInfoType = {
  3305. PyVarObject_HEAD_INIT(NULL, 0)
  3306. "datetime.tzinfo", /* tp_name */
  3307. sizeof(PyDateTime_TZInfo), /* tp_basicsize */
  3308. 0, /* tp_itemsize */
  3309. 0, /* tp_dealloc */
  3310. 0, /* tp_vectorcall_offset */
  3311. 0, /* tp_getattr */
  3312. 0, /* tp_setattr */
  3313. 0, /* tp_as_async */
  3314. 0, /* tp_repr */
  3315. 0, /* tp_as_number */
  3316. 0, /* tp_as_sequence */
  3317. 0, /* tp_as_mapping */
  3318. 0, /* tp_hash */
  3319. 0, /* tp_call */
  3320. 0, /* tp_str */
  3321. PyObject_GenericGetAttr, /* tp_getattro */
  3322. 0, /* tp_setattro */
  3323. 0, /* tp_as_buffer */
  3324. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  3325. tzinfo_doc, /* tp_doc */
  3326. 0, /* tp_traverse */
  3327. 0, /* tp_clear */
  3328. 0, /* tp_richcompare */
  3329. 0, /* tp_weaklistoffset */
  3330. 0, /* tp_iter */
  3331. 0, /* tp_iternext */
  3332. tzinfo_methods, /* tp_methods */
  3333. 0, /* tp_members */
  3334. 0, /* tp_getset */
  3335. 0, /* tp_base */
  3336. 0, /* tp_dict */
  3337. 0, /* tp_descr_get */
  3338. 0, /* tp_descr_set */
  3339. 0, /* tp_dictoffset */
  3340. 0, /* tp_init */
  3341. 0, /* tp_alloc */
  3342. PyType_GenericNew, /* tp_new */
  3343. 0, /* tp_free */
  3344. };
  3345. static char *timezone_kws[] = {"offset", "name", NULL};
  3346. static PyObject *
  3347. timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw)
  3348. {
  3349. PyObject *offset;
  3350. PyObject *name = NULL;
  3351. if (PyArg_ParseTupleAndKeywords(args, kw, "O!|U:timezone", timezone_kws,
  3352. &PyDateTime_DeltaType, &offset, &name))
  3353. return new_timezone(offset, name);
  3354. return NULL;
  3355. }
  3356. static void
  3357. timezone_dealloc(PyDateTime_TimeZone *self)
  3358. {
  3359. Py_CLEAR(self->offset);
  3360. Py_CLEAR(self->name);
  3361. Py_TYPE(self)->tp_free((PyObject *)self);
  3362. }
  3363. static PyObject *
  3364. timezone_richcompare(PyDateTime_TimeZone *self,
  3365. PyDateTime_TimeZone *other, int op)
  3366. {
  3367. if (op != Py_EQ && op != Py_NE)
  3368. Py_RETURN_NOTIMPLEMENTED;
  3369. if (!PyTimezone_Check(other)) {
  3370. Py_RETURN_NOTIMPLEMENTED;
  3371. }
  3372. return delta_richcompare(self->offset, other->offset, op);
  3373. }
  3374. static Py_hash_t
  3375. timezone_hash(PyDateTime_TimeZone *self)
  3376. {
  3377. return delta_hash((PyDateTime_Delta *)self->offset);
  3378. }
  3379. /* Check argument type passed to tzname, utcoffset, or dst methods.
  3380. Returns 0 for good argument. Returns -1 and sets exception info
  3381. otherwise.
  3382. */
  3383. static int
  3384. _timezone_check_argument(PyObject *dt, const char *meth)
  3385. {
  3386. if (dt == Py_None || PyDateTime_Check(dt))
  3387. return 0;
  3388. PyErr_Format(PyExc_TypeError, "%s(dt) argument must be a datetime instance"
  3389. " or None, not %.200s", meth, Py_TYPE(dt)->tp_name);
  3390. return -1;
  3391. }
  3392. static PyObject *
  3393. timezone_repr(PyDateTime_TimeZone *self)
  3394. {
  3395. /* Note that although timezone is not subclassable, it is convenient
  3396. to use Py_TYPE(self)->tp_name here. */
  3397. const char *type_name = Py_TYPE(self)->tp_name;
  3398. if (((PyObject *)self) == PyDateTime_TimeZone_UTC)
  3399. return PyUnicode_FromFormat("%s.utc", type_name);
  3400. if (self->name == NULL)
  3401. return PyUnicode_FromFormat("%s(%R)", type_name, self->offset);
  3402. return PyUnicode_FromFormat("%s(%R, %R)", type_name, self->offset,
  3403. self->name);
  3404. }
  3405. static PyObject *
  3406. timezone_str(PyDateTime_TimeZone *self)
  3407. {
  3408. int hours, minutes, seconds, microseconds;
  3409. PyObject *offset;
  3410. char sign;
  3411. if (self->name != NULL) {
  3412. Py_INCREF(self->name);
  3413. return self->name;
  3414. }
  3415. if ((PyObject *)self == PyDateTime_TimeZone_UTC ||
  3416. (GET_TD_DAYS(self->offset) == 0 &&
  3417. GET_TD_SECONDS(self->offset) == 0 &&
  3418. GET_TD_MICROSECONDS(self->offset) == 0))
  3419. return PyUnicode_FromString("UTC");
  3420. /* Offset is normalized, so it is negative if days < 0 */
  3421. if (GET_TD_DAYS(self->offset) < 0) {
  3422. sign = '-';
  3423. offset = delta_negative((PyDateTime_Delta *)self->offset);
  3424. if (offset == NULL)
  3425. return NULL;
  3426. }
  3427. else {
  3428. sign = '+';
  3429. offset = self->offset;
  3430. Py_INCREF(offset);
  3431. }
  3432. /* Offset is not negative here. */
  3433. microseconds = GET_TD_MICROSECONDS(offset);
  3434. seconds = GET_TD_SECONDS(offset);
  3435. Py_DECREF(offset);
  3436. minutes = divmod(seconds, 60, &seconds);
  3437. hours = divmod(minutes, 60, &minutes);
  3438. if (microseconds != 0) {
  3439. return PyUnicode_FromFormat("UTC%c%02d:%02d:%02d.%06d",
  3440. sign, hours, minutes,
  3441. seconds, microseconds);
  3442. }
  3443. if (seconds != 0) {
  3444. return PyUnicode_FromFormat("UTC%c%02d:%02d:%02d",
  3445. sign, hours, minutes, seconds);
  3446. }
  3447. return PyUnicode_FromFormat("UTC%c%02d:%02d", sign, hours, minutes);
  3448. }
  3449. static PyObject *
  3450. timezone_tzname(PyDateTime_TimeZone *self, PyObject *dt)
  3451. {
  3452. if (_timezone_check_argument(dt, "tzname") == -1)
  3453. return NULL;
  3454. return timezone_str(self);
  3455. }
  3456. static PyObject *
  3457. timezone_utcoffset(PyDateTime_TimeZone *self, PyObject *dt)
  3458. {
  3459. if (_timezone_check_argument(dt, "utcoffset") == -1)
  3460. return NULL;
  3461. Py_INCREF(self->offset);
  3462. return self->offset;
  3463. }
  3464. static PyObject *
  3465. timezone_dst(PyObject *self, PyObject *dt)
  3466. {
  3467. if (_timezone_check_argument(dt, "dst") == -1)
  3468. return NULL;
  3469. Py_RETURN_NONE;
  3470. }
  3471. static PyObject *
  3472. timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt)
  3473. {
  3474. if (!PyDateTime_Check(dt)) {
  3475. PyErr_SetString(PyExc_TypeError,
  3476. "fromutc: argument must be a datetime");
  3477. return NULL;
  3478. }
  3479. if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) {
  3480. PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
  3481. "is not self");
  3482. return NULL;
  3483. }
  3484. return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1);
  3485. }
  3486. static PyObject *
  3487. timezone_getinitargs(PyDateTime_TimeZone *self, PyObject *Py_UNUSED(ignored))
  3488. {
  3489. if (self->name == NULL)
  3490. return Py_BuildValue("(O)", self->offset);
  3491. return Py_BuildValue("(OO)", self->offset, self->name);
  3492. }
  3493. static PyMethodDef timezone_methods[] = {
  3494. {"tzname", (PyCFunction)timezone_tzname, METH_O,
  3495. PyDoc_STR("If name is specified when timezone is created, returns the name."
  3496. " Otherwise returns offset as 'UTC(+|-)HH:MM'.")},
  3497. {"utcoffset", (PyCFunction)timezone_utcoffset, METH_O,
  3498. PyDoc_STR("Return fixed offset.")},
  3499. {"dst", (PyCFunction)timezone_dst, METH_O,
  3500. PyDoc_STR("Return None.")},
  3501. {"fromutc", (PyCFunction)timezone_fromutc, METH_O,
  3502. PyDoc_STR("datetime in UTC -> datetime in local time.")},
  3503. {"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS,
  3504. PyDoc_STR("pickle support")},
  3505. {NULL, NULL}
  3506. };
  3507. static const char timezone_doc[] =
  3508. PyDoc_STR("Fixed offset from UTC implementation of tzinfo.");
  3509. static PyTypeObject PyDateTime_TimeZoneType = {
  3510. PyVarObject_HEAD_INIT(NULL, 0)
  3511. "datetime.timezone", /* tp_name */
  3512. sizeof(PyDateTime_TimeZone), /* tp_basicsize */
  3513. 0, /* tp_itemsize */
  3514. (destructor)timezone_dealloc, /* tp_dealloc */
  3515. 0, /* tp_vectorcall_offset */
  3516. 0, /* tp_getattr */
  3517. 0, /* tp_setattr */
  3518. 0, /* tp_as_async */
  3519. (reprfunc)timezone_repr, /* tp_repr */
  3520. 0, /* tp_as_number */
  3521. 0, /* tp_as_sequence */
  3522. 0, /* tp_as_mapping */
  3523. (hashfunc)timezone_hash, /* tp_hash */
  3524. 0, /* tp_call */
  3525. (reprfunc)timezone_str, /* tp_str */
  3526. 0, /* tp_getattro */
  3527. 0, /* tp_setattro */
  3528. 0, /* tp_as_buffer */
  3529. Py_TPFLAGS_DEFAULT, /* tp_flags */
  3530. timezone_doc, /* tp_doc */
  3531. 0, /* tp_traverse */
  3532. 0, /* tp_clear */
  3533. (richcmpfunc)timezone_richcompare,/* tp_richcompare */
  3534. 0, /* tp_weaklistoffset */
  3535. 0, /* tp_iter */
  3536. 0, /* tp_iternext */
  3537. timezone_methods, /* tp_methods */
  3538. 0, /* tp_members */
  3539. 0, /* tp_getset */
  3540. 0, /* tp_base; filled in PyInit__datetime */
  3541. 0, /* tp_dict */
  3542. 0, /* tp_descr_get */
  3543. 0, /* tp_descr_set */
  3544. 0, /* tp_dictoffset */
  3545. 0, /* tp_init */
  3546. 0, /* tp_alloc */
  3547. timezone_new, /* tp_new */
  3548. };
  3549. /*
  3550. * PyDateTime_Time implementation.
  3551. */
  3552. /* Accessor properties.
  3553. */
  3554. static PyObject *
  3555. time_hour(PyDateTime_Time *self, void *unused)
  3556. {
  3557. return PyLong_FromLong(TIME_GET_HOUR(self));
  3558. }
  3559. static PyObject *
  3560. time_minute(PyDateTime_Time *self, void *unused)
  3561. {
  3562. return PyLong_FromLong(TIME_GET_MINUTE(self));
  3563. }
  3564. /* The name time_second conflicted with some platform header file. */
  3565. static PyObject *
  3566. py_time_second(PyDateTime_Time *self, void *unused)
  3567. {
  3568. return PyLong_FromLong(TIME_GET_SECOND(self));
  3569. }
  3570. static PyObject *
  3571. time_microsecond(PyDateTime_Time *self, void *unused)
  3572. {
  3573. return PyLong_FromLong(TIME_GET_MICROSECOND(self));
  3574. }
  3575. static PyObject *
  3576. time_tzinfo(PyDateTime_Time *self, void *unused)
  3577. {
  3578. PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
  3579. Py_INCREF(result);
  3580. return result;
  3581. }
  3582. static PyObject *
  3583. time_fold(PyDateTime_Time *self, void *unused)
  3584. {
  3585. return PyLong_FromLong(TIME_GET_FOLD(self));
  3586. }
  3587. static PyGetSetDef time_getset[] = {
  3588. {"hour", (getter)time_hour},
  3589. {"minute", (getter)time_minute},
  3590. {"second", (getter)py_time_second},
  3591. {"microsecond", (getter)time_microsecond},
  3592. {"tzinfo", (getter)time_tzinfo},
  3593. {"fold", (getter)time_fold},
  3594. {NULL}
  3595. };
  3596. /*
  3597. * Constructors.
  3598. */
  3599. static char *time_kws[] = {"hour", "minute", "second", "microsecond",
  3600. "tzinfo", "fold", NULL};
  3601. static PyObject *
  3602. time_from_pickle(PyTypeObject *type, PyObject *state, PyObject *tzinfo)
  3603. {
  3604. PyDateTime_Time *me;
  3605. char aware = (char)(tzinfo != Py_None);
  3606. if (aware && check_tzinfo_subclass(tzinfo) < 0) {
  3607. PyErr_SetString(PyExc_TypeError, "bad tzinfo state arg");
  3608. return NULL;
  3609. }
  3610. me = (PyDateTime_Time *) (type->tp_alloc(type, aware));
  3611. if (me != NULL) {
  3612. const char *pdata = PyBytes_AS_STRING(state);
  3613. memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE);
  3614. me->hashcode = -1;
  3615. me->hastzinfo = aware;
  3616. if (aware) {
  3617. Py_INCREF(tzinfo);
  3618. me->tzinfo = tzinfo;
  3619. }
  3620. if (pdata[0] & (1 << 7)) {
  3621. me->data[0] -= 128;
  3622. me->fold = 1;
  3623. }
  3624. else {
  3625. me->fold = 0;
  3626. }
  3627. }
  3628. return (PyObject *)me;
  3629. }
  3630. static PyObject *
  3631. time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
  3632. {
  3633. PyObject *self = NULL;
  3634. int hour = 0;
  3635. int minute = 0;
  3636. int second = 0;
  3637. int usecond = 0;
  3638. PyObject *tzinfo = Py_None;
  3639. int fold = 0;
  3640. /* Check for invocation from pickle with __getstate__ state */
  3641. if (PyTuple_GET_SIZE(args) >= 1 && PyTuple_GET_SIZE(args) <= 2) {
  3642. PyObject *state = PyTuple_GET_ITEM(args, 0);
  3643. if (PyTuple_GET_SIZE(args) == 2) {
  3644. tzinfo = PyTuple_GET_ITEM(args, 1);
  3645. }
  3646. if (PyBytes_Check(state)) {
  3647. if (PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE &&
  3648. (0x7F & ((unsigned char) (PyBytes_AS_STRING(state)[0]))) < 24)
  3649. {
  3650. return time_from_pickle(type, state, tzinfo);
  3651. }
  3652. }
  3653. else if (PyUnicode_Check(state)) {
  3654. if (PyUnicode_READY(state)) {
  3655. return NULL;
  3656. }
  3657. if (PyUnicode_GET_LENGTH(state) == _PyDateTime_TIME_DATASIZE &&
  3658. (0x7F & PyUnicode_READ_CHAR(state, 0)) < 24)
  3659. {
  3660. state = PyUnicode_AsLatin1String(state);
  3661. if (state == NULL) {
  3662. if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
  3663. /* More informative error message. */
  3664. PyErr_SetString(PyExc_ValueError,
  3665. "Failed to encode latin1 string when unpickling "
  3666. "a time object. "
  3667. "pickle.load(data, encoding='latin1') is assumed.");
  3668. }
  3669. return NULL;
  3670. }
  3671. self = time_from_pickle(type, state, tzinfo);
  3672. Py_DECREF(state);
  3673. return self;
  3674. }
  3675. }
  3676. tzinfo = Py_None;
  3677. }
  3678. if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i", time_kws,
  3679. &hour, &minute, &second, &usecond,
  3680. &tzinfo, &fold)) {
  3681. self = new_time_ex2(hour, minute, second, usecond, tzinfo, fold,
  3682. type);
  3683. }
  3684. return self;
  3685. }
  3686. /*
  3687. * Destructor.
  3688. */
  3689. static void
  3690. time_dealloc(PyDateTime_Time *self)
  3691. {
  3692. if (HASTZINFO(self)) {
  3693. Py_XDECREF(self->tzinfo);
  3694. }
  3695. Py_TYPE(self)->tp_free((PyObject *)self);
  3696. }
  3697. /*
  3698. * Indirect access to tzinfo methods.
  3699. */
  3700. /* These are all METH_NOARGS, so don't need to check the arglist. */
  3701. static PyObject *
  3702. time_utcoffset(PyObject *self, PyObject *unused) {
  3703. return call_utcoffset(GET_TIME_TZINFO(self), Py_None);
  3704. }
  3705. static PyObject *
  3706. time_dst(PyObject *self, PyObject *unused) {
  3707. return call_dst(GET_TIME_TZINFO(self), Py_None);
  3708. }
  3709. static PyObject *
  3710. time_tzname(PyDateTime_Time *self, PyObject *unused) {
  3711. return call_tzname(GET_TIME_TZINFO(self), Py_None);
  3712. }
  3713. /*
  3714. * Various ways to turn a time into a string.
  3715. */
  3716. static PyObject *
  3717. time_repr(PyDateTime_Time *self)
  3718. {
  3719. const char *type_name = Py_TYPE(self)->tp_name;
  3720. int h = TIME_GET_HOUR(self);
  3721. int m = TIME_GET_MINUTE(self);
  3722. int s = TIME_GET_SECOND(self);
  3723. int us = TIME_GET_MICROSECOND(self);
  3724. int fold = TIME_GET_FOLD(self);
  3725. PyObject *result = NULL;
  3726. if (us)
  3727. result = PyUnicode_FromFormat("%s(%d, %d, %d, %d)",
  3728. type_name, h, m, s, us);
  3729. else if (s)
  3730. result = PyUnicode_FromFormat("%s(%d, %d, %d)",
  3731. type_name, h, m, s);
  3732. else
  3733. result = PyUnicode_FromFormat("%s(%d, %d)", type_name, h, m);
  3734. if (result != NULL && HASTZINFO(self))
  3735. result = append_keyword_tzinfo(result, self->tzinfo);
  3736. if (result != NULL && fold)
  3737. result = append_keyword_fold(result, fold);
  3738. return result;
  3739. }
  3740. static PyObject *
  3741. time_str(PyDateTime_Time *self)
  3742. {
  3743. return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
  3744. }
  3745. static PyObject *
  3746. time_isoformat(PyDateTime_Time *self, PyObject *args, PyObject *kw)
  3747. {
  3748. char buf[100];
  3749. const char *timespec = NULL;
  3750. static char *keywords[] = {"timespec", NULL};
  3751. PyObject *result;
  3752. int us = TIME_GET_MICROSECOND(self);
  3753. static const char *specs[][2] = {
  3754. {"hours", "%02d"},
  3755. {"minutes", "%02d:%02d"},
  3756. {"seconds", "%02d:%02d:%02d"},
  3757. {"milliseconds", "%02d:%02d:%02d.%03d"},
  3758. {"microseconds", "%02d:%02d:%02d.%06d"},
  3759. };
  3760. size_t given_spec;
  3761. if (!PyArg_ParseTupleAndKeywords(args, kw, "|s:isoformat", keywords, &timespec))
  3762. return NULL;
  3763. if (timespec == NULL || strcmp(timespec, "auto") == 0) {
  3764. if (us == 0) {
  3765. /* seconds */
  3766. given_spec = 2;
  3767. }
  3768. else {
  3769. /* microseconds */
  3770. given_spec = 4;
  3771. }
  3772. }
  3773. else {
  3774. for (given_spec = 0; given_spec < Py_ARRAY_LENGTH(specs); given_spec++) {
  3775. if (strcmp(timespec, specs[given_spec][0]) == 0) {
  3776. if (given_spec == 3) {
  3777. /* milliseconds */
  3778. us = us / 1000;
  3779. }
  3780. break;
  3781. }
  3782. }
  3783. }
  3784. if (given_spec == Py_ARRAY_LENGTH(specs)) {
  3785. PyErr_Format(PyExc_ValueError, "Unknown timespec value");
  3786. return NULL;
  3787. }
  3788. else {
  3789. result = PyUnicode_FromFormat(specs[given_spec][1],
  3790. TIME_GET_HOUR(self), TIME_GET_MINUTE(self),
  3791. TIME_GET_SECOND(self), us);
  3792. }
  3793. if (result == NULL || !HASTZINFO(self) || self->tzinfo == Py_None)
  3794. return result;
  3795. /* We need to append the UTC offset. */
  3796. if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
  3797. Py_None) < 0) {
  3798. Py_DECREF(result);
  3799. return NULL;
  3800. }
  3801. PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buf));
  3802. return result;
  3803. }
  3804. static PyObject *
  3805. time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
  3806. {
  3807. PyObject *result;
  3808. PyObject *tuple;
  3809. PyObject *format;
  3810. static char *keywords[] = {"format", NULL};
  3811. if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords,
  3812. &format))
  3813. return NULL;
  3814. /* Python's strftime does insane things with the year part of the
  3815. * timetuple. The year is forced to (the otherwise nonsensical)
  3816. * 1900 to work around that.
  3817. */
  3818. tuple = Py_BuildValue("iiiiiiiii",
  3819. 1900, 1, 1, /* year, month, day */
  3820. TIME_GET_HOUR(self),
  3821. TIME_GET_MINUTE(self),
  3822. TIME_GET_SECOND(self),
  3823. 0, 1, -1); /* weekday, daynum, dst */
  3824. if (tuple == NULL)
  3825. return NULL;
  3826. assert(PyTuple_Size(tuple) == 9);
  3827. result = wrap_strftime((PyObject *)self, format, tuple,
  3828. Py_None);
  3829. Py_DECREF(tuple);
  3830. return result;
  3831. }
  3832. /*
  3833. * Miscellaneous methods.
  3834. */
  3835. static PyObject *
  3836. time_richcompare(PyObject *self, PyObject *other, int op)
  3837. {
  3838. PyObject *result = NULL;
  3839. PyObject *offset1, *offset2;
  3840. int diff;
  3841. if (! PyTime_Check(other))
  3842. Py_RETURN_NOTIMPLEMENTED;
  3843. if (GET_TIME_TZINFO(self) == GET_TIME_TZINFO(other)) {
  3844. diff = memcmp(((PyDateTime_Time *)self)->data,
  3845. ((PyDateTime_Time *)other)->data,
  3846. _PyDateTime_TIME_DATASIZE);
  3847. return diff_to_bool(diff, op);
  3848. }
  3849. offset1 = time_utcoffset(self, NULL);
  3850. if (offset1 == NULL)
  3851. return NULL;
  3852. offset2 = time_utcoffset(other, NULL);
  3853. if (offset2 == NULL)
  3854. goto done;
  3855. /* If they're both naive, or both aware and have the same offsets,
  3856. * we get off cheap. Note that if they're both naive, offset1 ==
  3857. * offset2 == Py_None at this point.
  3858. */
  3859. if ((offset1 == offset2) ||
  3860. (PyDelta_Check(offset1) && PyDelta_Check(offset2) &&
  3861. delta_cmp(offset1, offset2) == 0)) {
  3862. diff = memcmp(((PyDateTime_Time *)self)->data,
  3863. ((PyDateTime_Time *)other)->data,
  3864. _PyDateTime_TIME_DATASIZE);
  3865. result = diff_to_bool(diff, op);
  3866. }
  3867. /* The hard case: both aware with different UTC offsets */
  3868. else if (offset1 != Py_None && offset2 != Py_None) {
  3869. int offsecs1, offsecs2;
  3870. assert(offset1 != offset2); /* else last "if" handled it */
  3871. offsecs1 = TIME_GET_HOUR(self) * 3600 +
  3872. TIME_GET_MINUTE(self) * 60 +
  3873. TIME_GET_SECOND(self) -
  3874. GET_TD_DAYS(offset1) * 86400 -
  3875. GET_TD_SECONDS(offset1);
  3876. offsecs2 = TIME_GET_HOUR(other) * 3600 +
  3877. TIME_GET_MINUTE(other) * 60 +
  3878. TIME_GET_SECOND(other) -
  3879. GET_TD_DAYS(offset2) * 86400 -
  3880. GET_TD_SECONDS(offset2);
  3881. diff = offsecs1 - offsecs2;
  3882. if (diff == 0)
  3883. diff = TIME_GET_MICROSECOND(self) -
  3884. TIME_GET_MICROSECOND(other);
  3885. result = diff_to_bool(diff, op);
  3886. }
  3887. else if (op == Py_EQ) {
  3888. result = Py_False;
  3889. Py_INCREF(result);
  3890. }
  3891. else if (op == Py_NE) {
  3892. result = Py_True;
  3893. Py_INCREF(result);
  3894. }
  3895. else {
  3896. PyErr_SetString(PyExc_TypeError,
  3897. "can't compare offset-naive and "
  3898. "offset-aware times");
  3899. }
  3900. done:
  3901. Py_DECREF(offset1);
  3902. Py_XDECREF(offset2);
  3903. return result;
  3904. }
  3905. static Py_hash_t
  3906. time_hash(PyDateTime_Time *self)
  3907. {
  3908. if (self->hashcode == -1) {
  3909. PyObject *offset, *self0;
  3910. if (TIME_GET_FOLD(self)) {
  3911. self0 = new_time_ex2(TIME_GET_HOUR(self),
  3912. TIME_GET_MINUTE(self),
  3913. TIME_GET_SECOND(self),
  3914. TIME_GET_MICROSECOND(self),
  3915. HASTZINFO(self) ? self->tzinfo : Py_None,
  3916. 0, Py_TYPE(self));
  3917. if (self0 == NULL)
  3918. return -1;
  3919. }
  3920. else {
  3921. self0 = (PyObject *)self;
  3922. Py_INCREF(self0);
  3923. }
  3924. offset = time_utcoffset(self0, NULL);
  3925. Py_DECREF(self0);
  3926. if (offset == NULL)
  3927. return -1;
  3928. /* Reduce this to a hash of another object. */
  3929. if (offset == Py_None)
  3930. self->hashcode = generic_hash(
  3931. (unsigned char *)self->data, _PyDateTime_TIME_DATASIZE);
  3932. else {
  3933. PyObject *temp1, *temp2;
  3934. int seconds, microseconds;
  3935. assert(HASTZINFO(self));
  3936. seconds = TIME_GET_HOUR(self) * 3600 +
  3937. TIME_GET_MINUTE(self) * 60 +
  3938. TIME_GET_SECOND(self);
  3939. microseconds = TIME_GET_MICROSECOND(self);
  3940. temp1 = new_delta(0, seconds, microseconds, 1);
  3941. if (temp1 == NULL) {
  3942. Py_DECREF(offset);
  3943. return -1;
  3944. }
  3945. temp2 = delta_subtract(temp1, offset);
  3946. Py_DECREF(temp1);
  3947. if (temp2 == NULL) {
  3948. Py_DECREF(offset);
  3949. return -1;
  3950. }
  3951. self->hashcode = PyObject_Hash(temp2);
  3952. Py_DECREF(temp2);
  3953. }
  3954. Py_DECREF(offset);
  3955. }
  3956. return self->hashcode;
  3957. }
  3958. static PyObject *
  3959. time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
  3960. {
  3961. PyObject *clone;
  3962. PyObject *tuple;
  3963. int hh = TIME_GET_HOUR(self);
  3964. int mm = TIME_GET_MINUTE(self);
  3965. int ss = TIME_GET_SECOND(self);
  3966. int us = TIME_GET_MICROSECOND(self);
  3967. PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
  3968. int fold = TIME_GET_FOLD(self);
  3969. if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i:replace",
  3970. time_kws,
  3971. &hh, &mm, &ss, &us, &tzinfo, &fold))
  3972. return NULL;
  3973. if (fold != 0 && fold != 1) {
  3974. PyErr_SetString(PyExc_ValueError,
  3975. "fold must be either 0 or 1");
  3976. return NULL;
  3977. }
  3978. tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
  3979. if (tuple == NULL)
  3980. return NULL;
  3981. clone = time_new(Py_TYPE(self), tuple, NULL);
  3982. if (clone != NULL) {
  3983. TIME_SET_FOLD(clone, fold);
  3984. }
  3985. Py_DECREF(tuple);
  3986. return clone;
  3987. }
  3988. static PyObject *
  3989. time_fromisoformat(PyObject *cls, PyObject *tstr) {
  3990. assert(tstr != NULL);
  3991. if (!PyUnicode_Check(tstr)) {
  3992. PyErr_SetString(PyExc_TypeError, "fromisoformat: argument must be str");
  3993. return NULL;
  3994. }
  3995. Py_ssize_t len;
  3996. const char *p = PyUnicode_AsUTF8AndSize(tstr, &len);
  3997. if (p == NULL) {
  3998. goto invalid_string_error;
  3999. }
  4000. int hour = 0, minute = 0, second = 0, microsecond = 0;
  4001. int tzoffset, tzimicrosecond = 0;
  4002. int rv = parse_isoformat_time(p, len,
  4003. &hour, &minute, &second, &microsecond,
  4004. &tzoffset, &tzimicrosecond);
  4005. if (rv < 0) {
  4006. goto invalid_string_error;
  4007. }
  4008. PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset,
  4009. tzimicrosecond);
  4010. if (tzinfo == NULL) {
  4011. return NULL;
  4012. }
  4013. PyObject *t;
  4014. if ( (PyTypeObject *)cls == &PyDateTime_TimeType ) {
  4015. t = new_time(hour, minute, second, microsecond, tzinfo, 0);
  4016. } else {
  4017. t = PyObject_CallFunction(cls, "iiiiO",
  4018. hour, minute, second, microsecond, tzinfo);
  4019. }
  4020. Py_DECREF(tzinfo);
  4021. return t;
  4022. invalid_string_error:
  4023. PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", tstr);
  4024. return NULL;
  4025. }
  4026. /* Pickle support, a simple use of __reduce__. */
  4027. /* Let basestate be the non-tzinfo data string.
  4028. * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
  4029. * So it's a tuple in any (non-error) case.
  4030. * __getstate__ isn't exposed.
  4031. */
  4032. static PyObject *
  4033. time_getstate(PyDateTime_Time *self, int proto)
  4034. {
  4035. PyObject *basestate;
  4036. PyObject *result = NULL;
  4037. basestate = PyBytes_FromStringAndSize((char *)self->data,
  4038. _PyDateTime_TIME_DATASIZE);
  4039. if (basestate != NULL) {
  4040. if (proto > 3 && TIME_GET_FOLD(self))
  4041. /* Set the first bit of the first byte */
  4042. PyBytes_AS_STRING(basestate)[0] |= (1 << 7);
  4043. if (! HASTZINFO(self) || self->tzinfo == Py_None)
  4044. result = PyTuple_Pack(1, basestate);
  4045. else
  4046. result = PyTuple_Pack(2, basestate, self->tzinfo);
  4047. Py_DECREF(basestate);
  4048. }
  4049. return result;
  4050. }
  4051. static PyObject *
  4052. time_reduce_ex(PyDateTime_Time *self, PyObject *args)
  4053. {
  4054. int proto;
  4055. if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto))
  4056. return NULL;
  4057. return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, proto));
  4058. }
  4059. static PyObject *
  4060. time_reduce(PyDateTime_Time *self, PyObject *arg)
  4061. {
  4062. return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, 2));
  4063. }
  4064. static PyMethodDef time_methods[] = {
  4065. {"isoformat", (PyCFunction)(void(*)(void))time_isoformat, METH_VARARGS | METH_KEYWORDS,
  4066. PyDoc_STR("Return string in ISO 8601 format, [HH[:MM[:SS[.mmm[uuu]]]]]"
  4067. "[+HH:MM].\n\n"
  4068. "The optional argument timespec specifies the number "
  4069. "of additional terms\nof the time to include. Valid "
  4070. "options are 'auto', 'hours', 'minutes',\n'seconds', "
  4071. "'milliseconds' and 'microseconds'.\n")},
  4072. {"strftime", (PyCFunction)(void(*)(void))time_strftime, METH_VARARGS | METH_KEYWORDS,
  4073. PyDoc_STR("format -> strftime() style string.")},
  4074. {"__format__", (PyCFunction)date_format, METH_VARARGS,
  4075. PyDoc_STR("Formats self with strftime.")},
  4076. {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS,
  4077. PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
  4078. {"tzname", (PyCFunction)time_tzname, METH_NOARGS,
  4079. PyDoc_STR("Return self.tzinfo.tzname(self).")},
  4080. {"dst", (PyCFunction)time_dst, METH_NOARGS,
  4081. PyDoc_STR("Return self.tzinfo.dst(self).")},
  4082. {"replace", (PyCFunction)(void(*)(void))time_replace, METH_VARARGS | METH_KEYWORDS,
  4083. PyDoc_STR("Return time with new specified fields.")},
  4084. {"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS,
  4085. PyDoc_STR("string -> time from time.isoformat() output")},
  4086. {"__reduce_ex__", (PyCFunction)time_reduce_ex, METH_VARARGS,
  4087. PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")},
  4088. {"__reduce__", (PyCFunction)time_reduce, METH_NOARGS,
  4089. PyDoc_STR("__reduce__() -> (cls, state)")},
  4090. {NULL, NULL}
  4091. };
  4092. static const char time_doc[] =
  4093. PyDoc_STR("time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a time object\n\
  4094. \n\
  4095. All arguments are optional. tzinfo may be None, or an instance of\n\
  4096. a tzinfo subclass. The remaining arguments may be ints.\n");
  4097. static PyTypeObject PyDateTime_TimeType = {
  4098. PyVarObject_HEAD_INIT(NULL, 0)
  4099. "datetime.time", /* tp_name */
  4100. sizeof(PyDateTime_Time), /* tp_basicsize */
  4101. 0, /* tp_itemsize */
  4102. (destructor)time_dealloc, /* tp_dealloc */
  4103. 0, /* tp_vectorcall_offset */
  4104. 0, /* tp_getattr */
  4105. 0, /* tp_setattr */
  4106. 0, /* tp_as_async */
  4107. (reprfunc)time_repr, /* tp_repr */
  4108. 0, /* tp_as_number */
  4109. 0, /* tp_as_sequence */
  4110. 0, /* tp_as_mapping */
  4111. (hashfunc)time_hash, /* tp_hash */
  4112. 0, /* tp_call */
  4113. (reprfunc)time_str, /* tp_str */
  4114. PyObject_GenericGetAttr, /* tp_getattro */
  4115. 0, /* tp_setattro */
  4116. 0, /* tp_as_buffer */
  4117. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  4118. time_doc, /* tp_doc */
  4119. 0, /* tp_traverse */
  4120. 0, /* tp_clear */
  4121. time_richcompare, /* tp_richcompare */
  4122. 0, /* tp_weaklistoffset */
  4123. 0, /* tp_iter */
  4124. 0, /* tp_iternext */
  4125. time_methods, /* tp_methods */
  4126. 0, /* tp_members */
  4127. time_getset, /* tp_getset */
  4128. 0, /* tp_base */
  4129. 0, /* tp_dict */
  4130. 0, /* tp_descr_get */
  4131. 0, /* tp_descr_set */
  4132. 0, /* tp_dictoffset */
  4133. 0, /* tp_init */
  4134. time_alloc, /* tp_alloc */
  4135. time_new, /* tp_new */
  4136. 0, /* tp_free */
  4137. };
  4138. /*
  4139. * PyDateTime_DateTime implementation.
  4140. */
  4141. /* Accessor properties. Properties for day, month, and year are inherited
  4142. * from date.
  4143. */
  4144. static PyObject *
  4145. datetime_hour(PyDateTime_DateTime *self, void *unused)
  4146. {
  4147. return PyLong_FromLong(DATE_GET_HOUR(self));
  4148. }
  4149. static PyObject *
  4150. datetime_minute(PyDateTime_DateTime *self, void *unused)
  4151. {
  4152. return PyLong_FromLong(DATE_GET_MINUTE(self));
  4153. }
  4154. static PyObject *
  4155. datetime_second(PyDateTime_DateTime *self, void *unused)
  4156. {
  4157. return PyLong_FromLong(DATE_GET_SECOND(self));
  4158. }
  4159. static PyObject *
  4160. datetime_microsecond(PyDateTime_DateTime *self, void *unused)
  4161. {
  4162. return PyLong_FromLong(DATE_GET_MICROSECOND(self));
  4163. }
  4164. static PyObject *
  4165. datetime_tzinfo(PyDateTime_DateTime *self, void *unused)
  4166. {
  4167. PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
  4168. Py_INCREF(result);
  4169. return result;
  4170. }
  4171. static PyObject *
  4172. datetime_fold(PyDateTime_DateTime *self, void *unused)
  4173. {
  4174. return PyLong_FromLong(DATE_GET_FOLD(self));
  4175. }
  4176. static PyGetSetDef datetime_getset[] = {
  4177. {"hour", (getter)datetime_hour},
  4178. {"minute", (getter)datetime_minute},
  4179. {"second", (getter)datetime_second},
  4180. {"microsecond", (getter)datetime_microsecond},
  4181. {"tzinfo", (getter)datetime_tzinfo},
  4182. {"fold", (getter)datetime_fold},
  4183. {NULL}
  4184. };
  4185. /*
  4186. * Constructors.
  4187. */
  4188. static char *datetime_kws[] = {
  4189. "year", "month", "day", "hour", "minute", "second",
  4190. "microsecond", "tzinfo", "fold", NULL
  4191. };
  4192. static PyObject *
  4193. datetime_from_pickle(PyTypeObject *type, PyObject *state, PyObject *tzinfo)
  4194. {
  4195. PyDateTime_DateTime *me;
  4196. char aware = (char)(tzinfo != Py_None);
  4197. if (aware && check_tzinfo_subclass(tzinfo) < 0) {
  4198. PyErr_SetString(PyExc_TypeError, "bad tzinfo state arg");
  4199. return NULL;
  4200. }
  4201. me = (PyDateTime_DateTime *) (type->tp_alloc(type , aware));
  4202. if (me != NULL) {
  4203. const char *pdata = PyBytes_AS_STRING(state);
  4204. memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE);
  4205. me->hashcode = -1;
  4206. me->hastzinfo = aware;
  4207. if (aware) {
  4208. Py_INCREF(tzinfo);
  4209. me->tzinfo = tzinfo;
  4210. }
  4211. if (pdata[2] & (1 << 7)) {
  4212. me->data[2] -= 128;
  4213. me->fold = 1;
  4214. }
  4215. else {
  4216. me->fold = 0;
  4217. }
  4218. }
  4219. return (PyObject *)me;
  4220. }
  4221. static PyObject *
  4222. datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
  4223. {
  4224. PyObject *self = NULL;
  4225. int year;
  4226. int month;
  4227. int day;
  4228. int hour = 0;
  4229. int minute = 0;
  4230. int second = 0;
  4231. int usecond = 0;
  4232. int fold = 0;
  4233. PyObject *tzinfo = Py_None;
  4234. /* Check for invocation from pickle with __getstate__ state */
  4235. if (PyTuple_GET_SIZE(args) >= 1 && PyTuple_GET_SIZE(args) <= 2) {
  4236. PyObject *state = PyTuple_GET_ITEM(args, 0);
  4237. if (PyTuple_GET_SIZE(args) == 2) {
  4238. tzinfo = PyTuple_GET_ITEM(args, 1);
  4239. }
  4240. if (PyBytes_Check(state)) {
  4241. if (PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE &&
  4242. MONTH_IS_SANE(PyBytes_AS_STRING(state)[2] & 0x7F))
  4243. {
  4244. return datetime_from_pickle(type, state, tzinfo);
  4245. }
  4246. }
  4247. else if (PyUnicode_Check(state)) {
  4248. if (PyUnicode_READY(state)) {
  4249. return NULL;
  4250. }
  4251. if (PyUnicode_GET_LENGTH(state) == _PyDateTime_DATETIME_DATASIZE &&
  4252. MONTH_IS_SANE(PyUnicode_READ_CHAR(state, 2) & 0x7F))
  4253. {
  4254. state = PyUnicode_AsLatin1String(state);
  4255. if (state == NULL) {
  4256. if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
  4257. /* More informative error message. */
  4258. PyErr_SetString(PyExc_ValueError,
  4259. "Failed to encode latin1 string when unpickling "
  4260. "a datetime object. "
  4261. "pickle.load(data, encoding='latin1') is assumed.");
  4262. }
  4263. return NULL;
  4264. }
  4265. self = datetime_from_pickle(type, state, tzinfo);
  4266. Py_DECREF(state);
  4267. return self;
  4268. }
  4269. }
  4270. tzinfo = Py_None;
  4271. }
  4272. if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO$i", datetime_kws,
  4273. &year, &month, &day, &hour, &minute,
  4274. &second, &usecond, &tzinfo, &fold)) {
  4275. self = new_datetime_ex2(year, month, day,
  4276. hour, minute, second, usecond,
  4277. tzinfo, fold, type);
  4278. }
  4279. return self;
  4280. }
  4281. /* TM_FUNC is the shared type of _PyTime_localtime() and
  4282. * _PyTime_gmtime(). */
  4283. typedef int (*TM_FUNC)(time_t timer, struct tm*);
  4284. /* As of version 2015f max fold in IANA database is
  4285. * 23 hours at 1969-09-30 13:00:00 in Kwajalein. */
  4286. static long long max_fold_seconds = 24 * 3600;
  4287. /* NB: date(1970,1,1).toordinal() == 719163 */
  4288. static long long epoch = 719163LL * 24 * 60 * 60;
  4289. static long long
  4290. utc_to_seconds(int year, int month, int day,
  4291. int hour, int minute, int second)
  4292. {
  4293. long long ordinal;
  4294. /* ymd_to_ord() doesn't support year <= 0 */
  4295. if (year < MINYEAR || year > MAXYEAR) {
  4296. PyErr_Format(PyExc_ValueError, "year %i is out of range", year);
  4297. return -1;
  4298. }
  4299. ordinal = ymd_to_ord(year, month, day);
  4300. return ((ordinal * 24 + hour) * 60 + minute) * 60 + second;
  4301. }
  4302. static long long
  4303. local(long long u)
  4304. {
  4305. struct tm local_time;
  4306. time_t t;
  4307. u -= epoch;
  4308. t = u;
  4309. if (t != u) {
  4310. PyErr_SetString(PyExc_OverflowError,
  4311. "timestamp out of range for platform time_t");
  4312. return -1;
  4313. }
  4314. if (_PyTime_localtime(t, &local_time) != 0)
  4315. return -1;
  4316. return utc_to_seconds(local_time.tm_year + 1900,
  4317. local_time.tm_mon + 1,
  4318. local_time.tm_mday,
  4319. local_time.tm_hour,
  4320. local_time.tm_min,
  4321. local_time.tm_sec);
  4322. }
  4323. /* Internal helper.
  4324. * Build datetime from a time_t and a distinct count of microseconds.
  4325. * Pass localtime or gmtime for f, to control the interpretation of timet.
  4326. */
  4327. static PyObject *
  4328. datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
  4329. PyObject *tzinfo)
  4330. {
  4331. struct tm tm;
  4332. int year, month, day, hour, minute, second, fold = 0;
  4333. if (f(timet, &tm) != 0)
  4334. return NULL;
  4335. year = tm.tm_year + 1900;
  4336. month = tm.tm_mon + 1;
  4337. day = tm.tm_mday;
  4338. hour = tm.tm_hour;
  4339. minute = tm.tm_min;
  4340. /* The platform localtime/gmtime may insert leap seconds,
  4341. * indicated by tm.tm_sec > 59. We don't care about them,
  4342. * except to the extent that passing them on to the datetime
  4343. * constructor would raise ValueError for a reason that
  4344. * made no sense to the user.
  4345. */
  4346. second = Py_MIN(59, tm.tm_sec);
  4347. /* local timezone requires to compute fold */
  4348. if (tzinfo == Py_None && f == _PyTime_localtime
  4349. /* On Windows, passing a negative value to local results
  4350. * in an OSError because localtime_s on Windows does
  4351. * not support negative timestamps. Unfortunately this
  4352. * means that fold detection for time values between
  4353. * 0 and max_fold_seconds will result in an identical
  4354. * error since we subtract max_fold_seconds to detect a
  4355. * fold. However, since we know there haven't been any
  4356. * folds in the interval [0, max_fold_seconds) in any
  4357. * timezone, we can hackily just forego fold detection
  4358. * for this time range.
  4359. */
  4360. #ifdef MS_WINDOWS
  4361. && (timet - max_fold_seconds > 0)
  4362. #endif
  4363. ) {
  4364. long long probe_seconds, result_seconds, transition;
  4365. result_seconds = utc_to_seconds(year, month, day,
  4366. hour, minute, second);
  4367. /* Probe max_fold_seconds to detect a fold. */
  4368. probe_seconds = local(epoch + timet - max_fold_seconds);
  4369. if (probe_seconds == -1)
  4370. return NULL;
  4371. transition = result_seconds - probe_seconds - max_fold_seconds;
  4372. if (transition < 0) {
  4373. probe_seconds = local(epoch + timet + transition);
  4374. if (probe_seconds == -1)
  4375. return NULL;
  4376. if (probe_seconds == result_seconds)
  4377. fold = 1;
  4378. }
  4379. }
  4380. return new_datetime_subclass_fold_ex(year, month, day, hour, minute,
  4381. second, us, tzinfo, fold, cls);
  4382. }
  4383. /* Internal helper.
  4384. * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
  4385. * to control the interpretation of the timestamp. Since a double doesn't
  4386. * have enough bits to cover a datetime's full range of precision, it's
  4387. * better to call datetime_from_timet_and_us provided you have a way
  4388. * to get that much precision (e.g., C time() isn't good enough).
  4389. */
  4390. static PyObject *
  4391. datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
  4392. PyObject *tzinfo)
  4393. {
  4394. time_t timet;
  4395. long us;
  4396. if (_PyTime_ObjectToTimeval(timestamp,
  4397. &timet, &us, _PyTime_ROUND_HALF_EVEN) == -1)
  4398. return NULL;
  4399. return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
  4400. }
  4401. /* Internal helper.
  4402. * Build most accurate possible datetime for current time. Pass localtime or
  4403. * gmtime for f as appropriate.
  4404. */
  4405. static PyObject *
  4406. datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
  4407. {
  4408. _PyTime_t ts = _PyTime_GetSystemClock();
  4409. time_t secs;
  4410. int us;
  4411. if (_PyTime_AsTimevalTime_t(ts, &secs, &us, _PyTime_ROUND_FLOOR) < 0)
  4412. return NULL;
  4413. assert(0 <= us && us <= 999999);
  4414. return datetime_from_timet_and_us(cls, f, secs, us, tzinfo);
  4415. }
  4416. /*[clinic input]
  4417. @classmethod
  4418. datetime.datetime.now
  4419. tz: object = None
  4420. Timezone object.
  4421. Returns new datetime object representing current time local to tz.
  4422. If no tz is specified, uses local timezone.
  4423. [clinic start generated code]*/
  4424. static PyObject *
  4425. datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz)
  4426. /*[clinic end generated code: output=b3386e5345e2b47a input=80d09869c5267d00]*/
  4427. {
  4428. PyObject *self;
  4429. /* Return best possible local time -- this isn't constrained by the
  4430. * precision of a timestamp.
  4431. */
  4432. if (check_tzinfo_subclass(tz) < 0)
  4433. return NULL;
  4434. self = datetime_best_possible((PyObject *)type,
  4435. tz == Py_None ? _PyTime_localtime :
  4436. _PyTime_gmtime,
  4437. tz);
  4438. if (self != NULL && tz != Py_None) {
  4439. /* Convert UTC to tzinfo's zone. */
  4440. self = _PyObject_CallMethodId(tz, &PyId_fromutc, "N", self);
  4441. }
  4442. return self;
  4443. }
  4444. /* Return best possible UTC time -- this isn't constrained by the
  4445. * precision of a timestamp.
  4446. */
  4447. static PyObject *
  4448. datetime_utcnow(PyObject *cls, PyObject *dummy)
  4449. {
  4450. return datetime_best_possible(cls, _PyTime_gmtime, Py_None);
  4451. }
  4452. /* Return new local datetime from timestamp (Python timestamp -- a double). */
  4453. static PyObject *
  4454. datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
  4455. {
  4456. PyObject *self;
  4457. PyObject *timestamp;
  4458. PyObject *tzinfo = Py_None;
  4459. static char *keywords[] = {"timestamp", "tz", NULL};
  4460. if (! PyArg_ParseTupleAndKeywords(args, kw, "O|O:fromtimestamp",
  4461. keywords, &timestamp, &tzinfo))
  4462. return NULL;
  4463. if (check_tzinfo_subclass(tzinfo) < 0)
  4464. return NULL;
  4465. self = datetime_from_timestamp(cls,
  4466. tzinfo == Py_None ? _PyTime_localtime :
  4467. _PyTime_gmtime,
  4468. timestamp,
  4469. tzinfo);
  4470. if (self != NULL && tzinfo != Py_None) {
  4471. /* Convert UTC to tzinfo's zone. */
  4472. self = _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "N", self);
  4473. }
  4474. return self;
  4475. }
  4476. /* Return new UTC datetime from timestamp (Python timestamp -- a double). */
  4477. static PyObject *
  4478. datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
  4479. {
  4480. PyObject *timestamp;
  4481. PyObject *result = NULL;
  4482. if (PyArg_ParseTuple(args, "O:utcfromtimestamp", &timestamp))
  4483. result = datetime_from_timestamp(cls, _PyTime_gmtime, timestamp,
  4484. Py_None);
  4485. return result;
  4486. }
  4487. /* Return new datetime from _strptime.strptime_datetime(). */
  4488. static PyObject *
  4489. datetime_strptime(PyObject *cls, PyObject *args)
  4490. {
  4491. static PyObject *module = NULL;
  4492. PyObject *string, *format;
  4493. _Py_IDENTIFIER(_strptime_datetime);
  4494. if (!PyArg_ParseTuple(args, "UU:strptime", &string, &format))
  4495. return NULL;
  4496. if (module == NULL) {
  4497. module = PyImport_ImportModuleNoBlock("_strptime");
  4498. if (module == NULL)
  4499. return NULL;
  4500. }
  4501. return _PyObject_CallMethodIdObjArgs(module, &PyId__strptime_datetime,
  4502. cls, string, format, NULL);
  4503. }
  4504. /* Return new datetime from date/datetime and time arguments. */
  4505. static PyObject *
  4506. datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
  4507. {
  4508. static char *keywords[] = {"date", "time", "tzinfo", NULL};
  4509. PyObject *date;
  4510. PyObject *time;
  4511. PyObject *tzinfo = NULL;
  4512. PyObject *result = NULL;
  4513. if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!|O:combine", keywords,
  4514. &PyDateTime_DateType, &date,
  4515. &PyDateTime_TimeType, &time, &tzinfo)) {
  4516. if (tzinfo == NULL) {
  4517. if (HASTZINFO(time))
  4518. tzinfo = ((PyDateTime_Time *)time)->tzinfo;
  4519. else
  4520. tzinfo = Py_None;
  4521. }
  4522. result = new_datetime_subclass_fold_ex(GET_YEAR(date),
  4523. GET_MONTH(date),
  4524. GET_DAY(date),
  4525. TIME_GET_HOUR(time),
  4526. TIME_GET_MINUTE(time),
  4527. TIME_GET_SECOND(time),
  4528. TIME_GET_MICROSECOND(time),
  4529. tzinfo,
  4530. TIME_GET_FOLD(time),
  4531. cls);
  4532. }
  4533. return result;
  4534. }
  4535. static PyObject *
  4536. _sanitize_isoformat_str(PyObject *dtstr)
  4537. {
  4538. // `fromisoformat` allows surrogate characters in exactly one position,
  4539. // the separator; to allow datetime_fromisoformat to make the simplifying
  4540. // assumption that all valid strings can be encoded in UTF-8, this function
  4541. // replaces any surrogate character separators with `T`.
  4542. //
  4543. // The result of this, if not NULL, returns a new reference
  4544. Py_ssize_t len = PyUnicode_GetLength(dtstr);
  4545. if (len < 0) {
  4546. return NULL;
  4547. }
  4548. if (len <= 10 ||
  4549. !Py_UNICODE_IS_SURROGATE(PyUnicode_READ_CHAR(dtstr, 10))) {
  4550. Py_INCREF(dtstr);
  4551. return dtstr;
  4552. }
  4553. PyObject *str_out = _PyUnicode_Copy(dtstr);
  4554. if (str_out == NULL) {
  4555. return NULL;
  4556. }
  4557. if (PyUnicode_WriteChar(str_out, 10, (Py_UCS4)'T')) {
  4558. Py_DECREF(str_out);
  4559. return NULL;
  4560. }
  4561. return str_out;
  4562. }
  4563. static PyObject *
  4564. datetime_fromisoformat(PyObject *cls, PyObject *dtstr)
  4565. {
  4566. assert(dtstr != NULL);
  4567. if (!PyUnicode_Check(dtstr)) {
  4568. PyErr_SetString(PyExc_TypeError,
  4569. "fromisoformat: argument must be str");
  4570. return NULL;
  4571. }
  4572. PyObject *dtstr_clean = _sanitize_isoformat_str(dtstr);
  4573. if (dtstr_clean == NULL) {
  4574. goto error;
  4575. }
  4576. Py_ssize_t len;
  4577. const char *dt_ptr = PyUnicode_AsUTF8AndSize(dtstr_clean, &len);
  4578. if (dt_ptr == NULL) {
  4579. if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
  4580. // Encoding errors are invalid string errors at this point
  4581. goto invalid_string_error;
  4582. }
  4583. else {
  4584. goto error;
  4585. }
  4586. }
  4587. const char *p = dt_ptr;
  4588. int year = 0, month = 0, day = 0;
  4589. int hour = 0, minute = 0, second = 0, microsecond = 0;
  4590. int tzoffset = 0, tzusec = 0;
  4591. // date has a fixed length of 10
  4592. int rv = parse_isoformat_date(p, &year, &month, &day);
  4593. if (!rv && len > 10) {
  4594. // In UTF-8, the length of multi-byte characters is encoded in the MSB
  4595. if ((p[10] & 0x80) == 0) {
  4596. p += 11;
  4597. }
  4598. else {
  4599. switch (p[10] & 0xf0) {
  4600. case 0xe0:
  4601. p += 13;
  4602. break;
  4603. case 0xf0:
  4604. p += 14;
  4605. break;
  4606. default:
  4607. p += 12;
  4608. break;
  4609. }
  4610. }
  4611. len -= (p - dt_ptr);
  4612. rv = parse_isoformat_time(p, len, &hour, &minute, &second,
  4613. &microsecond, &tzoffset, &tzusec);
  4614. }
  4615. if (rv < 0) {
  4616. goto invalid_string_error;
  4617. }
  4618. PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, tzusec);
  4619. if (tzinfo == NULL) {
  4620. goto error;
  4621. }
  4622. PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute,
  4623. second, microsecond, tzinfo, cls);
  4624. Py_DECREF(tzinfo);
  4625. Py_DECREF(dtstr_clean);
  4626. return dt;
  4627. invalid_string_error:
  4628. PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", dtstr);
  4629. error:
  4630. Py_XDECREF(dtstr_clean);
  4631. return NULL;
  4632. }
  4633. /*
  4634. * Destructor.
  4635. */
  4636. static void
  4637. datetime_dealloc(PyDateTime_DateTime *self)
  4638. {
  4639. if (HASTZINFO(self)) {
  4640. Py_XDECREF(self->tzinfo);
  4641. }
  4642. Py_TYPE(self)->tp_free((PyObject *)self);
  4643. }
  4644. /*
  4645. * Indirect access to tzinfo methods.
  4646. */
  4647. /* These are all METH_NOARGS, so don't need to check the arglist. */
  4648. static PyObject *
  4649. datetime_utcoffset(PyObject *self, PyObject *unused) {
  4650. return call_utcoffset(GET_DT_TZINFO(self), self);
  4651. }
  4652. static PyObject *
  4653. datetime_dst(PyObject *self, PyObject *unused) {
  4654. return call_dst(GET_DT_TZINFO(self), self);
  4655. }
  4656. static PyObject *
  4657. datetime_tzname(PyObject *self, PyObject *unused) {
  4658. return call_tzname(GET_DT_TZINFO(self), self);
  4659. }
  4660. /*
  4661. * datetime arithmetic.
  4662. */
  4663. /* factor must be 1 (to add) or -1 (to subtract). The result inherits
  4664. * the tzinfo state of date.
  4665. */
  4666. static PyObject *
  4667. add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta,
  4668. int factor)
  4669. {
  4670. /* Note that the C-level additions can't overflow, because of
  4671. * invariant bounds on the member values.
  4672. */
  4673. int year = GET_YEAR(date);
  4674. int month = GET_MONTH(date);
  4675. int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor;
  4676. int hour = DATE_GET_HOUR(date);
  4677. int minute = DATE_GET_MINUTE(date);
  4678. int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor;
  4679. int microsecond = DATE_GET_MICROSECOND(date) +
  4680. GET_TD_MICROSECONDS(delta) * factor;
  4681. assert(factor == 1 || factor == -1);
  4682. if (normalize_datetime(&year, &month, &day,
  4683. &hour, &minute, &second, &microsecond) < 0) {
  4684. return NULL;
  4685. }
  4686. return new_datetime_subclass_ex(year, month, day,
  4687. hour, minute, second, microsecond,
  4688. HASTZINFO(date) ? date->tzinfo : Py_None,
  4689. (PyObject *)Py_TYPE(date));
  4690. }
  4691. static PyObject *
  4692. datetime_add(PyObject *left, PyObject *right)
  4693. {
  4694. if (PyDateTime_Check(left)) {
  4695. /* datetime + ??? */
  4696. if (PyDelta_Check(right))
  4697. /* datetime + delta */
  4698. return add_datetime_timedelta(
  4699. (PyDateTime_DateTime *)left,
  4700. (PyDateTime_Delta *)right,
  4701. 1);
  4702. }
  4703. else if (PyDelta_Check(left)) {
  4704. /* delta + datetime */
  4705. return add_datetime_timedelta((PyDateTime_DateTime *) right,
  4706. (PyDateTime_Delta *) left,
  4707. 1);
  4708. }
  4709. Py_RETURN_NOTIMPLEMENTED;
  4710. }
  4711. static PyObject *
  4712. datetime_subtract(PyObject *left, PyObject *right)
  4713. {
  4714. PyObject *result = Py_NotImplemented;
  4715. if (PyDateTime_Check(left)) {
  4716. /* datetime - ??? */
  4717. if (PyDateTime_Check(right)) {
  4718. /* datetime - datetime */
  4719. PyObject *offset1, *offset2, *offdiff = NULL;
  4720. int delta_d, delta_s, delta_us;
  4721. if (GET_DT_TZINFO(left) == GET_DT_TZINFO(right)) {
  4722. offset2 = offset1 = Py_None;
  4723. Py_INCREF(offset1);
  4724. Py_INCREF(offset2);
  4725. }
  4726. else {
  4727. offset1 = datetime_utcoffset(left, NULL);
  4728. if (offset1 == NULL)
  4729. return NULL;
  4730. offset2 = datetime_utcoffset(right, NULL);
  4731. if (offset2 == NULL) {
  4732. Py_DECREF(offset1);
  4733. return NULL;
  4734. }
  4735. if ((offset1 != Py_None) != (offset2 != Py_None)) {
  4736. PyErr_SetString(PyExc_TypeError,
  4737. "can't subtract offset-naive and "
  4738. "offset-aware datetimes");
  4739. Py_DECREF(offset1);
  4740. Py_DECREF(offset2);
  4741. return NULL;
  4742. }
  4743. }
  4744. if ((offset1 != offset2) &&
  4745. delta_cmp(offset1, offset2) != 0) {
  4746. offdiff = delta_subtract(offset1, offset2);
  4747. if (offdiff == NULL) {
  4748. Py_DECREF(offset1);
  4749. Py_DECREF(offset2);
  4750. return NULL;
  4751. }
  4752. }
  4753. Py_DECREF(offset1);
  4754. Py_DECREF(offset2);
  4755. delta_d = ymd_to_ord(GET_YEAR(left),
  4756. GET_MONTH(left),
  4757. GET_DAY(left)) -
  4758. ymd_to_ord(GET_YEAR(right),
  4759. GET_MONTH(right),
  4760. GET_DAY(right));
  4761. /* These can't overflow, since the values are
  4762. * normalized. At most this gives the number of
  4763. * seconds in one day.
  4764. */
  4765. delta_s = (DATE_GET_HOUR(left) -
  4766. DATE_GET_HOUR(right)) * 3600 +
  4767. (DATE_GET_MINUTE(left) -
  4768. DATE_GET_MINUTE(right)) * 60 +
  4769. (DATE_GET_SECOND(left) -
  4770. DATE_GET_SECOND(right));
  4771. delta_us = DATE_GET_MICROSECOND(left) -
  4772. DATE_GET_MICROSECOND(right);
  4773. result = new_delta(delta_d, delta_s, delta_us, 1);
  4774. if (result == NULL)
  4775. return NULL;
  4776. if (offdiff != NULL) {
  4777. Py_SETREF(result, delta_subtract(result, offdiff));
  4778. Py_DECREF(offdiff);
  4779. }
  4780. }
  4781. else if (PyDelta_Check(right)) {
  4782. /* datetime - delta */
  4783. result = add_datetime_timedelta(
  4784. (PyDateTime_DateTime *)left,
  4785. (PyDateTime_Delta *)right,
  4786. -1);
  4787. }
  4788. }
  4789. if (result == Py_NotImplemented)
  4790. Py_INCREF(result);
  4791. return result;
  4792. }
  4793. /* Various ways to turn a datetime into a string. */
  4794. static PyObject *
  4795. datetime_repr(PyDateTime_DateTime *self)
  4796. {
  4797. const char *type_name = Py_TYPE(self)->tp_name;
  4798. PyObject *baserepr;
  4799. if (DATE_GET_MICROSECOND(self)) {
  4800. baserepr = PyUnicode_FromFormat(
  4801. "%s(%d, %d, %d, %d, %d, %d, %d)",
  4802. type_name,
  4803. GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
  4804. DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
  4805. DATE_GET_SECOND(self),
  4806. DATE_GET_MICROSECOND(self));
  4807. }
  4808. else if (DATE_GET_SECOND(self)) {
  4809. baserepr = PyUnicode_FromFormat(
  4810. "%s(%d, %d, %d, %d, %d, %d)",
  4811. type_name,
  4812. GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
  4813. DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
  4814. DATE_GET_SECOND(self));
  4815. }
  4816. else {
  4817. baserepr = PyUnicode_FromFormat(
  4818. "%s(%d, %d, %d, %d, %d)",
  4819. type_name,
  4820. GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
  4821. DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
  4822. }
  4823. if (baserepr != NULL && DATE_GET_FOLD(self) != 0)
  4824. baserepr = append_keyword_fold(baserepr, DATE_GET_FOLD(self));
  4825. if (baserepr == NULL || ! HASTZINFO(self))
  4826. return baserepr;
  4827. return append_keyword_tzinfo(baserepr, self->tzinfo);
  4828. }
  4829. static PyObject *
  4830. datetime_str(PyDateTime_DateTime *self)
  4831. {
  4832. return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, "s", " ");
  4833. }
  4834. static PyObject *
  4835. datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
  4836. {
  4837. int sep = 'T';
  4838. char *timespec = NULL;
  4839. static char *keywords[] = {"sep", "timespec", NULL};
  4840. char buffer[100];
  4841. PyObject *result = NULL;
  4842. int us = DATE_GET_MICROSECOND(self);
  4843. static const char *specs[][2] = {
  4844. {"hours", "%04d-%02d-%02d%c%02d"},
  4845. {"minutes", "%04d-%02d-%02d%c%02d:%02d"},
  4846. {"seconds", "%04d-%02d-%02d%c%02d:%02d:%02d"},
  4847. {"milliseconds", "%04d-%02d-%02d%c%02d:%02d:%02d.%03d"},
  4848. {"microseconds", "%04d-%02d-%02d%c%02d:%02d:%02d.%06d"},
  4849. };
  4850. size_t given_spec;
  4851. if (!PyArg_ParseTupleAndKeywords(args, kw, "|Cs:isoformat", keywords, &sep, &timespec))
  4852. return NULL;
  4853. if (timespec == NULL || strcmp(timespec, "auto") == 0) {
  4854. if (us == 0) {
  4855. /* seconds */
  4856. given_spec = 2;
  4857. }
  4858. else {
  4859. /* microseconds */
  4860. given_spec = 4;
  4861. }
  4862. }
  4863. else {
  4864. for (given_spec = 0; given_spec < Py_ARRAY_LENGTH(specs); given_spec++) {
  4865. if (strcmp(timespec, specs[given_spec][0]) == 0) {
  4866. if (given_spec == 3) {
  4867. us = us / 1000;
  4868. }
  4869. break;
  4870. }
  4871. }
  4872. }
  4873. if (given_spec == Py_ARRAY_LENGTH(specs)) {
  4874. PyErr_Format(PyExc_ValueError, "Unknown timespec value");
  4875. return NULL;
  4876. }
  4877. else {
  4878. result = PyUnicode_FromFormat(specs[given_spec][1],
  4879. GET_YEAR(self), GET_MONTH(self),
  4880. GET_DAY(self), (int)sep,
  4881. DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
  4882. DATE_GET_SECOND(self), us);
  4883. }
  4884. if (!result || !HASTZINFO(self))
  4885. return result;
  4886. /* We need to append the UTC offset. */
  4887. if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo,
  4888. (PyObject *)self) < 0) {
  4889. Py_DECREF(result);
  4890. return NULL;
  4891. }
  4892. PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buffer));
  4893. return result;
  4894. }
  4895. static PyObject *
  4896. datetime_ctime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
  4897. {
  4898. return format_ctime((PyDateTime_Date *)self,
  4899. DATE_GET_HOUR(self),
  4900. DATE_GET_MINUTE(self),
  4901. DATE_GET_SECOND(self));
  4902. }
  4903. /* Miscellaneous methods. */
  4904. static PyObject *
  4905. flip_fold(PyObject *dt)
  4906. {
  4907. return new_datetime_ex2(GET_YEAR(dt),
  4908. GET_MONTH(dt),
  4909. GET_DAY(dt),
  4910. DATE_GET_HOUR(dt),
  4911. DATE_GET_MINUTE(dt),
  4912. DATE_GET_SECOND(dt),
  4913. DATE_GET_MICROSECOND(dt),
  4914. HASTZINFO(dt) ?
  4915. ((PyDateTime_DateTime *)dt)->tzinfo : Py_None,
  4916. !DATE_GET_FOLD(dt),
  4917. Py_TYPE(dt));
  4918. }
  4919. static PyObject *
  4920. get_flip_fold_offset(PyObject *dt)
  4921. {
  4922. PyObject *result, *flip_dt;
  4923. flip_dt = flip_fold(dt);
  4924. if (flip_dt == NULL)
  4925. return NULL;
  4926. result = datetime_utcoffset(flip_dt, NULL);
  4927. Py_DECREF(flip_dt);
  4928. return result;
  4929. }
  4930. /* PEP 495 exception: Whenever one or both of the operands in
  4931. * inter-zone comparison is such that its utcoffset() depends
  4932. * on the value of its fold attribute, the result is False.
  4933. *
  4934. * Return 1 if exception applies, 0 if not, and -1 on error.
  4935. */
  4936. static int
  4937. pep495_eq_exception(PyObject *self, PyObject *other,
  4938. PyObject *offset_self, PyObject *offset_other)
  4939. {
  4940. int result = 0;
  4941. PyObject *flip_offset;
  4942. flip_offset = get_flip_fold_offset(self);
  4943. if (flip_offset == NULL)
  4944. return -1;
  4945. if (flip_offset != offset_self &&
  4946. delta_cmp(flip_offset, offset_self))
  4947. {
  4948. result = 1;
  4949. goto done;
  4950. }
  4951. Py_DECREF(flip_offset);
  4952. flip_offset = get_flip_fold_offset(other);
  4953. if (flip_offset == NULL)
  4954. return -1;
  4955. if (flip_offset != offset_other &&
  4956. delta_cmp(flip_offset, offset_other))
  4957. result = 1;
  4958. done:
  4959. Py_DECREF(flip_offset);
  4960. return result;
  4961. }
  4962. static PyObject *
  4963. datetime_richcompare(PyObject *self, PyObject *other, int op)
  4964. {
  4965. PyObject *result = NULL;
  4966. PyObject *offset1, *offset2;
  4967. int diff;
  4968. if (! PyDateTime_Check(other)) {
  4969. if (PyDate_Check(other)) {
  4970. /* Prevent invocation of date_richcompare. We want to
  4971. return NotImplemented here to give the other object
  4972. a chance. But since DateTime is a subclass of
  4973. Date, if the other object is a Date, it would
  4974. compute an ordering based on the date part alone,
  4975. and we don't want that. So force unequal or
  4976. uncomparable here in that case. */
  4977. if (op == Py_EQ)
  4978. Py_RETURN_FALSE;
  4979. if (op == Py_NE)
  4980. Py_RETURN_TRUE;
  4981. return cmperror(self, other);
  4982. }
  4983. Py_RETURN_NOTIMPLEMENTED;
  4984. }
  4985. if (GET_DT_TZINFO(self) == GET_DT_TZINFO(other)) {
  4986. diff = memcmp(((PyDateTime_DateTime *)self)->data,
  4987. ((PyDateTime_DateTime *)other)->data,
  4988. _PyDateTime_DATETIME_DATASIZE);
  4989. return diff_to_bool(diff, op);
  4990. }
  4991. offset1 = datetime_utcoffset(self, NULL);
  4992. if (offset1 == NULL)
  4993. return NULL;
  4994. offset2 = datetime_utcoffset(other, NULL);
  4995. if (offset2 == NULL)
  4996. goto done;
  4997. /* If they're both naive, or both aware and have the same offsets,
  4998. * we get off cheap. Note that if they're both naive, offset1 ==
  4999. * offset2 == Py_None at this point.
  5000. */
  5001. if ((offset1 == offset2) ||
  5002. (PyDelta_Check(offset1) && PyDelta_Check(offset2) &&
  5003. delta_cmp(offset1, offset2) == 0)) {
  5004. diff = memcmp(((PyDateTime_DateTime *)self)->data,
  5005. ((PyDateTime_DateTime *)other)->data,
  5006. _PyDateTime_DATETIME_DATASIZE);
  5007. if ((op == Py_EQ || op == Py_NE) && diff == 0) {
  5008. int ex = pep495_eq_exception(self, other, offset1, offset2);
  5009. if (ex == -1)
  5010. goto done;
  5011. if (ex)
  5012. diff = 1;
  5013. }
  5014. result = diff_to_bool(diff, op);
  5015. }
  5016. else if (offset1 != Py_None && offset2 != Py_None) {
  5017. PyDateTime_Delta *delta;
  5018. assert(offset1 != offset2); /* else last "if" handled it */
  5019. delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self,
  5020. other);
  5021. if (delta == NULL)
  5022. goto done;
  5023. diff = GET_TD_DAYS(delta);
  5024. if (diff == 0)
  5025. diff = GET_TD_SECONDS(delta) |
  5026. GET_TD_MICROSECONDS(delta);
  5027. Py_DECREF(delta);
  5028. if ((op == Py_EQ || op == Py_NE) && diff == 0) {
  5029. int ex = pep495_eq_exception(self, other, offset1, offset2);
  5030. if (ex == -1)
  5031. goto done;
  5032. if (ex)
  5033. diff = 1;
  5034. }
  5035. result = diff_to_bool(diff, op);
  5036. }
  5037. else if (op == Py_EQ) {
  5038. result = Py_False;
  5039. Py_INCREF(result);
  5040. }
  5041. else if (op == Py_NE) {
  5042. result = Py_True;
  5043. Py_INCREF(result);
  5044. }
  5045. else {
  5046. PyErr_SetString(PyExc_TypeError,
  5047. "can't compare offset-naive and "
  5048. "offset-aware datetimes");
  5049. }
  5050. done:
  5051. Py_DECREF(offset1);
  5052. Py_XDECREF(offset2);
  5053. return result;
  5054. }
  5055. static Py_hash_t
  5056. datetime_hash(PyDateTime_DateTime *self)
  5057. {
  5058. if (self->hashcode == -1) {
  5059. PyObject *offset, *self0;
  5060. if (DATE_GET_FOLD(self)) {
  5061. self0 = new_datetime_ex2(GET_YEAR(self),
  5062. GET_MONTH(self),
  5063. GET_DAY(self),
  5064. DATE_GET_HOUR(self),
  5065. DATE_GET_MINUTE(self),
  5066. DATE_GET_SECOND(self),
  5067. DATE_GET_MICROSECOND(self),
  5068. HASTZINFO(self) ? self->tzinfo : Py_None,
  5069. 0, Py_TYPE(self));
  5070. if (self0 == NULL)
  5071. return -1;
  5072. }
  5073. else {
  5074. self0 = (PyObject *)self;
  5075. Py_INCREF(self0);
  5076. }
  5077. offset = datetime_utcoffset(self0, NULL);
  5078. Py_DECREF(self0);
  5079. if (offset == NULL)
  5080. return -1;
  5081. /* Reduce this to a hash of another object. */
  5082. if (offset == Py_None)
  5083. self->hashcode = generic_hash(
  5084. (unsigned char *)self->data, _PyDateTime_DATETIME_DATASIZE);
  5085. else {
  5086. PyObject *temp1, *temp2;
  5087. int days, seconds;
  5088. assert(HASTZINFO(self));
  5089. days = ymd_to_ord(GET_YEAR(self),
  5090. GET_MONTH(self),
  5091. GET_DAY(self));
  5092. seconds = DATE_GET_HOUR(self) * 3600 +
  5093. DATE_GET_MINUTE(self) * 60 +
  5094. DATE_GET_SECOND(self);
  5095. temp1 = new_delta(days, seconds,
  5096. DATE_GET_MICROSECOND(self),
  5097. 1);
  5098. if (temp1 == NULL) {
  5099. Py_DECREF(offset);
  5100. return -1;
  5101. }
  5102. temp2 = delta_subtract(temp1, offset);
  5103. Py_DECREF(temp1);
  5104. if (temp2 == NULL) {
  5105. Py_DECREF(offset);
  5106. return -1;
  5107. }
  5108. self->hashcode = PyObject_Hash(temp2);
  5109. Py_DECREF(temp2);
  5110. }
  5111. Py_DECREF(offset);
  5112. }
  5113. return self->hashcode;
  5114. }
  5115. static PyObject *
  5116. datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
  5117. {
  5118. PyObject *clone;
  5119. PyObject *tuple;
  5120. int y = GET_YEAR(self);
  5121. int m = GET_MONTH(self);
  5122. int d = GET_DAY(self);
  5123. int hh = DATE_GET_HOUR(self);
  5124. int mm = DATE_GET_MINUTE(self);
  5125. int ss = DATE_GET_SECOND(self);
  5126. int us = DATE_GET_MICROSECOND(self);
  5127. PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
  5128. int fold = DATE_GET_FOLD(self);
  5129. if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO$i:replace",
  5130. datetime_kws,
  5131. &y, &m, &d, &hh, &mm, &ss, &us,
  5132. &tzinfo, &fold))
  5133. return NULL;
  5134. if (fold != 0 && fold != 1) {
  5135. PyErr_SetString(PyExc_ValueError,
  5136. "fold must be either 0 or 1");
  5137. return NULL;
  5138. }
  5139. tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
  5140. if (tuple == NULL)
  5141. return NULL;
  5142. clone = datetime_new(Py_TYPE(self), tuple, NULL);
  5143. if (clone != NULL) {
  5144. DATE_SET_FOLD(clone, fold);
  5145. }
  5146. Py_DECREF(tuple);
  5147. return clone;
  5148. }
  5149. static PyObject *
  5150. local_timezone_from_timestamp(time_t timestamp)
  5151. {
  5152. PyObject *result = NULL;
  5153. PyObject *delta;
  5154. struct tm local_time_tm;
  5155. PyObject *nameo = NULL;
  5156. const char *zone = NULL;
  5157. if (_PyTime_localtime(timestamp, &local_time_tm) != 0)
  5158. return NULL;
  5159. #ifdef HAVE_STRUCT_TM_TM_ZONE
  5160. zone = local_time_tm.tm_zone;
  5161. delta = new_delta(0, local_time_tm.tm_gmtoff, 0, 1);
  5162. #else /* HAVE_STRUCT_TM_TM_ZONE */
  5163. {
  5164. PyObject *local_time, *utc_time;
  5165. struct tm utc_time_tm;
  5166. char buf[100];
  5167. strftime(buf, sizeof(buf), "%Z", &local_time_tm);
  5168. zone = buf;
  5169. local_time = new_datetime(local_time_tm.tm_year + 1900,
  5170. local_time_tm.tm_mon + 1,
  5171. local_time_tm.tm_mday,
  5172. local_time_tm.tm_hour,
  5173. local_time_tm.tm_min,
  5174. local_time_tm.tm_sec, 0, Py_None, 0);
  5175. if (local_time == NULL) {
  5176. return NULL;
  5177. }
  5178. if (_PyTime_gmtime(timestamp, &utc_time_tm) != 0)
  5179. return NULL;
  5180. utc_time = new_datetime(utc_time_tm.tm_year + 1900,
  5181. utc_time_tm.tm_mon + 1,
  5182. utc_time_tm.tm_mday,
  5183. utc_time_tm.tm_hour,
  5184. utc_time_tm.tm_min,
  5185. utc_time_tm.tm_sec, 0, Py_None, 0);
  5186. if (utc_time == NULL) {
  5187. Py_DECREF(local_time);
  5188. return NULL;
  5189. }
  5190. delta = datetime_subtract(local_time, utc_time);
  5191. Py_DECREF(local_time);
  5192. Py_DECREF(utc_time);
  5193. }
  5194. #endif /* HAVE_STRUCT_TM_TM_ZONE */
  5195. if (delta == NULL) {
  5196. return NULL;
  5197. }
  5198. if (zone != NULL) {
  5199. nameo = PyUnicode_DecodeLocale(zone, "surrogateescape");
  5200. if (nameo == NULL)
  5201. goto error;
  5202. }
  5203. result = new_timezone(delta, nameo);
  5204. Py_XDECREF(nameo);
  5205. error:
  5206. Py_DECREF(delta);
  5207. return result;
  5208. }
  5209. static PyObject *
  5210. local_timezone(PyDateTime_DateTime *utc_time)
  5211. {
  5212. time_t timestamp;
  5213. PyObject *delta;
  5214. PyObject *one_second;
  5215. PyObject *seconds;
  5216. delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch);
  5217. if (delta == NULL)
  5218. return NULL;
  5219. one_second = new_delta(0, 1, 0, 0);
  5220. if (one_second == NULL) {
  5221. Py_DECREF(delta);
  5222. return NULL;
  5223. }
  5224. seconds = divide_timedelta_timedelta((PyDateTime_Delta *)delta,
  5225. (PyDateTime_Delta *)one_second);
  5226. Py_DECREF(one_second);
  5227. Py_DECREF(delta);
  5228. if (seconds == NULL)
  5229. return NULL;
  5230. timestamp = _PyLong_AsTime_t(seconds);
  5231. Py_DECREF(seconds);
  5232. if (timestamp == -1 && PyErr_Occurred())
  5233. return NULL;
  5234. return local_timezone_from_timestamp(timestamp);
  5235. }
  5236. static long long
  5237. local_to_seconds(int year, int month, int day,
  5238. int hour, int minute, int second, int fold);
  5239. static PyObject *
  5240. local_timezone_from_local(PyDateTime_DateTime *local_dt)
  5241. {
  5242. long long seconds;
  5243. time_t timestamp;
  5244. seconds = local_to_seconds(GET_YEAR(local_dt),
  5245. GET_MONTH(local_dt),
  5246. GET_DAY(local_dt),
  5247. DATE_GET_HOUR(local_dt),
  5248. DATE_GET_MINUTE(local_dt),
  5249. DATE_GET_SECOND(local_dt),
  5250. DATE_GET_FOLD(local_dt));
  5251. if (seconds == -1)
  5252. return NULL;
  5253. /* XXX: add bounds check */
  5254. timestamp = seconds - epoch;
  5255. return local_timezone_from_timestamp(timestamp);
  5256. }
  5257. static PyDateTime_DateTime *
  5258. datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
  5259. {
  5260. PyDateTime_DateTime *result;
  5261. PyObject *offset;
  5262. PyObject *temp;
  5263. PyObject *self_tzinfo;
  5264. PyObject *tzinfo = Py_None;
  5265. static char *keywords[] = {"tz", NULL};
  5266. if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:astimezone", keywords,
  5267. &tzinfo))
  5268. return NULL;
  5269. if (check_tzinfo_subclass(tzinfo) == -1)
  5270. return NULL;
  5271. if (!HASTZINFO(self) || self->tzinfo == Py_None) {
  5272. naive:
  5273. self_tzinfo = local_timezone_from_local(self);
  5274. if (self_tzinfo == NULL)
  5275. return NULL;
  5276. } else {
  5277. self_tzinfo = self->tzinfo;
  5278. Py_INCREF(self_tzinfo);
  5279. }
  5280. /* Conversion to self's own time zone is a NOP. */
  5281. if (self_tzinfo == tzinfo) {
  5282. Py_DECREF(self_tzinfo);
  5283. Py_INCREF(self);
  5284. return self;
  5285. }
  5286. /* Convert self to UTC. */
  5287. offset = call_utcoffset(self_tzinfo, (PyObject *)self);
  5288. Py_DECREF(self_tzinfo);
  5289. if (offset == NULL)
  5290. return NULL;
  5291. else if(offset == Py_None) {
  5292. Py_DECREF(offset);
  5293. goto naive;
  5294. }
  5295. else if (!PyDelta_Check(offset)) {
  5296. Py_DECREF(offset);
  5297. PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s,"
  5298. " expected timedelta or None", Py_TYPE(offset)->tp_name);
  5299. return NULL;
  5300. }
  5301. /* result = self - offset */
  5302. result = (PyDateTime_DateTime *)add_datetime_timedelta(self,
  5303. (PyDateTime_Delta *)offset, -1);
  5304. Py_DECREF(offset);
  5305. if (result == NULL)
  5306. return NULL;
  5307. /* Make sure result is aware and UTC. */
  5308. if (!HASTZINFO(result)) {
  5309. temp = (PyObject *)result;
  5310. result = (PyDateTime_DateTime *)
  5311. new_datetime_ex2(GET_YEAR(result),
  5312. GET_MONTH(result),
  5313. GET_DAY(result),
  5314. DATE_GET_HOUR(result),
  5315. DATE_GET_MINUTE(result),
  5316. DATE_GET_SECOND(result),
  5317. DATE_GET_MICROSECOND(result),
  5318. PyDateTime_TimeZone_UTC,
  5319. DATE_GET_FOLD(result),
  5320. Py_TYPE(result));
  5321. Py_DECREF(temp);
  5322. if (result == NULL)
  5323. return NULL;
  5324. }
  5325. else {
  5326. /* Result is already aware - just replace tzinfo. */
  5327. temp = result->tzinfo;
  5328. result->tzinfo = PyDateTime_TimeZone_UTC;
  5329. Py_INCREF(result->tzinfo);
  5330. Py_DECREF(temp);
  5331. }
  5332. /* Attach new tzinfo and let fromutc() do the rest. */
  5333. temp = result->tzinfo;
  5334. if (tzinfo == Py_None) {
  5335. tzinfo = local_timezone(result);
  5336. if (tzinfo == NULL) {
  5337. Py_DECREF(result);
  5338. return NULL;
  5339. }
  5340. }
  5341. else
  5342. Py_INCREF(tzinfo);
  5343. result->tzinfo = tzinfo;
  5344. Py_DECREF(temp);
  5345. temp = (PyObject *)result;
  5346. result = (PyDateTime_DateTime *)
  5347. _PyObject_CallMethodIdOneArg(tzinfo, &PyId_fromutc, temp);
  5348. Py_DECREF(temp);
  5349. return result;
  5350. }
  5351. static PyObject *
  5352. datetime_timetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
  5353. {
  5354. int dstflag = -1;
  5355. if (HASTZINFO(self) && self->tzinfo != Py_None) {
  5356. PyObject * dst;
  5357. dst = call_dst(self->tzinfo, (PyObject *)self);
  5358. if (dst == NULL)
  5359. return NULL;
  5360. if (dst != Py_None)
  5361. dstflag = delta_bool((PyDateTime_Delta *)dst);
  5362. Py_DECREF(dst);
  5363. }
  5364. return build_struct_time(GET_YEAR(self),
  5365. GET_MONTH(self),
  5366. GET_DAY(self),
  5367. DATE_GET_HOUR(self),
  5368. DATE_GET_MINUTE(self),
  5369. DATE_GET_SECOND(self),
  5370. dstflag);
  5371. }
  5372. static long long
  5373. local_to_seconds(int year, int month, int day,
  5374. int hour, int minute, int second, int fold)
  5375. {
  5376. long long t, a, b, u1, u2, t1, t2, lt;
  5377. t = utc_to_seconds(year, month, day, hour, minute, second);
  5378. /* Our goal is to solve t = local(u) for u. */
  5379. lt = local(t);
  5380. if (lt == -1)
  5381. return -1;
  5382. a = lt - t;
  5383. u1 = t - a;
  5384. t1 = local(u1);
  5385. if (t1 == -1)
  5386. return -1;
  5387. if (t1 == t) {
  5388. /* We found one solution, but it may not be the one we need.
  5389. * Look for an earlier solution (if `fold` is 0), or a
  5390. * later one (if `fold` is 1). */
  5391. if (fold)
  5392. u2 = u1 + max_fold_seconds;
  5393. else
  5394. u2 = u1 - max_fold_seconds;
  5395. lt = local(u2);
  5396. if (lt == -1)
  5397. return -1;
  5398. b = lt - u2;
  5399. if (a == b)
  5400. return u1;
  5401. }
  5402. else {
  5403. b = t1 - u1;
  5404. assert(a != b);
  5405. }
  5406. u2 = t - b;
  5407. t2 = local(u2);
  5408. if (t2 == -1)
  5409. return -1;
  5410. if (t2 == t)
  5411. return u2;
  5412. if (t1 == t)
  5413. return u1;
  5414. /* We have found both offsets a and b, but neither t - a nor t - b is
  5415. * a solution. This means t is in the gap. */
  5416. return fold?Py_MIN(u1, u2):Py_MAX(u1, u2);
  5417. }
  5418. /* date(1970,1,1).toordinal() == 719163 */
  5419. #define EPOCH_SECONDS (719163LL * 24 * 60 * 60)
  5420. static PyObject *
  5421. datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
  5422. {
  5423. PyObject *result;
  5424. if (HASTZINFO(self) && self->tzinfo != Py_None) {
  5425. PyObject *delta;
  5426. delta = datetime_subtract((PyObject *)self, PyDateTime_Epoch);
  5427. if (delta == NULL)
  5428. return NULL;
  5429. result = delta_total_seconds(delta, NULL);
  5430. Py_DECREF(delta);
  5431. }
  5432. else {
  5433. long long seconds;
  5434. seconds = local_to_seconds(GET_YEAR(self),
  5435. GET_MONTH(self),
  5436. GET_DAY(self),
  5437. DATE_GET_HOUR(self),
  5438. DATE_GET_MINUTE(self),
  5439. DATE_GET_SECOND(self),
  5440. DATE_GET_FOLD(self));
  5441. if (seconds == -1)
  5442. return NULL;
  5443. result = PyFloat_FromDouble(seconds - EPOCH_SECONDS +
  5444. DATE_GET_MICROSECOND(self) / 1e6);
  5445. }
  5446. return result;
  5447. }
  5448. static PyObject *
  5449. datetime_getdate(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
  5450. {
  5451. return new_date(GET_YEAR(self),
  5452. GET_MONTH(self),
  5453. GET_DAY(self));
  5454. }
  5455. static PyObject *
  5456. datetime_gettime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
  5457. {
  5458. return new_time(DATE_GET_HOUR(self),
  5459. DATE_GET_MINUTE(self),
  5460. DATE_GET_SECOND(self),
  5461. DATE_GET_MICROSECOND(self),
  5462. Py_None,
  5463. DATE_GET_FOLD(self));
  5464. }
  5465. static PyObject *
  5466. datetime_gettimetz(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
  5467. {
  5468. return new_time(DATE_GET_HOUR(self),
  5469. DATE_GET_MINUTE(self),
  5470. DATE_GET_SECOND(self),
  5471. DATE_GET_MICROSECOND(self),
  5472. GET_DT_TZINFO(self),
  5473. DATE_GET_FOLD(self));
  5474. }
  5475. static PyObject *
  5476. datetime_utctimetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
  5477. {
  5478. int y, m, d, hh, mm, ss;
  5479. PyObject *tzinfo;
  5480. PyDateTime_DateTime *utcself;
  5481. tzinfo = GET_DT_TZINFO(self);
  5482. if (tzinfo == Py_None) {
  5483. utcself = self;
  5484. Py_INCREF(utcself);
  5485. }
  5486. else {
  5487. PyObject *offset;
  5488. offset = call_utcoffset(tzinfo, (PyObject *)self);
  5489. if (offset == NULL)
  5490. return NULL;
  5491. if (offset == Py_None) {
  5492. Py_DECREF(offset);
  5493. utcself = self;
  5494. Py_INCREF(utcself);
  5495. }
  5496. else {
  5497. utcself = (PyDateTime_DateTime *)add_datetime_timedelta(self,
  5498. (PyDateTime_Delta *)offset, -1);
  5499. Py_DECREF(offset);
  5500. if (utcself == NULL)
  5501. return NULL;
  5502. }
  5503. }
  5504. y = GET_YEAR(utcself);
  5505. m = GET_MONTH(utcself);
  5506. d = GET_DAY(utcself);
  5507. hh = DATE_GET_HOUR(utcself);
  5508. mm = DATE_GET_MINUTE(utcself);
  5509. ss = DATE_GET_SECOND(utcself);
  5510. Py_DECREF(utcself);
  5511. return build_struct_time(y, m, d, hh, mm, ss, 0);
  5512. }
  5513. /* Pickle support, a simple use of __reduce__. */
  5514. /* Let basestate be the non-tzinfo data string.
  5515. * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
  5516. * So it's a tuple in any (non-error) case.
  5517. * __getstate__ isn't exposed.
  5518. */
  5519. static PyObject *
  5520. datetime_getstate(PyDateTime_DateTime *self, int proto)
  5521. {
  5522. PyObject *basestate;
  5523. PyObject *result = NULL;
  5524. basestate = PyBytes_FromStringAndSize((char *)self->data,
  5525. _PyDateTime_DATETIME_DATASIZE);
  5526. if (basestate != NULL) {
  5527. if (proto > 3 && DATE_GET_FOLD(self))
  5528. /* Set the first bit of the third byte */
  5529. PyBytes_AS_STRING(basestate)[2] |= (1 << 7);
  5530. if (! HASTZINFO(self) || self->tzinfo == Py_None)
  5531. result = PyTuple_Pack(1, basestate);
  5532. else
  5533. result = PyTuple_Pack(2, basestate, self->tzinfo);
  5534. Py_DECREF(basestate);
  5535. }
  5536. return result;
  5537. }
  5538. static PyObject *
  5539. datetime_reduce_ex(PyDateTime_DateTime *self, PyObject *args)
  5540. {
  5541. int proto;
  5542. if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto))
  5543. return NULL;
  5544. return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, proto));
  5545. }
  5546. static PyObject *
  5547. datetime_reduce(PyDateTime_DateTime *self, PyObject *arg)
  5548. {
  5549. return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, 2));
  5550. }
  5551. static PyMethodDef datetime_methods[] = {
  5552. /* Class methods: */
  5553. DATETIME_DATETIME_NOW_METHODDEF
  5554. {"utcnow", (PyCFunction)datetime_utcnow,
  5555. METH_NOARGS | METH_CLASS,
  5556. PyDoc_STR("Return a new datetime representing UTC day and time.")},
  5557. {"fromtimestamp", (PyCFunction)(void(*)(void))datetime_fromtimestamp,
  5558. METH_VARARGS | METH_KEYWORDS | METH_CLASS,
  5559. PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")},
  5560. {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
  5561. METH_VARARGS | METH_CLASS,
  5562. PyDoc_STR("Construct a naive UTC datetime from a POSIX timestamp.")},
  5563. {"strptime", (PyCFunction)datetime_strptime,
  5564. METH_VARARGS | METH_CLASS,
  5565. PyDoc_STR("string, format -> new datetime parsed from a string "
  5566. "(like time.strptime()).")},
  5567. {"combine", (PyCFunction)(void(*)(void))datetime_combine,
  5568. METH_VARARGS | METH_KEYWORDS | METH_CLASS,
  5569. PyDoc_STR("date, time -> datetime with same date and time fields")},
  5570. {"fromisoformat", (PyCFunction)datetime_fromisoformat,
  5571. METH_O | METH_CLASS,
  5572. PyDoc_STR("string -> datetime from datetime.isoformat() output")},
  5573. /* Instance methods: */
  5574. {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
  5575. PyDoc_STR("Return date object with same year, month and day.")},
  5576. {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
  5577. PyDoc_STR("Return time object with same time but with tzinfo=None.")},
  5578. {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS,
  5579. PyDoc_STR("Return time object with same time and tzinfo.")},
  5580. {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
  5581. PyDoc_STR("Return ctime() style string.")},
  5582. {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
  5583. PyDoc_STR("Return time tuple, compatible with time.localtime().")},
  5584. {"timestamp", (PyCFunction)datetime_timestamp, METH_NOARGS,
  5585. PyDoc_STR("Return POSIX timestamp as float.")},
  5586. {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS,
  5587. PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
  5588. {"isoformat", (PyCFunction)(void(*)(void))datetime_isoformat, METH_VARARGS | METH_KEYWORDS,
  5589. PyDoc_STR("[sep] -> string in ISO 8601 format, "
  5590. "YYYY-MM-DDT[HH[:MM[:SS[.mmm[uuu]]]]][+HH:MM].\n"
  5591. "sep is used to separate the year from the time, and "
  5592. "defaults to 'T'.\n"
  5593. "The optional argument timespec specifies the number "
  5594. "of additional terms\nof the time to include. Valid "
  5595. "options are 'auto', 'hours', 'minutes',\n'seconds', "
  5596. "'milliseconds' and 'microseconds'.\n")},
  5597. {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS,
  5598. PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
  5599. {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS,
  5600. PyDoc_STR("Return self.tzinfo.tzname(self).")},
  5601. {"dst", (PyCFunction)datetime_dst, METH_NOARGS,
  5602. PyDoc_STR("Return self.tzinfo.dst(self).")},
  5603. {"replace", (PyCFunction)(void(*)(void))datetime_replace, METH_VARARGS | METH_KEYWORDS,
  5604. PyDoc_STR("Return datetime with new specified fields.")},
  5605. {"astimezone", (PyCFunction)(void(*)(void))datetime_astimezone, METH_VARARGS | METH_KEYWORDS,
  5606. PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
  5607. {"__reduce_ex__", (PyCFunction)datetime_reduce_ex, METH_VARARGS,
  5608. PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")},
  5609. {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS,
  5610. PyDoc_STR("__reduce__() -> (cls, state)")},
  5611. {NULL, NULL}
  5612. };
  5613. static const char datetime_doc[] =
  5614. PyDoc_STR("datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\
  5615. \n\
  5616. The year, month and day arguments are required. tzinfo may be None, or an\n\
  5617. instance of a tzinfo subclass. The remaining arguments may be ints.\n");
  5618. static PyNumberMethods datetime_as_number = {
  5619. datetime_add, /* nb_add */
  5620. datetime_subtract, /* nb_subtract */
  5621. 0, /* nb_multiply */
  5622. 0, /* nb_remainder */
  5623. 0, /* nb_divmod */
  5624. 0, /* nb_power */
  5625. 0, /* nb_negative */
  5626. 0, /* nb_positive */
  5627. 0, /* nb_absolute */
  5628. 0, /* nb_bool */
  5629. };
  5630. static PyTypeObject PyDateTime_DateTimeType = {
  5631. PyVarObject_HEAD_INIT(NULL, 0)
  5632. "datetime.datetime", /* tp_name */
  5633. sizeof(PyDateTime_DateTime), /* tp_basicsize */
  5634. 0, /* tp_itemsize */
  5635. (destructor)datetime_dealloc, /* tp_dealloc */
  5636. 0, /* tp_vectorcall_offset */
  5637. 0, /* tp_getattr */
  5638. 0, /* tp_setattr */
  5639. 0, /* tp_as_async */
  5640. (reprfunc)datetime_repr, /* tp_repr */
  5641. &datetime_as_number, /* tp_as_number */
  5642. 0, /* tp_as_sequence */
  5643. 0, /* tp_as_mapping */
  5644. (hashfunc)datetime_hash, /* tp_hash */
  5645. 0, /* tp_call */
  5646. (reprfunc)datetime_str, /* tp_str */
  5647. PyObject_GenericGetAttr, /* tp_getattro */
  5648. 0, /* tp_setattro */
  5649. 0, /* tp_as_buffer */
  5650. Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  5651. datetime_doc, /* tp_doc */
  5652. 0, /* tp_traverse */
  5653. 0, /* tp_clear */
  5654. datetime_richcompare, /* tp_richcompare */
  5655. 0, /* tp_weaklistoffset */
  5656. 0, /* tp_iter */
  5657. 0, /* tp_iternext */
  5658. datetime_methods, /* tp_methods */
  5659. 0, /* tp_members */
  5660. datetime_getset, /* tp_getset */
  5661. 0, /* tp_base; filled in
  5662. PyInit__datetime */
  5663. 0, /* tp_dict */
  5664. 0, /* tp_descr_get */
  5665. 0, /* tp_descr_set */
  5666. 0, /* tp_dictoffset */
  5667. 0, /* tp_init */
  5668. datetime_alloc, /* tp_alloc */
  5669. datetime_new, /* tp_new */
  5670. 0, /* tp_free */
  5671. };
  5672. /* ---------------------------------------------------------------------------
  5673. * Module methods and initialization.
  5674. */
  5675. static PyMethodDef module_methods[] = {
  5676. {NULL, NULL}
  5677. };
  5678. /* C API. Clients get at this via PyDateTime_IMPORT, defined in
  5679. * datetime.h.
  5680. */
  5681. static PyDateTime_CAPI CAPI = {
  5682. &PyDateTime_DateType,
  5683. &PyDateTime_DateTimeType,
  5684. &PyDateTime_TimeType,
  5685. &PyDateTime_DeltaType,
  5686. &PyDateTime_TZInfoType,
  5687. NULL, // PyDatetime_TimeZone_UTC not initialized yet
  5688. new_date_ex,
  5689. new_datetime_ex,
  5690. new_time_ex,
  5691. new_delta_ex,
  5692. new_timezone,
  5693. datetime_fromtimestamp,
  5694. datetime_date_fromtimestamp_capi,
  5695. new_datetime_ex2,
  5696. new_time_ex2
  5697. };
  5698. static struct PyModuleDef datetimemodule = {
  5699. PyModuleDef_HEAD_INIT,
  5700. "_datetime",
  5701. "Fast implementation of the datetime type.",
  5702. -1,
  5703. module_methods,
  5704. NULL,
  5705. NULL,
  5706. NULL,
  5707. NULL
  5708. };
  5709. PyMODINIT_FUNC
  5710. PyInit__datetime(void)
  5711. {
  5712. PyObject *m; /* a module object */
  5713. PyObject *d; /* its dict */
  5714. PyObject *x;
  5715. PyObject *delta;
  5716. m = PyModule_Create(&datetimemodule);
  5717. if (m == NULL)
  5718. return NULL;
  5719. // `&...` is not a constant expression according to a strict reading
  5720. // of C standards. Fill tp_base at run-time rather than statically.
  5721. // See https://bugs.python.org/issue40777
  5722. PyDateTime_IsoCalendarDateType.tp_base = &PyTuple_Type;
  5723. PyDateTime_TimeZoneType.tp_base = &PyDateTime_TZInfoType;
  5724. PyDateTime_DateTimeType.tp_base = &PyDateTime_DateType;
  5725. PyTypeObject *types[] = {
  5726. &PyDateTime_DateType,
  5727. &PyDateTime_DateTimeType,
  5728. &PyDateTime_TimeType,
  5729. &PyDateTime_DeltaType,
  5730. &PyDateTime_TZInfoType,
  5731. &PyDateTime_TimeZoneType,
  5732. };
  5733. for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) {
  5734. if (PyModule_AddType(m, types[i]) < 0) {
  5735. return NULL;
  5736. }
  5737. }
  5738. if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) {
  5739. return NULL;
  5740. }
  5741. Py_INCREF(&PyDateTime_IsoCalendarDateType);
  5742. /* timedelta values */
  5743. d = PyDateTime_DeltaType.tp_dict;
  5744. x = new_delta(0, 0, 1, 0);
  5745. if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
  5746. return NULL;
  5747. Py_DECREF(x);
  5748. x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
  5749. if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
  5750. return NULL;
  5751. Py_DECREF(x);
  5752. x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
  5753. if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
  5754. return NULL;
  5755. Py_DECREF(x);
  5756. /* date values */
  5757. d = PyDateTime_DateType.tp_dict;
  5758. x = new_date(1, 1, 1);
  5759. if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
  5760. return NULL;
  5761. Py_DECREF(x);
  5762. x = new_date(MAXYEAR, 12, 31);
  5763. if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
  5764. return NULL;
  5765. Py_DECREF(x);
  5766. x = new_delta(1, 0, 0, 0);
  5767. if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
  5768. return NULL;
  5769. Py_DECREF(x);
  5770. /* time values */
  5771. d = PyDateTime_TimeType.tp_dict;
  5772. x = new_time(0, 0, 0, 0, Py_None, 0);
  5773. if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
  5774. return NULL;
  5775. Py_DECREF(x);
  5776. x = new_time(23, 59, 59, 999999, Py_None, 0);
  5777. if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
  5778. return NULL;
  5779. Py_DECREF(x);
  5780. x = new_delta(0, 0, 1, 0);
  5781. if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
  5782. return NULL;
  5783. Py_DECREF(x);
  5784. /* datetime values */
  5785. d = PyDateTime_DateTimeType.tp_dict;
  5786. x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0);
  5787. if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
  5788. return NULL;
  5789. Py_DECREF(x);
  5790. x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None, 0);
  5791. if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
  5792. return NULL;
  5793. Py_DECREF(x);
  5794. x = new_delta(0, 0, 1, 0);
  5795. if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
  5796. return NULL;
  5797. Py_DECREF(x);
  5798. /* timezone values */
  5799. d = PyDateTime_TimeZoneType.tp_dict;
  5800. delta = new_delta(0, 0, 0, 0);
  5801. if (delta == NULL)
  5802. return NULL;
  5803. x = create_timezone(delta, NULL);
  5804. Py_DECREF(delta);
  5805. if (x == NULL || PyDict_SetItemString(d, "utc", x) < 0)
  5806. return NULL;
  5807. PyDateTime_TimeZone_UTC = x;
  5808. CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC;
  5809. /* bpo-37642: These attributes are rounded to the nearest minute for backwards
  5810. * compatibility, even though the constructor will accept a wider range of
  5811. * values. This may change in the future.*/
  5812. delta = new_delta(-1, 60, 0, 1); /* -23:59 */
  5813. if (delta == NULL)
  5814. return NULL;
  5815. x = create_timezone(delta, NULL);
  5816. Py_DECREF(delta);
  5817. if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
  5818. return NULL;
  5819. Py_DECREF(x);
  5820. delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */
  5821. if (delta == NULL)
  5822. return NULL;
  5823. x = create_timezone(delta, NULL);
  5824. Py_DECREF(delta);
  5825. if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
  5826. return NULL;
  5827. Py_DECREF(x);
  5828. /* Epoch */
  5829. PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0,
  5830. PyDateTime_TimeZone_UTC, 0);
  5831. if (PyDateTime_Epoch == NULL)
  5832. return NULL;
  5833. /* module initialization */
  5834. PyModule_AddIntMacro(m, MINYEAR);
  5835. PyModule_AddIntMacro(m, MAXYEAR);
  5836. x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
  5837. if (x == NULL)
  5838. return NULL;
  5839. PyModule_AddObject(m, "datetime_CAPI", x);
  5840. /* A 4-year cycle has an extra leap day over what we'd get from
  5841. * pasting together 4 single years.
  5842. */
  5843. Py_BUILD_ASSERT(DI4Y == 4 * 365 + 1);
  5844. assert(DI4Y == days_before_year(4+1));
  5845. /* Similarly, a 400-year cycle has an extra leap day over what we'd
  5846. * get from pasting together 4 100-year cycles.
  5847. */
  5848. Py_BUILD_ASSERT(DI400Y == 4 * DI100Y + 1);
  5849. assert(DI400Y == days_before_year(400+1));
  5850. /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
  5851. * pasting together 25 4-year cycles.
  5852. */
  5853. Py_BUILD_ASSERT(DI100Y == 25 * DI4Y - 1);
  5854. assert(DI100Y == days_before_year(100+1));
  5855. us_per_ms = PyLong_FromLong(1000);
  5856. us_per_second = PyLong_FromLong(1000000);
  5857. us_per_minute = PyLong_FromLong(60000000);
  5858. seconds_per_day = PyLong_FromLong(24 * 3600);
  5859. if (us_per_ms == NULL || us_per_second == NULL ||
  5860. us_per_minute == NULL || seconds_per_day == NULL)
  5861. return NULL;
  5862. /* The rest are too big for 32-bit ints, but even
  5863. * us_per_week fits in 40 bits, so doubles should be exact.
  5864. */
  5865. us_per_hour = PyLong_FromDouble(3600000000.0);
  5866. us_per_day = PyLong_FromDouble(86400000000.0);
  5867. us_per_week = PyLong_FromDouble(604800000000.0);
  5868. if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
  5869. return NULL;
  5870. return m;
  5871. }
  5872. /* ---------------------------------------------------------------------------
  5873. Some time zone algebra. For a datetime x, let
  5874. x.n = x stripped of its timezone -- its naive time.
  5875. x.o = x.utcoffset(), and assuming that doesn't raise an exception or
  5876. return None
  5877. x.d = x.dst(), and assuming that doesn't raise an exception or
  5878. return None
  5879. x.s = x's standard offset, x.o - x.d
  5880. Now some derived rules, where k is a duration (timedelta).
  5881. 1. x.o = x.s + x.d
  5882. This follows from the definition of x.s.
  5883. 2. If x and y have the same tzinfo member, x.s = y.s.
  5884. This is actually a requirement, an assumption we need to make about
  5885. sane tzinfo classes.
  5886. 3. The naive UTC time corresponding to x is x.n - x.o.
  5887. This is again a requirement for a sane tzinfo class.
  5888. 4. (x+k).s = x.s
  5889. This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
  5890. 5. (x+k).n = x.n + k
  5891. Again follows from how arithmetic is defined.
  5892. Now we can explain tz.fromutc(x). Let's assume it's an interesting case
  5893. (meaning that the various tzinfo methods exist, and don't blow up or return
  5894. None when called).
  5895. The function wants to return a datetime y with timezone tz, equivalent to x.
  5896. x is already in UTC.
  5897. By #3, we want
  5898. y.n - y.o = x.n [1]
  5899. The algorithm starts by attaching tz to x.n, and calling that y. So
  5900. x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
  5901. becomes true; in effect, we want to solve [2] for k:
  5902. (y+k).n - (y+k).o = x.n [2]
  5903. By #1, this is the same as
  5904. (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
  5905. By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
  5906. Substituting that into [3],
  5907. x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
  5908. k - (y+k).s - (y+k).d = 0; rearranging,
  5909. k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
  5910. k = y.s - (y+k).d
  5911. On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
  5912. approximate k by ignoring the (y+k).d term at first. Note that k can't be
  5913. very large, since all offset-returning methods return a duration of magnitude
  5914. less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
  5915. be 0, so ignoring it has no consequence then.
  5916. In any case, the new value is
  5917. z = y + y.s [4]
  5918. It's helpful to step back at look at [4] from a higher level: it's simply
  5919. mapping from UTC to tz's standard time.
  5920. At this point, if
  5921. z.n - z.o = x.n [5]
  5922. we have an equivalent time, and are almost done. The insecurity here is
  5923. at the start of daylight time. Picture US Eastern for concreteness. The wall
  5924. time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
  5925. sense then. The docs ask that an Eastern tzinfo class consider such a time to
  5926. be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
  5927. on the day DST starts. We want to return the 1:MM EST spelling because that's
  5928. the only spelling that makes sense on the local wall clock.
  5929. In fact, if [5] holds at this point, we do have the standard-time spelling,
  5930. but that takes a bit of proof. We first prove a stronger result. What's the
  5931. difference between the LHS and RHS of [5]? Let
  5932. diff = x.n - (z.n - z.o) [6]
  5933. Now
  5934. z.n = by [4]
  5935. (y + y.s).n = by #5
  5936. y.n + y.s = since y.n = x.n
  5937. x.n + y.s = since z and y are have the same tzinfo member,
  5938. y.s = z.s by #2
  5939. x.n + z.s
  5940. Plugging that back into [6] gives
  5941. diff =
  5942. x.n - ((x.n + z.s) - z.o) = expanding
  5943. x.n - x.n - z.s + z.o = cancelling
  5944. - z.s + z.o = by #2
  5945. z.d
  5946. So diff = z.d.
  5947. If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
  5948. spelling we wanted in the endcase described above. We're done. Contrarily,
  5949. if z.d = 0, then we have a UTC equivalent, and are also done.
  5950. If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
  5951. add to z (in effect, z is in tz's standard time, and we need to shift the
  5952. local clock into tz's daylight time).
  5953. Let
  5954. z' = z + z.d = z + diff [7]
  5955. and we can again ask whether
  5956. z'.n - z'.o = x.n [8]
  5957. If so, we're done. If not, the tzinfo class is insane, according to the
  5958. assumptions we've made. This also requires a bit of proof. As before, let's
  5959. compute the difference between the LHS and RHS of [8] (and skipping some of
  5960. the justifications for the kinds of substitutions we've done several times
  5961. already):
  5962. diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
  5963. x.n - (z.n + diff - z'.o) = replacing diff via [6]
  5964. x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
  5965. x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
  5966. - z.n + z.n - z.o + z'.o = cancel z.n
  5967. - z.o + z'.o = #1 twice
  5968. -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
  5969. z'.d - z.d
  5970. So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
  5971. we've found the UTC-equivalent so are done. In fact, we stop with [7] and
  5972. return z', not bothering to compute z'.d.
  5973. How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
  5974. a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
  5975. would have to change the result dst() returns: we start in DST, and moving
  5976. a little further into it takes us out of DST.
  5977. There isn't a sane case where this can happen. The closest it gets is at
  5978. the end of DST, where there's an hour in UTC with no spelling in a hybrid
  5979. tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
  5980. that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
  5981. UTC) because the docs insist on that, but 0:MM is taken as being in daylight
  5982. time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
  5983. clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
  5984. standard time. Since that's what the local clock *does*, we want to map both
  5985. UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
  5986. in local time, but so it goes -- it's the way the local clock works.
  5987. When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
  5988. so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
  5989. z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
  5990. (correctly) concludes that z' is not UTC-equivalent to x.
  5991. Because we know z.d said z was in daylight time (else [5] would have held and
  5992. we would have stopped then), and we know z.d != z'.d (else [8] would have held
  5993. and we would have stopped then), and there are only 2 possible values dst() can
  5994. return in Eastern, it follows that z'.d must be 0 (which it is in the example,
  5995. but the reasoning doesn't depend on the example -- it depends on there being
  5996. two possible dst() outcomes, one zero and the other non-zero). Therefore
  5997. z' must be in standard time, and is the spelling we want in this case.
  5998. Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
  5999. concerned (because it takes z' as being in standard time rather than the
  6000. daylight time we intend here), but returning it gives the real-life "local
  6001. clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
  6002. tz.
  6003. When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
  6004. the 1:MM standard time spelling we want.
  6005. So how can this break? One of the assumptions must be violated. Two
  6006. possibilities:
  6007. 1) [2] effectively says that y.s is invariant across all y belong to a given
  6008. time zone. This isn't true if, for political reasons or continental drift,
  6009. a region decides to change its base offset from UTC.
  6010. 2) There may be versions of "double daylight" time where the tail end of
  6011. the analysis gives up a step too early. I haven't thought about that
  6012. enough to say.
  6013. In any case, it's clear that the default fromutc() is strong enough to handle
  6014. "almost all" time zones: so long as the standard offset is invariant, it
  6015. doesn't matter if daylight time transition points change from year to year, or
  6016. if daylight time is skipped in some years; it doesn't matter how large or
  6017. small dst() may get within its bounds; and it doesn't even matter if some
  6018. perverse time zone returns a negative dst()). So a breaking case must be
  6019. pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
  6020. --------------------------------------------------------------------------- */