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}