diff --git a/doc/json_schema.json b/doc/json_schema.json index dc3fd30a4..0c0812568 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -351,11 +351,11 @@ "type": "string" }, "uptimeFormat": { - "description": "Output format of the module `Uptime`. See Wiki for formatting syntax\n 1. {days}: Days\n 2. {hours}: Hours\n 3. {minutes}: Minutes\n 4. {seconds}: Seconds\n 5. {milliseconds}: Milliseconds\n 6. {boot-time}: Boot time in local timezone", + "description": "Output format of the module `Uptime`. See Wiki for formatting syntax\n 1. {days}: Days after boot\n 2. {hours}: Hours after boot\n 3. {minutes}: Minutes after boot\n 4. {seconds}: Seconds after boot\n 5. {milliseconds}: Milliseconds after boot\n 6. {boot-time}: Boot time in local timezone\n 7. {years}: Years integer after boot\n 8. {days-of-year}: Days of year after boot\n 9. {years-fraction}: Years fraction after boot", "type": "string" }, "usersFormat": { - "description": "Output format of the module `Users`. See Wiki for formatting syntax\n 1. {name}: User name\n 2. {host-name}: Host name\n 3. {session}: Session name\n 4. {client-ip}: Client IP\n 5. {login-time}: Login Time in local timezone\n 6. {days}: Days after login\n 7. {hours}: Hours after login\n 8. {minutes}: Minutes after login\n 9. {seconds}: Seconds after login\n 10. {milliseconds}: Milliseconds after login", + "description": "Output format of the module `Users`. See Wiki for formatting syntax\n 1. {name}: User name\n 2. {host-name}: Host name\n 3. {session}: Session name\n 4. {client-ip}: Client IP\n 5. {login-time}: Login Time in local timezone\n 6. {days}: Days after login\n 7. {hours}: Hours after login\n 8. {minutes}: Minutes after login\n 9. {seconds}: Seconds after login\n 10. {milliseconds}: Milliseconds after login\n 11. {years}: Years integer after login\n 12. {days-of-year}: Days of year after login\n 13. {years-fraction}: Years fraction after login", "type": "string" }, "versionFormat": { diff --git a/src/common/time.h b/src/common/time.h index 0745574bb..ed0fd1138 100644 --- a/src/common/time.h +++ b/src/common/time.h @@ -97,3 +97,47 @@ static inline const char* ffTimeToTimeStr(uint64_t msec) #ifdef _WIN32 #pragma GCC diagnostic pop #endif + +typedef struct FFTimeGetAgeResult +{ + uint32_t years; + uint32_t daysOfYear; + double yearsFraction; +} FFTimeGetAgeResult; + +static inline FFTimeGetAgeResult ffTimeGetAge(uint64_t birthMs, uint64_t nowMs) +{ + FFTimeGetAgeResult result = {}; + if (__builtin_expect(birthMs == 0 || nowMs < birthMs, 0)) + return result; + + time_t birth_s = (time_t) (birthMs / 1000); + struct tm birth_tm; + #ifdef _WIN32 + localtime_s(&birth_tm, &birth_s); + #else + localtime_r(&birth_s, &birth_tm); + #endif + + time_t now_s = (time_t) (nowMs / 1000); + struct tm now_tm; + #ifdef _WIN32 + localtime_s(&now_tm, &now_s); + #else + localtime_r(&now_s, &now_tm); + #endif + + result.years = (uint32_t) (now_tm.tm_year - birth_tm.tm_year); + if (now_tm.tm_yday < birth_tm.tm_yday) + result.years--; + + birth_tm.tm_year += result.years; + birth_s = mktime(&birth_tm); + uint32_t diff_s = (uint32_t) (now_s - birth_s); + result.daysOfYear = diff_s / (24 * 60 * 60); + + birth_tm.tm_year += 1; + result.yearsFraction = (double) diff_s / (double) (mktime(&birth_tm) - birth_s) + result.years; + + return result; +} diff --git a/src/modules/disk/disk.c b/src/modules/disk/disk.c index f69ed36e7..a2fe912f3 100644 --- a/src/modules/disk/disk.c +++ b/src/modules/disk/disk.c @@ -137,33 +137,7 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index duration /= 24; uint32_t days = (uint32_t) duration; - time_t past_s = (time_t) (disk->createTime / 1000); - struct tm past_tm; - #ifdef _WIN32 - localtime_s(&past_tm, &past_s); - #else - localtime_r(&past_s, &past_tm); - #endif - - time_t now_s = (time_t) (now / 1000); - struct tm now_tm; - #ifdef _WIN32 - localtime_s(&now_tm, &now_s); - #else - localtime_r(&now_s, &now_tm); - #endif - - uint32_t years = (uint32_t) (now_tm.tm_year - past_tm.tm_year); - if (now_tm.tm_yday < past_tm.tm_yday) - years--; - past_tm.tm_year += years; - uint32_t gap_s = (uint32_t) (now_s - mktime(&past_tm)); - uint32_t daysOfYear = gap_s / (24 * 60 * 60); - - uint32_t pastYear = past_tm.tm_year + 1900; - bool isLeapYear = (pastYear % 4 == 0 && pastYear % 100 != 0) || (pastYear % 400 == 0); - double yearsFraction = (double) daysOfYear / (isLeapYear ? 366 : 365) + years; - + FFTimeGetAgeResult age = ffTimeGetAge(disk->createTime, now); FF_PRINT_FORMAT_CHECKED(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) { FF_FORMAT_ARG(usedPretty, "size-used"), FF_FORMAT_ARG(totalPretty, "size-total"), @@ -186,9 +160,9 @@ static void printDisk(FFDiskOptions* options, const FFDisk* disk, uint32_t index FF_FORMAT_ARG(milliseconds, "milliseconds"), FF_FORMAT_ARG(disk->mountpoint, "mountpoint"), FF_FORMAT_ARG(disk->mountFrom, "mount-from"), - FF_FORMAT_ARG(years, "years"), - FF_FORMAT_ARG(daysOfYear, "days-of-year"), - FF_FORMAT_ARG(yearsFraction, "years-fraction"), + FF_FORMAT_ARG(age.years, "years"), + FF_FORMAT_ARG(age.daysOfYear, "days-of-year"), + FF_FORMAT_ARG(age.yearsFraction, "years-fraction"), })); } } diff --git a/src/modules/uptime/uptime.c b/src/modules/uptime/uptime.c index 6c3a3d2c2..64873cc19 100644 --- a/src/modules/uptime/uptime.c +++ b/src/modules/uptime/uptime.c @@ -39,6 +39,8 @@ void ffPrintUptime(FFUptimeOptions* options) uptime /= 24; uint32_t days = (uint32_t) uptime; + FFTimeGetAgeResult age = ffTimeGetAge(result.bootTime, ffTimeGetNow()); + FF_PRINT_FORMAT_CHECKED(FF_UPTIME_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ FF_FORMAT_ARG(days, "days"), FF_FORMAT_ARG(hours, "hours"), @@ -46,6 +48,9 @@ void ffPrintUptime(FFUptimeOptions* options) FF_FORMAT_ARG(seconds, "seconds"), FF_FORMAT_ARG(milliseconds, "milliseconds"), {FF_FORMAT_ARG_TYPE_STRING, ffTimeToShortStr(result.bootTime), "boot-time"}, + FF_FORMAT_ARG(age.years, "years"), + FF_FORMAT_ARG(age.daysOfYear, "days-of-year"), + FF_FORMAT_ARG(age.yearsFraction, "years-fraction"), })); } } @@ -110,12 +115,15 @@ static FFModuleBaseInfo ffModuleInfo = { .generateJsonResult = (void*) ffGenerateUptimeJsonResult, .generateJsonConfig = (void*) ffGenerateUptimeJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { - {"Days", "days"}, - {"Hours", "hours"}, - {"Minutes", "minutes"}, - {"Seconds", "seconds"}, - {"Milliseconds", "milliseconds"}, + {"Days after boot", "days"}, + {"Hours after boot", "hours"}, + {"Minutes after boot", "minutes"}, + {"Seconds after boot", "seconds"}, + {"Milliseconds after boot", "milliseconds"}, {"Boot time in local timezone", "boot-time"}, + {"Years integer after boot", "years"}, + {"Days of year after boot", "days-of-year"}, + {"Years fraction after boot", "years-fraction"}, })) }; diff --git a/src/modules/users/users.c b/src/modules/users/users.c index e50b17ced..74a608eb2 100644 --- a/src/modules/users/users.c +++ b/src/modules/users/users.c @@ -78,6 +78,8 @@ void ffPrintUsers(FFUsersOptions* options) duration /= 24; uint32_t days = (uint32_t) duration; + FFTimeGetAgeResult age = ffTimeGetAge(user->loginTime, ffTimeGetNow()); + FF_PRINT_FORMAT_CHECKED(FF_USERS_MODULE_NAME, users.length == 1 ? 0 : (uint8_t) (i + 1), &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]){ FF_FORMAT_ARG(user->name, "name"), FF_FORMAT_ARG(user->hostName, "host-name"), @@ -89,6 +91,9 @@ void ffPrintUsers(FFUsersOptions* options) FF_FORMAT_ARG(minutes, "minutes"), FF_FORMAT_ARG(seconds, "seconds"), FF_FORMAT_ARG(milliseconds, "milliseconds"), + FF_FORMAT_ARG(age.years, "years"), + FF_FORMAT_ARG(age.daysOfYear, "days-of-year"), + FF_FORMAT_ARG(age.yearsFraction, "years-fraction"), })); } } @@ -222,6 +227,9 @@ static FFModuleBaseInfo ffModuleInfo = { {"Minutes after login", "minutes"}, {"Seconds after login", "seconds"}, {"Milliseconds after login", "milliseconds"}, + {"Years integer after login", "years"}, + {"Days of year after login", "days-of-year"}, + {"Years fraction after login", "years-fraction"}, })) };