master ohmu/fastfetch-openbsd / src / common / impl / time.c
ohmu  ·  2026-10-15
 1#include "common/time.h"
 2
 3#include <stdio.h>
 4
 5char ffTimeInternalBuffer[64]; // Reduce memory usage and prevent redundant allocations
 6
 7#ifdef _WIN32
 8    #pragma GCC diagnostic push
 9    #pragma GCC diagnostic ignored "-Wformat"
10#endif
11
12const char* ffTimeToFullStr(uint64_t msec) {
13    if (msec == 0) {
14        return "";
15    }
16    time_t tsec = (time_t) (msec / 1000);
17    const struct tm* tm = localtime(&tsec);
18
19    uint32_t len = 0;
20    len += (uint32_t) strftime(ffTimeInternalBuffer, ARRAY_SIZE(ffTimeInternalBuffer) - len, "%FT%T", tm);
21    len += (uint32_t) snprintf(ffTimeInternalBuffer + len, ARRAY_SIZE(ffTimeInternalBuffer) - len, ".%03u", (unsigned) (msec % 1000));
22    len += (uint32_t) strftime(ffTimeInternalBuffer + len, ARRAY_SIZE(ffTimeInternalBuffer) - len, "%z", tm);
23    return ffTimeInternalBuffer;
24}
25
26const char* ffTimeToShortStr(uint64_t msec) {
27    if (msec == 0) {
28        return "";
29    }
30    time_t tsec = (time_t) (msec / 1000);
31
32    strftime(ffTimeInternalBuffer, ARRAY_SIZE(ffTimeInternalBuffer), "%F %T", localtime(&tsec));
33    return ffTimeInternalBuffer;
34}
35
36const char* ffTimeToTimeStr(uint64_t msec) {
37    if (msec == 0) {
38        return "";
39    }
40    time_t tsec = (time_t) (msec / 1000);
41
42    uint32_t len = (uint32_t) strftime(ffTimeInternalBuffer, ARRAY_SIZE(ffTimeInternalBuffer), "%T", localtime(&tsec));
43    sprintf(ffTimeInternalBuffer + len, ".%03u", (unsigned) (msec % 1000));
44    return ffTimeInternalBuffer;
45}
46
47#ifdef _WIN32
48    #pragma GCC diagnostic pop
49#endif
50
51FFTimeGetAgeResult ffTimeGetAge(uint64_t birthMs, uint64_t nowMs) {
52    FFTimeGetAgeResult result = {};
53    if (__builtin_expect(birthMs == 0 || nowMs < birthMs, 0)) {
54        return result;
55    }
56
57    time_t birth_s = (time_t) (birthMs / 1000);
58    struct tm birth_tm;
59#ifdef _WIN32
60    localtime_s(&birth_tm, &birth_s);
61#else
62    localtime_r(&birth_s, &birth_tm);
63#endif
64
65    time_t now_s = (time_t) (nowMs / 1000);
66    struct tm now_tm;
67#ifdef _WIN32
68    localtime_s(&now_tm, &now_s);
69#else
70    localtime_r(&now_s, &now_tm);
71#endif
72
73    result.years = (uint32_t) (now_tm.tm_year - birth_tm.tm_year);
74    if (now_tm.tm_yday < birth_tm.tm_yday) {
75        result.years--;
76    }
77
78    birth_tm.tm_year += (int) result.years;
79    birth_s = mktime(&birth_tm);
80    uint32_t diff_s = (uint32_t) (now_s - birth_s);
81    result.daysOfYear = diff_s / (24 * 60 * 60);
82
83    birth_tm.tm_year += 1;
84    result.yearsFraction = (double) diff_s / (double) (mktime(&birth_tm) - birth_s) + result.years;
85
86    return result;
87}
88
89#ifdef _WIN32
90double ffQpcMultiplier;
91
92[[gnu::constructor]] static void ffTimeInitQpcMultiplier(void) {
93    LARGE_INTEGER frequency;
94    RtlQueryPerformanceFrequency(&frequency);
95    ffQpcMultiplier = 1000. / (double) frequency.QuadPart;
96}
97#endif