libhmd-c

C human-readable date string library
git clone https://git.sinitax.com/sinitax/libhmd-c
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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:
Mbuild.jst.tmpl | 4++--
Minclude/hmd.h | 18+++++++++++++++++-
Mlibhmd.api | 5+++++
Mlibhmd.lds | 7++++++-
Msrc/hmd.c | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
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;