commit 68cb2d3fb078f5bd653ec6d573982e32596eb9fa
parent 7ef28642466f51bf065e3988966a184ceb88fef4
Author: Louis Burda <quent.burda@gmail.com>
Date: Mon, 26 Jun 2023 14:31:40 +0200
Add date span api
Diffstat:
5 files changed, 116 insertions(+), 5 deletions(-)
diff --git a/build.jst.tmpl b/build.jst.tmpl
@@ -39,10 +39,10 @@ target lib/liballoc/build/liballoc.a
just lib/liballoc
target build/libhmd.a
- liba src/hmd.c | include/hmd.h build
+ liba src/hmd.c | include/hmd.h build libhmd.api
target build/libhmd.so
- libso src/hmd.c | include/hmd.h build
+ libso src/hmd.c | include/hmd.h build libhmd.lds
target build/test
cc src/test.c build/libhmd.a lib/liballoc/build/liballoc.a | build
diff --git a/include/hmd.h b/include/hmd.h
@@ -11,10 +11,11 @@
#define HMD_WEEK_SPN (HMD_DAY_SPN * 7)
enum hmd_err {
- HMD_OK,
+ HMD_OK = 0,
HMD_ERR_OOB,
HMD_ERR_FMT,
HMD_ERR_SYS,
+ HMD_ERR_ARG,
HMD_ERR_INT
};
@@ -43,6 +44,15 @@ enum hmd_wday {
HMD_SAT,
};
+struct hmd_spn {
+ uint32_t years;
+ uint32_t weeks;
+ uint32_t days;
+ uint32_t hours;
+ uint32_t mins;
+ uint32_t secs;
+};
+
struct hmd_date {
uint64_t ts; /* unix epoch */
uint64_t spn;
@@ -69,6 +79,12 @@ struct hmd_ival {
uint8_t sec;
};
+enum hmd_err hmd_spn_parse(struct hmd_spn *spn, const char *arg);
+enum hmd_err hmd_spn_calc(struct hmd_spn *spn, uint64_t start, uint64_t end);
+
+char *hmd_spn_str(struct hmd_spn *spn,
+ const struct allocator *allocator, int *rc);
+
enum hmd_err hmd_date_parse_daydate_reltime_weekday(
struct hmd_date *date, char *arg);
enum hmd_err hmd_date_parse_daydate_reltime_coarse(
diff --git a/libhmd.api b/libhmd.api
@@ -1,3 +1,8 @@
+hmd_spn_parse
+
+hmd_spn_calc
+hmd_spn_str
+
hmd_date_parse_daydate_reltime_weekday
hmd_date_parse_daydate_reltime_coarse
hmd_date_parse_daydate_iso8601
diff --git a/libhmd.lds b/libhmd.lds
@@ -1,4 +1,9 @@
-LIBHMD_0.1.0 {
+LIBHMD_0.1.1 {
+ hmd_spn_parse;
+
+ hmd_spn_calc;
+ hmd_spn_str;
+
hmd_date_parse_daydate_reltime_weekday;
hmd_date_parse_daydate_reltime_coarse;
hmd_date_parse_daydate_iso8601;
diff --git a/src/hmd.c b/src/hmd.c
@@ -1,6 +1,6 @@
#include "hmd.h"
-#include <asm-generic/errno.h>
+#include <stdint.h>
#include <time.h>
#include <errno.h>
#include <stdarg.h>
@@ -145,6 +145,90 @@ time2tm(struct tm *tm, uint64_t time)
}
enum hmd_err
+hmd_spn_parse(struct hmd_spn *spn, const char *arg)
+{
+ const char *c;
+ char *end;
+ uint64_t v;
+
+ for (c = arg; *c; c = end + 1) {
+ v = strtoul(c, &end, 10);
+ if (!end) return HMD_ERR_FMT;
+ if (v >= UINT32_MAX) return HMD_ERR_FMT;
+ switch (*end) {
+ case 'y':
+ spn->years += (uint32_t) v;
+ break;
+ case 'w':
+ spn->weeks += (uint32_t) v;
+ break;
+ case 'd':
+ spn->days += (uint32_t) v;
+ break;
+ case 'h':
+ spn->hours += (uint32_t) v;
+ break;
+ case 'm':
+ spn->mins += (uint32_t) v;
+ break;
+ case 's':
+ spn->secs += (uint32_t) v;
+ break;
+ default:
+ return HMD_ERR_FMT;
+ }
+ }
+
+ return HMD_OK;
+}
+
+enum hmd_err
+hmd_spn_calc(struct hmd_spn *spn, uint64_t start, uint64_t end)
+{
+ struct tm tm_start, tm_end;
+ enum hmd_err err;
+
+ if (end < start) return HMD_ERR_ARG;
+
+ err = time2tm(&tm_start, start);
+ if (err) return err;
+
+ err = time2tm(&tm_end, end);
+ if (err) return err;
+
+ spn->years = (uint32_t) (tm_end.tm_year - tm_start.tm_year);
+ spn->days = (uint32_t) (tm_end.tm_yday - tm_start.tm_yday);
+ spn->weeks = spn->days / 7;
+ spn->days = spn->days % 7;
+ spn->hours = (uint32_t) (tm_end.tm_hour - tm_start.tm_hour);
+ spn->mins = (uint32_t) (tm_end.tm_min - tm_start.tm_min);
+ spn->secs = (uint32_t) (tm_end.tm_sec - tm_start.tm_sec);
+
+ return HMD_OK;
+}
+
+char *
+hmd_spn_str(struct hmd_spn *spn,
+ const struct allocator *allocator, int *rc)
+{
+ char *str, *c;
+
+ c = str = allocator->alloc(allocator, 32 /* >= 5 * 6 + 1 */, rc);
+ if (!str && rc) *rc = -*rc;
+ if (!str) return NULL;
+
+ if (spn->years) c += snprintf(c, 6, "%.4uy", spn->years);
+ if (spn->weeks) c += snprintf(c, 6, "%.4uw", spn->weeks);
+ if (spn->days) c += snprintf(c, 6, "%.4ud", spn->days);
+ if (spn->hours) c += snprintf(c, 6, "%.4uh", spn->hours);
+ if (spn->mins) c += snprintf(c, 6, "%.4um", spn->mins);
+ if (spn->secs) c += snprintf(c, 6, "%.4us", spn->secs);
+ *c = '\0';
+
+ return str;
+}
+
+enum hmd_err
hmd_date_parse_daydate_reltime_weekday(struct hmd_date *date, char *arg)
{
struct tm datetm, nowtm;
@@ -253,6 +337,7 @@ hmd_date_parse_daydate_iso8601(struct hmd_date *date, char *arg)
now = time(NULL);
nowtm = *localtime(&now);
+ n = 0;
if (sscanf(arg, "%u-%u-%u%n", &year, &month, &day, &n) == 3 && !arg[n]) {
tm = startofday(nowtm);
tm.tm_year = year - 1900;