1 /*
2     KSysGuard, the KDE System Guard
3 
4     SPDX-FileCopyrightText: 2014 Gregor Mi <codestruct@posteo.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 
8 */
9 
10 #ifndef TIMEUTIL_H
11 #define TIMEUTIL_H
12 
13 #include <cmath> // floor
14 
15 #ifdef Q_OS_OSX
16 #include <mach/clock.h>
17 #include <mach/mach.h>
18 #else
19 #include <time.h>
20 #endif
21 
22 #include <QDateTime>
23 
24 #include <klocalizedstring.h> // KF5::I18n
25 
26 class TimeUtil
27 {
28 public:
29     /**
30      * @Returns the amount of seconds passed since the system was booted
31      */
systemUptimeSeconds()32     static long systemUptimeSeconds()
33     {
34 #ifdef Q_OS_OSX
35         clock_serv_t cclock;
36         mach_timespec_t tp;
37 
38         host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
39         clock_get_time(cclock, &tp);
40         mach_port_deallocate(mach_task_self(), cclock);
41 #else
42         timespec tp;
43 #ifdef Q_OS_LINUX
44         int isSuccess = clock_gettime(CLOCK_BOOTTIME, &tp);
45         // _MONOTONIC doesn't increase while the system is suspended,
46         // resulting in process start times in the future
47 #else
48         int isSuccess =
49             clock_gettime(CLOCK_MONOTONIC, &tp); // see https://stackoverflow.com/questions/8357073/get-uptime-in-seconds-or-miliseconds-on-unix-like-systems
50 #endif
51         Q_ASSERT(isSuccess == 0);
52 #endif
53         return tp.tv_sec;
54     }
55 
56     /**
57      * @Returns the point in time when the system was booted
58      */
systemUptimeAbsolute()59     static QDateTime systemUptimeAbsolute()
60     {
61         auto now = QDateTime::currentDateTime();
62         return now.addSecs(-systemUptimeSeconds());
63     }
64 
65     /**
66      * Converts the given @param seconds into a human readable string.
67      * It represents an elapsed time span, e.g. "3m 50s ago".
68      */
secondsToHumanElapsedString(long seconds)69     static QString secondsToHumanElapsedString(long seconds)
70     {
71         const int s_abs = seconds;
72         const int m_abs = floor(seconds / 60.0);
73         const int h_abs = floor(seconds / 60.0 / 60.0);
74         const int d_abs = floor(seconds / 60.0 / 60.0 / 24.0);
75 
76         if (m_abs == 0) {
77             return i18nc("contains a abbreviated time unit: (s)econds", "%1s ago", s_abs);
78         } else if (h_abs == 0) {
79             const int s = s_abs - m_abs * 60;
80             return i18nc("contains abbreviated time units: (m)inutes and (s)econds", "%1m %2s ago", m_abs, s);
81         } else if (d_abs == 0) {
82             const int s = s_abs - m_abs * 60;
83             const int m = m_abs - h_abs * 60;
84             return i18nc("contains abbreviated time units: (h)ours, (m)inutes and (s)econds)", "%1h %2m %3s ago", h_abs, m, s);
85         } else { // d_abs > 0
86             const int m = m_abs - h_abs * 60;
87             const int h = h_abs - d_abs * 24;
88             return i18ncp("contains also abbreviated time units: (h)ours and (m)inutes", "%1 day %2h %3m ago", "%1 days %2h %3m ago", d_abs, h, m);
89         }
90     }
91 };
92 
93 #endif
94