1#include <errno.h>
2#include <time.h>
3
4#include "include/pw.h"
5
6[[nodiscard]] bool pw_monotonic(PwValuePtr result)
7{
8 struct timespec t;
9 if (clock_gettime(CLOCK_MONOTONIC, &t) == -1) {
10 pw_set_status(PwErrno(errno));
11 return false;
12 }
13 pw_destroy(result);
14 result->type_id = PwTypeId_Timestamp;
15 result->ts_seconds = t.tv_sec;
16 result->ts_nanoseconds = t.tv_nsec;
17 return true;
18}
19
20[[nodiscard]] bool pw_utcnow(PwValuePtr result)
21{
22 struct timespec t;
23 if (clock_gettime(CLOCK_REALTIME, &t) == -1) {
24 pw_set_status(PwErrno(errno));
25 return false;
26 }
27 struct tm tm;
28 if (!gmtime_r(&t.tv_sec, &tm)) {
29 pw_set_status(PwErrno(errno));
30 return false;
31 }
32 pw_destroy(result);
33 result->type_id = PwTypeId_DateTime;
34 result->year = tm.tm_year + 1900;
35 result->month = tm.tm_mon + 1;
36 result->day = tm.tm_mday;
37 result->hour = tm.tm_hour;
38 result->minute = tm.tm_min;
39 result->second = tm.tm_sec;
40 result->nanosecond = t.tv_nsec;
41 result->gmt_offset = 0;
42 result->tzindex = 0;
43 return true;
44}
45
46void pw_timestamp_add(PwValuePtr a, PwValuePtr b)
47{
48 pw_hard_assert(pw_is_timestamp(a));
49 pw_hard_assert(pw_is_timestamp(b));
50
51 a->ts_seconds += b->ts_seconds;
52 a->ts_nanoseconds += b->ts_nanoseconds;
53 if (a->ts_nanoseconds >= 1000'000'000UL) {
54 a->ts_nanoseconds -= 1000'000'000UL;
55 a->ts_seconds++;
56 }
57}
58
59[[nodiscard]] _PwValue pw_timestamp_sum(PwValuePtr a, PwValuePtr b)
60{
61 pw_hard_assert(pw_is_timestamp(a));
62 pw_hard_assert(pw_is_timestamp(b));
63
64 _PwValue sum = PW_TIMESTAMP(
65 a->ts_seconds + b->ts_seconds,
66 a->ts_nanoseconds + b->ts_nanoseconds
67 );
68 if (sum.ts_nanoseconds >= 1000'000'000UL) {
69 sum.ts_nanoseconds -= 1000'000'000UL;
70 sum.ts_seconds++;
71 }
72 return sum;
73}
74
75[[nodiscard]] _PwValue pw_timestamp_diff(PwValuePtr a, PwValuePtr b)
76{
77 pw_hard_assert(pw_is_timestamp(a));
78 pw_hard_assert(pw_is_timestamp(b));
79
80 _PwValue diff = PW_TIMESTAMP(
81 a->ts_seconds - b->ts_seconds,
82 a->ts_nanoseconds - b->ts_nanoseconds
83 );
84 if (a->ts_nanoseconds < b->ts_nanoseconds) {
85 diff.ts_seconds--;
86 diff.ts_nanoseconds += 1000'000'000UL;
87 }
88 return diff;
89}
90
91[[nodiscard]] int pw_timestamp_cmp(PwValuePtr a, PwValuePtr b)
92{
93 pw_hard_assert(pw_is_timestamp(a));
94 pw_hard_assert(pw_is_timestamp(b));
95
96 if (a->ts_seconds < b->ts_seconds) {
97 return -1;
98 }
99 if (a->ts_seconds > b->ts_seconds) {
100 return 1;
101 }
102 if (a->ts_nanoseconds < b->ts_nanoseconds) {
103 return -1;
104 }
105 if (a->ts_nanoseconds > b->ts_nanoseconds) {
106 return 1;
107 }
108 return 0;
109}