diff --git a/HISTORY b/HISTORY index 0c79721..a59615d 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,7 @@ -Version 1.85 2026-06-08 +Version 1.85 2026-06-22 * add functions fc_safe_srand and fc_safe_rand for more security under Linux + * add function seconds_to_human_str Version 1.84 2026-01-16 * fast_task_queue.h: add function free_queue_task_arg_offset diff --git a/src/shared_func.c b/src/shared_func.c index ddb14b1..aaa817f 100644 --- a/src/shared_func.c +++ b/src/shared_func.c @@ -3353,6 +3353,117 @@ const char *bytes_to_human_str(const int64_t bytes, char *buff) return buff; } +static int format_number_with_unit(const int n, const char *unit_str, + const int unit_len, char *buff, const bool add_leading_space) +{ + char *p; + + if (n <= 0) + { + return 0; + } + + p = buff; + if (add_leading_space) + { + *p++ = ' '; + } + if (n == 1) + { + *p++ = '1'; + *p++ = ' '; + memcpy(p, unit_str, unit_len); + p += unit_len; + } + else + { + p += fc_itoa(n, p); + *p++ = ' '; + memcpy(p, unit_str, unit_len); + p += unit_len; + *p++ = 's'; + } + + return p - buff; +} + +static inline int format_number_unit_first(const int n, const char *unit_str, + const int unit_len, char *buff) +{ + const bool add_leading_space = false; + return format_number_with_unit(n, unit_str, + unit_len, buff, add_leading_space); +} + +static inline int format_number_unit_next(const int n, const char *unit_str, + const int unit_len, char *buff) +{ + const bool add_leading_space = true; + return format_number_with_unit(n, unit_str, + unit_len, buff, add_leading_space); +} + + +const char *seconds_to_human_str(const int64_t seconds, char *buff) +{ + int64_t remains; + int day; + int hour; + int minute; + int second; + char *p; + + if (seconds > 0) + { + remains = seconds; + } + else + { + remains = 0; + } + + day = remains / (24 * 3600); + remains %= (24 * 3600); + hour = remains / 3600; + remains %= 3600; + minute = remains / 60; + second = remains % 60; + + p = buff; + if (day > 0) + { + p += format_number_unit_first(day, "day", 3, p); + p += format_number_unit_next(hour, "hour", 4, p); + p += format_number_unit_next(minute, "minute", 6, p); + p += format_number_unit_next(second, "second", 6, p); + } + else if (hour > 0) + { + p += format_number_unit_first(hour, "hour", 4, p); + p += format_number_unit_next(minute, "minute", 6, p); + p += format_number_unit_next(second, "second", 6, p); + } + else if (minute > 0) + { + p += format_number_unit_first(minute, "minute", 6, p); + p += format_number_unit_next(second, "second", 6, p); + } + else if (second > 0) + { + p += format_number_unit_first(second, "second", 6, p); + } + else + { + *p++ = '0'; + *p++ = ' '; + memcpy(p, "second", 6); + p += 6; + } + + *p = '\0'; + return buff; +} + bool starts_with(const char *str, const char *needle) { int str_len; diff --git a/src/shared_func.h b/src/shared_func.h index aaee7d7..c79a278 100644 --- a/src/shared_func.h +++ b/src/shared_func.h @@ -1210,6 +1210,8 @@ static inline const char *double_to_comma_str(const double d, const char *bytes_to_human_str(const int64_t bytes, char *buff); +const char *seconds_to_human_str(const int64_t seconds, char *buff); + /** if the string starts with the needle string * parameters: * str: the string to detect