diff options
| author | 2023-05-13 12:43:58 -0400 | |
|---|---|---|
| committer | 2023-05-13 12:43:58 -0400 | |
| commit | 71026ea3ecb33b923f513f1e36cedbd89d6b7dc4 (patch) | |
| tree | 164885af945a25fef0f63303263522848238285d | |
| parent | better tests that also serve as temporary docs (diff) | |
add TM_GMTOFF and TM_ZONE
I might want to be able to write to them, but that seems very
error-prone.
| -rw-r--r-- | src/polyfill.h | 20 | ||||
| -rw-r--r-- | src/tm.c | 47 |
2 files changed, 62 insertions, 5 deletions
diff --git a/src/polyfill.h b/src/polyfill.h index 5fa72ac..ecc3a0d 100644 --- a/src/polyfill.h +++ b/src/polyfill.h @@ -18,5 +18,23 @@ const char *janet_optcbytes(const Janet *argv, int32_t argc, int32_t n, const ch static const int32_t CNAME##_sourceline_ = __LINE__; \ Janet CNAME (int32_t argc, Janet *argv) #endif // !defined(JANET_NO_SOURCEMAPS) - #endif // JANET_VERSION_MAJOR < 2 && JANET_VERSION_MINOR < 28 + +// === + +// public domain code from +// https://github.com/eggert/tz.git + +/* Infer TM_ZONE on systems where this information is known, but suppress + guessing if NO_TM_ZONE is defined. Similarly for TM_GMTOFF. */ +#if (defined __GLIBC__ \ + || defined __tm_zone /* musl */ \ + || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \ + || (defined __APPLE__ && defined __MACH__)) +# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF +# define TM_GMTOFF tm_gmtoff +# endif +# if !defined TM_ZONE && !defined NO_TM_ZONE +# define TM_ZONE tm_zone +# endif +#endif @@ -40,6 +40,12 @@ static const struct jd_tm_key jd_tm_keys[] = { {"wday", offsetof(struct tm, tm_wday)}, {"yday", offsetof(struct tm, tm_yday)}, {"isdst", offsetof(struct tm, tm_isdst)}, +#ifdef TM_GMTOFF + {"gmtoff", offsetof(struct tm, TM_GMTOFF)}, +#endif +#ifdef TM_ZONE + {"zone", offsetof(struct tm, TM_ZONE)}, +#endif {NULL, 0}, }; @@ -56,6 +62,21 @@ static int jd_tm_get(void *p, Janet key, Janet *out) { const struct jd_tm_key *ptr = jd_tm_keys; while (ptr->key) { if (janet_keyeq(key, ptr->key)) { +#ifdef TM_GMTOFF + if (janet_keyeq(key, "gmtoff")) { + long val = *((long*)(p + ptr->off)); + *out = janet_wrap_s64(val); + return 1; + } +#endif +#ifdef TM_ZONE + if (janet_keyeq(key, "zone")) { + const char *val = *((const char **)(p + ptr->off)); + *out = janet_ckeywordv(val); + return 1; + } +#endif + int val = *((int*)(p + ptr->off)); // exceptional values @@ -87,6 +108,16 @@ static Janet jd_tm_next(void *p, Janet key) { } static void jd_tm_put(void *data, Janet key, Janet value) { + if (0 +#ifdef TM_GMTOFF + || janet_keyeq(key, "gmtoff") +#endif +#ifdef TM_ZONE + || janet_keyeq(key, "zone") +#endif + ) { + janet_panicf("%s is read-only", key); + } // note that keyword, boolean are only valid for isdst if (!janet_checktypes(value, JANET_TFLAG_NUMBER | JANET_TFLAG_KEYWORD | JANET_TFLAG_BOOLEAN)) { janet_panicf("expected function or number, got %t", value); @@ -117,18 +148,26 @@ static void jd_tm_tostring(void *p, JanetBuffer *buffer) { const struct jd_tm_key *ptr = jd_tm_keys; while (ptr->key) { - int *loc = (int*)(p + ptr->off); + void *loc = (void*)(p + ptr->off); janet_buffer_push_cstring(buffer, ":"); janet_buffer_push_cstring(buffer, ptr->key); janet_buffer_push_cstring(buffer, " "); // exceptional values if (!strcmp(ptr->key, "year")) { - snprintf(buf, MAX_INT_STRLEN, "%d", *loc + 1900); + snprintf(buf, MAX_INT_STRLEN, "%d", *(int*)loc + 1900); } else if (!strcmp(ptr->key, "isdst")) { - strcpy(buf, *loc ? (*loc > 0 ? "true" : ":detect") : "false"); + strcpy(buf, *(int*)loc ? (*(int*)loc > 0 ? "true" : ":detect") : "false"); +#ifdef TM_ZONE + } else if (!strcmp(ptr->key, "zone")) { + strcpy(buf, *(char**)loc); +#endif +#ifdef TM_GMTOFF + } else if (!strcmp(ptr->key, "gmtoff")) { + snprintf(buf, MAX_INT_STRLEN, "%ld", *(long*)loc); +#endif } else { - snprintf(buf, MAX_INT_STRLEN, "%d", *loc); + snprintf(buf, MAX_INT_STRLEN, "%d", *(int*)loc); } janet_buffer_push_cstring(buffer, buf); |
