int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_res_t hint)
{
int i;
- fr_unix_time_t t;
int64_t tmp;
struct tm *tm, s_tm;
char buf[64];
*/
tmp = strtoul(date_str, &tail, 10);
if (*tail == '\0') {
- switch (hint) {
- case FR_TIME_RES_SEC:
- t = fr_unix_time_from_sec(tmp);
- break;
-
- case FR_TIME_RES_MSEC:
- t = fr_unix_time_from_msec(tmp);
- break;
-
- case FR_TIME_RES_USEC:
- t = fr_unix_time_from_usec(tmp);
- break;
-
- case FR_TIME_RES_NSEC:
- t = fr_unix_time_from_nsec(tmp);
- break;
-
- default:
- fr_strerror_printf("Invalid hint %d for time delta", hint);
- return -1;
- }
-
- *date = t;
+ *date = fr_unix_time_from_nsec(fr_time_scale(tmp, hint));
return 0;
}
goto parse_precision;
}
+ /*
+ * The input is just a number. Scale and clamp it as appropriate.
+ */
+ if (!*end) {
+ *out = fr_time_delta_from_nsec(fr_time_scale(sec, hint));
+ return 0;
+ }
+
/*
* Decimal number
*/
return 0;
}
+
+/** Scale an input time to NSEC, clamping it at max / min.
+ *
+ * @param t input time / time delta
+ * @param hint time resolution hint
+ * @return
+ * - INT64_MIN on underflow
+ * - 0 on invalid hint
+ * - INT64_MAX on overflow
+ * - otherwise a valid number, multiplied by the relevant scale,
+ * so that the result is in nanoseconds.
+ */
+int64_t fr_time_scale(int64_t t, fr_time_res_t hint)
+{
+ int64_t scale;
+
+ switch (hint) {
+ case FR_TIME_RES_SEC:
+ scale = NSEC;
+ break;
+
+ case FR_TIME_RES_MSEC:
+ scale = 1000000;
+ break;
+
+ case FR_TIME_RES_USEC:
+ scale = 1000;
+ break;
+
+ case FR_TIME_RES_NSEC:
+ return t;
+
+ default:
+ return 0;
+ }
+
+ if (t < 0) {
+ if (t < (INT64_MIN / scale)) {
+ return INT64_MIN;
+ }
+ } else if (t > 0) {
+ if (t > (INT64_MAX / scale)) {
+ return INT64_MAX;
+ }
+ }
+
+ return t * scale;
+}
int fr_time_start(void);
int fr_time_sync(void);
+int64_t fr_time_scale(int64_t t, fr_time_res_t hint);
+
int fr_time_delta_from_time_zone(char const *tz, fr_time_delta_t *delta) CC_HINT(nonnull);
int fr_time_delta_from_str(fr_time_delta_t *out, char const *in, fr_time_res_t hint) CC_HINT(nonnull);
date = tmp;
}
- switch (precision) {
- case FR_TIME_RES_SEC: /* external seconds, internal nanoseconds */
- dst->vb_time_delta = fr_time_delta_from_sec(date);
- break;
-
- case FR_TIME_RES_CSEC:
- dst->vb_time_delta = fr_time_delta_from_csec(date);
- break;
-
- case FR_TIME_RES_MSEC:
- dst->vb_time_delta = fr_time_delta_from_msec(date);
- break;
-
- case FR_TIME_RES_USEC:
- dst->vb_time_delta = fr_time_delta_from_usec(date);
- break;
-
- case FR_TIME_RES_NSEC:
- dst->vb_time_delta = fr_time_delta_wrap(date);
- break;
- }
-
+ dst->vb_time_delta = fr_time_delta_wrap(fr_time_scale(date, precision));
}
break;