Close #14180: Factorize code to convert a number of seconds to time_t, timeval or timespec

time.ctime(), gmtime(), time.localtime(), datetime.date.fromtimestamp(),
datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now
raises an OverflowError, instead of a ValueError, if the timestamp does not fit
in time_t.

datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now
round microseconds towards zero instead of rounding to nearest with ties going
away from zero.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 628b0b9..c7d48b0 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -3540,31 +3540,6 @@
 #endif /* HAVE_UNAME */
 
 
-static int
-extract_time(PyObject *t, time_t* sec, long* nsec)
-{
-    time_t intval;
-    if (PyFloat_Check(t)) {
-        double d = PyFloat_AsDouble(t);
-        double mod;
-        *sec = (time_t)d;
-        mod = fmod(d, 1.0);
-        mod *= 1e9;
-        *nsec = (long)mod;
-        return 0;
-    }
-#if SIZEOF_TIME_T > SIZEOF_LONG
-    intval = PyLong_AsUnsignedLongLongMask(t);
-#else
-    intval = PyLong_AsLong(t);
-#endif
-    if (intval == -1 && PyErr_Occurred())
-        return -1;
-    *sec = intval;
-    *nsec = 0;
-    return 0;
-}
-
 PyDoc_STRVAR(posix_utime__doc__,
 "utime(path[, (atime, mtime)])\n\
 Set the access and modified time of the file to the given values.\n\
@@ -3633,12 +3608,12 @@
         goto done;
     }
     else {
-        if (extract_time(PyTuple_GET_ITEM(arg, 0),
-                         &atimesec, &ansec) == -1)
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
+                                     &atimesec, &ansec) == -1)
             goto done;
         time_t_to_FILE_TIME(atimesec, ansec, &atime);
-        if (extract_time(PyTuple_GET_ITEM(arg, 1),
-                         &mtimesec, &mnsec) == -1)
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
+                                     &mtimesec, &mnsec) == -1)
             goto done;
         time_t_to_FILE_TIME(mtimesec, mnsec, &mtime);
     }
@@ -3681,13 +3656,13 @@
         return NULL;
     }
     else {
-        if (extract_time(PyTuple_GET_ITEM(arg, 0),
-                         &atime, &ansec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
+                                     &atime, &ansec) == -1) {
             Py_DECREF(opath);
             return NULL;
         }
-        if (extract_time(PyTuple_GET_ITEM(arg, 1),
-                         &mtime, &mnsec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
+                                     &mtime, &mnsec) == -1) {
             Py_DECREF(opath);
             return NULL;
         }
@@ -3763,12 +3738,12 @@
         return NULL;
     }
     else {
-        if (extract_time(PyTuple_GET_ITEM(arg, 0),
-                &atime, &ansec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
+                                     &atime, &ansec) == -1) {
             return NULL;
         }
-        if (extract_time(PyTuple_GET_ITEM(arg, 1),
-                &mtime, &mnsec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
+                                     &mtime, &mnsec) == -1) {
             return NULL;
         }
         Py_BEGIN_ALLOW_THREADS
@@ -3829,13 +3804,13 @@
         return NULL;
     }
     else {
-        if (extract_time(PyTuple_GET_ITEM(arg, 0),
-                &atime, &ansec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
+                                     &atime, &ansec) == -1) {
             Py_DECREF(opath);
             return NULL;
         }
-        if (extract_time(PyTuple_GET_ITEM(arg, 1),
-                &mtime, &mnsec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
+                                     &mtime, &mnsec) == -1) {
             Py_DECREF(opath);
             return NULL;
         }
@@ -9610,13 +9585,13 @@
         return NULL;
     }
     else {
-        if (extract_time(PyTuple_GET_ITEM(arg, 0),
-                         &atime, &ansec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
+                                     &atime, &ansec) == -1) {
             Py_DECREF(opath);
             return NULL;
         }
-        if (extract_time(PyTuple_GET_ITEM(arg, 1),
-                         &mtime, &mnsec) == -1) {
+        if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
+                                     &mtime, &mnsec) == -1) {
             Py_DECREF(opath);
             return NULL;
         }