+ char *arg_lim;
+ bool negative = *arg == '-';
+
+ errno = 0;
+
+ if (ISDIGIT (arg[negative]))
+ {
+ if (negative)
+ {
+ intmax_t i = strtoimax (arg, &arg_lim, 10);
+ if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
+ return decode_time_range;
+ s = i;
+ }
+ else
+ {
+ uintmax_t i = strtoumax (arg, &arg_lim, 10);
+ if (TYPE_MAXIMUM (time_t) < i)
+ return decode_time_range;
+ s = i;
+ }
+
+ p = arg_lim;
+
+ if (errno == ERANGE)
+ return decode_time_range;
+
+ if (*p == '.')
+ {
+ int digits = 0;
+ bool trailing_nonzero = false;
+
+ while (ISDIGIT (*++p))
+ if (digits < LOG10_BILLION)
+ {
+ ns = 10 * ns + (*p - '0');
+ digits++;
+ }
+ else
+ trailing_nonzero |= *p != '0';
+
+ while (digits++ < LOG10_BILLION)
+ ns *= 10;
+
+ if (negative)
+ {
+ /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
+ I.e., truncate time stamps towards minus infinity while
+ converting them to internal form. */
+ ns += trailing_nonzero;
+ if (ns != 0)
+ {
+ if (s == TYPE_MINIMUM (time_t))
+ return decode_time_range;
+ s--;
+ ns = BILLION - ns;
+ }
+ }
+ }
+
+ if (! *p)
+ {
+ ts->tv_sec = s;
+ ts->tv_nsec = ns;
+ return decode_time_success;
+ }
+ }
+
+ return decode_time_bad_header;
+}
+
+static bool
+decode_time (struct timespec *ts, char const *arg, char const *keyword)
+{
+ switch (_decode_time (ts, arg, keyword))