diff --git a/include/time.h b/include/time.h
index 5afb12305e..63cc855749 100644
--- a/include/time.h
+++ b/include/time.h
@@ -125,6 +125,12 @@ extern char * __strptime_internal (const char *rp, const char *fmt,
 				   struct tm *tm, void *statep,
 				   locale_t locparam) attribute_hidden;
 
+#if __TIMESIZE == 64
+# define __difftime64 __difftime
+#else
+extern double __difftime64 (__time64_t time1, __time64_t time0);
+#endif
+
 extern double __difftime (time_t time1, time_t time0);
 
 /* Use in the clock_* functions.  Size of the field representing the
diff --git a/time/difftime.c b/time/difftime.c
index 7c5dd9898b..fbc7ad9d57 100644
--- a/time/difftime.c
+++ b/time/difftime.c
@@ -30,87 +30,75 @@
 /* Return the difference between TIME1 and TIME0, where TIME0 <= TIME1.
    time_t is known to be an integer type.  */
 
-static double
-subtract (time_t time1, time_t time0)
+static double subtract (__time64_t time1, __time64_t time0)
 {
-  if (! TYPE_SIGNED (time_t))
-    return time1 - time0;
-  else
-    {
-      /* Optimize the common special cases where time_t
-	 can be converted to uintmax_t without losing information.  */
-      uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0;
-      double delta = dt;
-
-      if (UINTMAX_MAX / 2 < INTMAX_MAX)
-	{
-	  /* This is a rare host where uintmax_t has padding bits, and possibly
-	     information was lost when converting time_t to uintmax_t.
-	     Check for overflow by comparing dt/2 to (time1/2 - time0/2).
-	     Overflow occurred if they differ by more than a small slop.
-	     Thanks to Clive D.W. Feather for detailed technical advice about
-	     hosts with padding bits.
+  /* Optimize the common special cases where __time64_t
+ can be converted to uintmax_t without losing information.  */
+  uintmax_t dt = (uintmax_t) time1 - (uintmax_t) time0;
+  double delta = dt;
 
-	     In the following code the "h" prefix means half.  By range
-	     analysis, we have:
+  if (UINTMAX_MAX / 2 < INTMAX_MAX)
+{
+  /* This is a rare host where uintmax_t has padding bits, and possibly
+	 information was lost when converting time_t to uintmax_t.
+	 Check for overflow by comparing dt/2 to (time1/2 - time0/2).
+	 Overflow occurred if they differ by more than a small slop.
+	 Thanks to Clive D.W. Feather for detailed technical advice about
+	 hosts with padding bits.
 
-                  -0.5 <= ht1 - 0.5*time1 <= 0.5
-                  -0.5 <= ht0 - 0.5*time0 <= 0.5
-                  -1.0 <= dht - 0.5*(time1 - time0) <= 1.0
+	 In the following code the "h" prefix means half.  By range
+	 analysis, we have:
 
-             If overflow has not occurred, we also have:
+			  -0.5 <= ht1 - 0.5*time1 <= 0.5
+			  -0.5 <= ht0 - 0.5*time0 <= 0.5
+			  -1.0 <= dht - 0.5*(time1 - time0) <= 1.0
 
-                  -0.5 <= hdt - 0.5*(time1 - time0) <= 0
-                  -1.0 <= dht - hdt <= 1.5
+		 If overflow has not occurred, we also have:
 
-             and since dht - hdt is an integer, we also have:
+			  -0.5 <= hdt - 0.5*(time1 - time0) <= 0
+			  -1.0 <= dht - hdt <= 1.5
 
-                  -1 <= dht - hdt <= 1
+		 and since dht - hdt is an integer, we also have:
 
-             or equivalently:
+			  -1 <= dht - hdt <= 1
 
-                  0 <= dht - hdt + 1 <= 2
+		 or equivalently:
 
-             In the above analysis, all the operators have their exact
-             mathematical semantics, not C semantics.  However, dht - hdt +
-             1 is unsigned in C, so it need not be compared to zero.  */
+			  0 <= dht - hdt + 1 <= 2
 
-	  uintmax_t hdt = dt / 2;
-	  time_t ht1 = time1 / 2;
-	  time_t ht0 = time0 / 2;
-	  time_t dht = ht1 - ht0;
+		 In the above analysis, all the operators have their exact
+		 mathematical semantics, not C semantics.  However, dht - hdt +
+		 1 is unsigned in C, so it need not be compared to zero.  */
 
-	  if (2 < dht - hdt + 1)
-	    {
-	      /* Repair delta overflow.
+  uintmax_t hdt = dt / 2;
+  __time64_t ht1 = time1 / 2;
+  __time64_t ht0 = time0 / 2;
+  __time64_t dht = ht1 - ht0;
 
-		 The following expression contains a second rounding,
-		 so the result may not be the closest to the true answer.
-		 This problem occurs only with very large differences.
-		 It's too painful to fix this portably.  */
+  if (2 < dht - hdt + 1)
+	{
+	  /* Repair delta overflow.
 
-	      delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2);
-	    }
+	 The following expression contains a second rounding,
+	 so the result may not be the closest to the true answer.
+	 This problem occurs only with very large differences.
+	 It's too painful to fix this portably.  */
+
+	  delta = dt + 2.0L * (UINTMAX_MAX - UINTMAX_MAX / 2);
 	}
+}
 
-      return delta;
-    }
+  return delta;
 }
 
 /* Return the difference between TIME1 and TIME0.  */
 double
-__difftime (time_t time1, time_t time0)
+__difftime64 (__time64_t time1, __time64_t time0)
 {
-  /* Convert to double and then subtract if no double-rounding error could
+  /* Convert to long double and then subtract if no double-rounding error could
      result.  */
 
-  if (TYPE_BITS (time_t) <= DBL_MANT_DIG
-      || (TYPE_FLOATING (time_t) && sizeof (time_t) < sizeof (long double)))
-    return (double) time1 - (double) time0;
-
-  /* Likewise for long double.  */
-
-  if (TYPE_BITS (time_t) <= LDBL_MANT_DIG || TYPE_FLOATING (time_t))
+  if (TYPE_BITS (__time64_t) <= LDBL_MANT_DIG)
     return (long double) time1 - (long double) time0;
 
   /* Subtract the smaller integer from the larger, convert the difference to
@@ -118,4 +106,16 @@ __difftime (time_t time1, time_t time0)
 
   return time1 < time0 ? - subtract (time0, time1) : subtract (time1, time0);
 }
+
+#if __TIMESIZE != 64
+
+/* Return the difference between TIME1 and TIME0.  */
+double
+__difftime (time_t time1, time_t time0)
+{
+  return __difftime64 (time1, time0);
+}
+
+#endif
+
 strong_alias (__difftime, difftime)
