26RCSID(
"$Id: 6c8e72e674a65b1324b5b59fb9b757612c27ad6b $")
28#include <freeradius-devel/autoconf.h>
29#include <freeradius-devel/util/time.h>
30#include <freeradius-devel/util/misc.h>
89static char const *
tz_names[2] = { NULL, NULL };
113 struct timespec ts_realtime, ts_monotime;
118 if (clock_gettime(CLOCK_REALTIME, &ts_realtime) < 0)
return -1;
126 now = ts_realtime.tv_sec;
134 isdst = (tm.tm_isdst != 0);
180 if ((strcmp(tz,
"UTC") == 0) ||
181 (strcmp(tz,
"GMT") == 0)) {
235 err =
"Invalid text, input should be an integer";
266 if (negative) integer = -(integer);
271 fr_sbuff_marker(&m_f, &our_in);
302#ifdef STATIC_ANALYZER
304 if (f > UINT64_MAX / 10)
break;
344 fr_sbuff_set_to_start(&our_in);
359 if (negative) tmp = -(tmp);
371 uint64_t hours, minutes, seconds;
376 fr_sbuff_marker(&m1, &our_in);
378 if (
fr_sbuff_out(&sberr, &seconds, &our_in) < 0)
goto num_error;
385 minutes = negative ? -(integer) : integer;
387 if (minutes > UINT16_MAX) {
389 fr_sbuff_set_to_start(&our_in);
396 hours = negative ? -(integer) : integer;
399 if (
fr_sbuff_out(&sberr, &seconds, &our_in) < 0)
goto num_error;
401 if (hours > UINT16_MAX) {
403 fr_sbuff_set_to_start(&our_in);
407 if (minutes > UINT16_MAX) {
418 if (!
fr_add(&integer, ((hours * 60) * 60) + (minutes * 60), seconds))
goto overflow;
423 if (negative) integer = -(integer);
440 if (overflow)
goto overflow;
461 if (slen < 0)
return slen;
490#define MOD(a,b) (((a<0) ? (-a) : (a))%(b))
515 while (*q ==
'0') *(q--) =
'\0';
556 if (len == 0)
return 0;
585 if (len == 0)
return 0;
629 "1us",
"10us",
"100us",
630 "1ms",
"10ms",
"100ms",
634static char const *
tab_string =
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
641 if (!prefix) prefix =
"elapsed";
643 prefix_len = strlen(prefix);
645 for (i = 0; i < 8; i++) {
648 if (!elapsed->
array[i])
continue;
650 len = prefix_len + 1 + strlen(
names[i]);
652 if (len >= (
size_t) (tab_offset * 8)) {
653 fprintf(fp,
"%s.%s %" PRIu64
"\n",
659 tabs = ((tab_offset * 8) - len);
663 fprintf(fp,
"%s.%s%.*s%" PRIu64
"\n",
674 static const uint16_t month_yday[12] = {0, 31, 59, 90, 120, 151,
675 181, 212, 243, 273, 304, 334};
687 year_adj = tm->tm_year + 4800 + 1900;
688 febs = year_adj - (tm->tm_mon < 2 ? 1 : 0);
689 leap_days = 1 + (febs / 4) - (febs / 100) + (febs / 400);
691 days = 365 * year_adj + leap_days + month_yday[tm->tm_mon] + tm->tm_mday - 1;
693#define CHECK(_x, _max) if ((tm->tm_ ## _x < 0) || (tm->tm_ ## _x >= _max)) tm->tm_ ## _x = _max - 1
713 (tm->tm_min * 60) + tm->tm_sec) - tm->tm_gmtoff);
752 if (t < (INT64_MIN / scale)) {
756 if (t > (INT64_MAX / scale)) {
772 if (**ptr ==
'\0')
return NULL;
774 while (**ptr && strchr(sep, **ptr)) (*ptr)++;
776 if (**ptr ==
'\0')
return NULL;
779 while (**ptr && strchr(sep, **ptr) == NULL) (*ptr)++;
781 if (**ptr !=
'\0') *(*ptr)++ =
'\0';
790static int get_part(
char **str,
int *date,
int min,
int max,
char term,
char const *
name)
794 if (!isdigit((
uint8_t) *p) || !isdigit((
uint8_t) p[1]))
return -1;
795 *date = (p[0] -
'0') * 10 + (p[1] -
'0');
825 "jan",
"feb",
"mar",
"apr",
"may",
"jun",
826 "jul",
"aug",
"sep",
"oct",
"nov",
"dec" };
854 tmp = strtoul(date_str, &tail, 10);
861 memset(tm, 0,
sizeof(*tm));
874 if ((tmp > 1900) && (tmp < 3000) && *tail ==
'-') {
875 unsigned long subseconds;
876 int tz, tz_hour, tz_min;
879 s_tm.tm_year = tmp - 1900;
881 if (
get_part(&p, &s_tm.tm_mon, 1, 12,
'-',
"month") < 0)
return -1;
884 if (
get_part(&p, &s_tm.tm_mday, 1, 31,
'T',
"day") < 0)
return -1;
885 if (
get_part(&p, &s_tm.tm_hour, 0, 23,
':',
"hour") < 0)
return -1;
886 if (
get_part(&p, &s_tm.tm_min, 0, 59,
':',
"minute") < 0)
return -1;
887 if (
get_part(&p, &s_tm.tm_sec, 0, 60,
'\0',
"seconds") < 0)
return -1;
891 subseconds = strtoul(p, &tail, 10);
892 if (subseconds >
NSEC) {
901 if ((tail - p) < 9) {
902 for (i = 0; i < 9 - (tail -p); i++) {
925 if ((*p !=
'+') && (*p !=
'-')) {
932 if (
get_part(&p, &tz_hour, 0, 23,
':',
"hour in time zone") < 0)
return -1;
933 if (
get_part(&p, &tz_min, 0, 59,
'\0',
"minute in time zone") < 0)
return -1;
953 tz = tz_hour * 3600 + tz_min;
954 if (*tail ==
'-') tz *= -1;
982 char const *tz = strstr(date_str,
"UTC");
986 my_str = talloc_strdup(NULL, date_str);
988 p = my_str + (tz - date_str);
991 p = strptime(my_str,
"%b %e %Y %H:%M:%S %Z", tm);
992 if (p && (*p ==
'\0')) {
1003 p = strptime(date_str,
"%b %e %Y %H:%M:%S %Z", tm);
1004 if (p && (*p ==
'\0')) {
1009 strlcpy(buf, date_str,
sizeof(buf));
1016 if (!f[0] || !f[1] || !f[2]) {
1037 for (i = 0; i < 3; i++) {
1038 if (strchr(f[i],
':')) {
1051 for (i = 0; i < 3; i++) {
1052 if (isalpha((
uint8_t) *f[i])) {
1062 for (j = 0; j < 12; j++) {
1072 if (tm->tm_mon == 12) {
1080 l = strtoul(f[1], &tail, 10);
1081 if ((l == ULONG_MAX) || (*tail !=
'\0')) {
1087 l = strtoul(f[2], &tail, 10);
1088 if ((l == ULONG_MAX) || (*tail !=
'\0')) {
1094 if (tm->tm_year >= 1900) {
1095 tm->tm_year -= 1900;
1102 if (tm->tm_mday < 1900) {
1111 tm->tm_year = tm->tm_mday - 1900;
1115 if (tm->tm_year > 10000) {
1123 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1133 f[1] = strchr(f[0],
':');
1141 f[2] = strchr(f[1],
':');
1144 tm->tm_sec = atoi(f[2]);
1147 tm->tm_hour = atoi(f[0]);
1148 tm->tm_min = atoi(f[1]);
1182 len = strftime(buf,
sizeof(buf),
"%Y-%m-%dT%H:%M:%S", &s_tm);
1226 if (s_tm.tm_gmtoff != 0) {
1229 hours = s_tm.tm_gmtoff / 3600;
1230 minutes = (s_tm.tm_gmtoff / 60) % 60;
static int const char * fmt
#define L(_str)
Helper for initialising arrays of string literals.
static size_t min(size_t x, size_t y)
#define fr_add(_out, _a, _b)
Adds two integers.
@ FR_SBUFF_PARSE_ERROR_NOT_FOUND
String does not contain a token matching the output type.
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
int strncasecmp(char *s1, char *s2, int n)
struct tm * gmtime_r(time_t const *l_clock, struct tm *result)
struct tm * localtime_r(time_t const *l_clock, struct tm *result)
bool fr_sbuff_is_terminal(fr_sbuff_t *in, fr_sbuff_term_t const *tt)
Efficient terminal string search.
fr_table_num_ordered_t const sbuff_parse_error_table[]
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def)
#define fr_sbuff_adv_past_zeros(_sbuff, _len, _tt)
#define FR_SBUFF_IN_CHAR_RETURN(_sbuff,...)
#define fr_sbuff_set(_dst, _src)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker)
#define FR_SBUFF_SET_RETURN(_dst, _src)
#define FR_SBUFF_IN_SPRINTF_RETURN(...)
#define FR_SBUFF(_sbuff_or_marker)
#define FR_SBUFF_IN_BSTRNCPY_RETURN(...)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_out(_err, _out, _in)
#define fr_sbuff_behind(_sbuff_or_marker)
#define fr_sbuff_extend_lowat(_status, _sbuff_or_marker, _lowat)
Set of terminal elements.
#define atomic_store_explicit(object, desired, order)
size_t strlcpy(char *dst, char const *src, size_t siz)
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
An element in an arbitrarily ordered array of name to num mappings.
static char * mystrtok(char **ptr, char const *sep)
void fr_time_elapsed_update(fr_time_elapsed_t *elapsed, fr_time_t start, fr_time_t end)
fr_unix_time_t fr_unix_time_from_tm(struct tm *tm)
static char const * tab_string
static const char * names[8]
int fr_time_sync(void)
Get a new fr_time_monotonic_to_realtime value.
static int get_part(char **str, int *date, int min, int max, char term, char const *name)
static long gmtoff[2]
from localtime_r(), tm_gmtoff
fr_table_num_ordered_t const fr_time_precision_table[]
size_t fr_time_strftime_local(fr_sbuff_t *out, fr_time_t time, char const *fmt)
Copy a time string (local timezone) to an sbuff.
fr_slen_t fr_time_delta_from_substr(fr_time_delta_t *out, fr_sbuff_t *in, fr_time_res_t hint, bool no_trailing, fr_sbuff_term_t const *tt)
Create fr_time_delta_t from a string.
int fr_time_delta_from_time_zone(char const *tz, fr_time_delta_t *delta)
Return time delta from the time zone.
fr_slen_t fr_time_delta_from_str(fr_time_delta_t *out, char const *in, size_t inlen, fr_time_res_t hint)
Create fr_time_delta_t from a string.
bool fr_time_is_dst(void)
Whether or not we're daylight savings.
void fr_time_elapsed_fprint(FILE *fp, fr_time_elapsed_t const *elapsed, char const *prefix, int tab_offset)
_Atomic int64_t fr_time_monotonic_to_realtime
difference between the two clocks
int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_res_t hint)
Convert string in various formats to a fr_unix_time_t.
int64_t fr_time_scale(int64_t t, fr_time_res_t hint)
Scale an input time to NSEC, clamping it at max / min.
static char const * months[]
fr_time_delta_t fr_time_gmtoff(void)
Get the offset to gmt.
fr_slen_t fr_time_delta_to_str(fr_sbuff_t *out, fr_time_delta_t delta, fr_time_res_t res, bool is_unsigned)
Print fr_time_delta_t to a string with an appropriate suffix.
size_t fr_time_precision_table_len
static char const * tz_names[2]
normal, DST, from localtime_r(), tm_zone
int fr_time_start(void)
Initialize the local time.
static bool isdst
from localtime_r(), tm_is_dst
fr_slen_t fr_unix_time_to_str(fr_sbuff_t *out, fr_unix_time_t time, fr_time_res_t res, bool utc)
Convert unix time to string.
int64_t fr_time_epoch
monotonic clock at boot, i.e. our epoch
size_t fr_time_strftime_utc(fr_sbuff_t *out, fr_time_t time, char const *fmt)
Copy a time string (UTC) to an sbuff.
int64_t const fr_time_multiplier_by_res[]
static fr_time_delta_t fr_time_delta_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
static int64_t fr_time_delta_to_integer(fr_time_delta_t delta, fr_time_res_t res)
static int64_t fr_time_to_sec(fr_time_t when)
Convert an fr_time_t (internal time) to number of sec since the unix epoch (wallclock time)
#define fr_time_gteq(_a, _b)
static fr_unix_time_t fr_unix_time_from_nsec(int64_t nsec)
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
#define fr_time_delta_isneg(_a)
#define fr_time_delta_lt(_a, _b)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
static int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
#define fr_time_delta_wrap(_time)
#define fr_unix_time_min()
fr_time_res_t
The base resolution for print parse operations.
static fr_unix_time_t fr_unix_time_from_sec(int64_t sec)
static uint64_t fr_unix_time_unwrap(fr_unix_time_t time)
#define CLOCK_MONOTONIC_RAW
uint64_t array[8]
100ns to 100s
#define fr_time_sub(_a, _b)
Subtract one time from another.
#define FR_TIME_DUR_MONTH
#define fr_unix_time_add(_a, _b)
Add a time/time delta together.
static fr_time_delta_t fr_time_delta_from_timespec(struct timespec const *ts)
A time delta, a difference in time measured in nanoseconds.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out