26RCSID(
"$Id: e045065dd754e50ea00e17b282bfb9634aabd1ad $")
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)) {
259 if (negative) integer = -(integer);
264 fr_sbuff_marker(&m_f, &our_in);
295#ifdef STATIC_ANALYZER
297 if (f > UINT64_MAX / 10)
break;
337 fr_sbuff_set_to_start(&our_in);
352 if (negative) tmp = -(tmp);
364 uint64_t hours, minutes, seconds;
369 fr_sbuff_marker(&m1, &our_in);
371 if (
fr_sbuff_out(&sberr, &seconds, &our_in) < 0)
goto num_error;
378 minutes = negative ? -(integer) : integer;
380 if (minutes > UINT16_MAX) {
382 fr_sbuff_set_to_start(&our_in);
389 hours = negative ? -(integer) : integer;
392 if (
fr_sbuff_out(&sberr, &seconds, &our_in) < 0)
goto num_error;
394 if (hours > UINT16_MAX) {
396 fr_sbuff_set_to_start(&our_in);
400 if (minutes > UINT16_MAX) {
411 if (!
fr_add(&integer, ((hours * 60) * 60) + (minutes * 60), seconds))
goto overflow;
416 if (negative) integer = -(integer);
433 if (overflow)
goto overflow;
454 if (slen < 0)
return slen;
483#define MOD(a,b) (((a<0) ? (-a) : (a))%(b))
508 while (*q ==
'0') *(q--) =
'\0';
549 if (len == 0)
return 0;
578 if (len == 0)
return 0;
622 "1us",
"10us",
"100us",
623 "1ms",
"10ms",
"100ms",
627static char const *
tab_string =
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
634 if (!prefix) prefix =
"elapsed";
636 prefix_len = strlen(prefix);
638 for (i = 0; i < 8; i++) {
641 if (!elapsed->
array[i])
continue;
643 len = prefix_len + 1 + strlen(
names[i]);
645 if (len >= (
size_t) (tab_offset * 8)) {
646 fprintf(fp,
"%s.%s %" PRIu64
"\n",
652 tabs = ((tab_offset * 8) - len);
656 fprintf(fp,
"%s.%s%.*s%" PRIu64
"\n",
667 static const uint16_t month_yday[12] = {0, 31, 59, 90, 120, 151,
668 181, 212, 243, 273, 304, 334};
680 year_adj = tm->tm_year + 4800 + 1900;
681 febs = year_adj - (tm->tm_mon < 2 ? 1 : 0);
682 leap_days = 1 + (febs / 4) - (febs / 100) + (febs / 400);
684 days = 365 * year_adj + leap_days + month_yday[tm->tm_mon] + tm->tm_mday - 1;
686#define CHECK(_x, _max) if ((tm->tm_ ## _x < 0) || (tm->tm_ ## _x >= _max)) tm->tm_ ## _x = _max - 1
706 (tm->tm_min * 60) + tm->tm_sec) - tm->tm_gmtoff);
745 if (t < (INT64_MIN / scale)) {
749 if (t > (INT64_MAX / scale)) {
765 if (**ptr ==
'\0')
return NULL;
767 while (**ptr && strchr(sep, **ptr)) (*ptr)++;
769 if (**ptr ==
'\0')
return NULL;
772 while (**ptr && strchr(sep, **ptr) == NULL) (*ptr)++;
774 if (**ptr !=
'\0') *(*ptr)++ =
'\0';
783static int get_part(
char **str,
int *date,
int min,
int max,
char term,
char const *
name)
787 if (!isdigit((
uint8_t) *p) || !isdigit((
uint8_t) p[1]))
return -1;
788 *date = (p[0] -
'0') * 10 + (p[1] -
'0');
818 "jan",
"feb",
"mar",
"apr",
"may",
"jun",
819 "jul",
"aug",
"sep",
"oct",
"nov",
"dec" };
847 tmp = strtoul(date_str, &tail, 10);
854 memset(tm, 0,
sizeof(*tm));
867 if ((tmp > 1900) && (tmp < 3000) && *tail ==
'-') {
868 unsigned long subseconds;
869 int tz, tz_hour, tz_min;
872 s_tm.tm_year = tmp - 1900;
874 if (
get_part(&p, &s_tm.tm_mon, 1, 12,
'-',
"month") < 0)
return -1;
877 if (
get_part(&p, &s_tm.tm_mday, 1, 31,
'T',
"day") < 0)
return -1;
878 if (
get_part(&p, &s_tm.tm_hour, 0, 23,
':',
"hour") < 0)
return -1;
879 if (
get_part(&p, &s_tm.tm_min, 0, 59,
':',
"minute") < 0)
return -1;
880 if (
get_part(&p, &s_tm.tm_sec, 0, 60,
'\0',
"seconds") < 0)
return -1;
884 subseconds = strtoul(p, &tail, 10);
885 if (subseconds >
NSEC) {
894 if ((tail - p) < 9) {
895 for (i = 0; i < 9 - (tail -p); i++) {
918 if ((*p !=
'+') && (*p !=
'-')) {
925 if (
get_part(&p, &tz_hour, 0, 23,
':',
"hour in time zone") < 0)
return -1;
926 if (
get_part(&p, &tz_min, 0, 59,
'\0',
"minute in time zone") < 0)
return -1;
946 tz = tz_hour * 3600 + tz_min;
947 if (*tail ==
'-') tz *= -1;
975 char const *tz = strstr(date_str,
"UTC");
979 my_str = talloc_strdup(NULL, date_str);
981 p = my_str + (tz - date_str);
984 p = strptime(my_str,
"%b %e %Y %H:%M:%S %Z", tm);
985 if (p && (*p ==
'\0')) {
996 p = strptime(date_str,
"%b %e %Y %H:%M:%S %Z", tm);
997 if (p && (*p ==
'\0')) {
1002 strlcpy(buf, date_str,
sizeof(buf));
1009 if (!f[0] || !f[1] || !f[2]) {
1030 for (i = 0; i < 3; i++) {
1031 if (strchr(f[i],
':')) {
1044 for (i = 0; i < 3; i++) {
1045 if (isalpha((
uint8_t) *f[i])) {
1055 for (j = 0; j < 12; j++) {
1065 if (tm->tm_mon == 12) {
1073 l = strtoul(f[1], &tail, 10);
1074 if ((l == ULONG_MAX) || (*tail !=
'\0')) {
1080 l = strtoul(f[2], &tail, 10);
1081 if ((l == ULONG_MAX) || (*tail !=
'\0')) {
1087 if (tm->tm_year >= 1900) {
1088 tm->tm_year -= 1900;
1095 if (tm->tm_mday < 1900) {
1104 tm->tm_year = tm->tm_mday - 1900;
1108 if (tm->tm_year > 10000) {
1116 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1126 f[1] = strchr(f[0],
':');
1134 f[2] = strchr(f[1],
':');
1137 tm->tm_sec = atoi(f[2]);
1140 tm->tm_hour = atoi(f[0]);
1141 tm->tm_min = atoi(f[1]);
1174 len = strftime(buf,
sizeof(buf),
"%Y-%m-%dT%H:%M:%S", &s_tm);
1218 if (s_tm.tm_gmtoff != 0) {
1221 hours = s_tm.tm_gmtoff / 3600;
1222 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