aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChloe Kudryavtsev <code@toast.bunkerlabs.net>2023-06-17 22:20:11 +0200
committerChloe Kudryavtsev <code@toast.bunkerlabs.net>2023-06-17 22:20:11 +0200
commit36696695692ae816e8a3d442b7647e3aba1feba5 (patch)
tree4a06bc97e2e1091657e8884022407ee8ecea3add
parentminor native sources cleanup (diff)
allow constructing your own date/tm values
-rw-r--r--date/init.janet23
-rw-r--r--src/time.c10
-rw-r--r--src/tm.c15
-rw-r--r--test/02-api.janet8
4 files changed, 43 insertions, 13 deletions
diff --git a/date/init.janet b/date/init.janet
index aaf2272..215b019 100644
--- a/date/init.janet
+++ b/date/init.janet
@@ -1,15 +1,30 @@
(import date/native)
-(defn time
- `Return an opaque datetime representation of the current moment.`
- []
- (native/time))
+(def time
+ `Return an opaque date/time representation of the current moment.`
+ native/time)
(defn time?
`Check if x is a date/time object.`
[x]
(= :date/time (type x)))
+(defn- tm
+ [f &opt o]
+ (def out (native/tm o))
+ (f out)
+ out)
+
+(def utc
+ `Generate a date/tm object from a compatible dictionary. Implying UTC.
+ Non-specified fields will be initialized to their default values (usually zero).`
+ (partial tm native/timegm!))
+
+(def local
+ `Generate a date/tm object from a compatible dictionary. Implying localtime.
+ Non-specified fields will be initialized to their default values (usually zero).`
+ (partial tm native/mktime!))
+
(defn tm?
`Check if x is a date/tm object.`
[x]
diff --git a/src/time.c b/src/time.c
index f9bda70..eee419e 100644
--- a/src/time.c
+++ b/src/time.c
@@ -22,10 +22,14 @@ static int jd_time_get(void *p, Janet key, Janet *out) {
return janet_getmethod(janet_unwrap_keyword(key), jd_time_methods, out);
}
-// time_t is always a UTC-representation
+// time_t is an arithmetic type, which means some width of int or float
+// instead of trying to guess the type,
+// we give the number of seconds from the zero-value of time_t
+// on UNIX platforms, this is the number of seconds since UNIX epoch (1970)
+// ultimately, the user knows what platform they're on, making the output useful
static void jd_time_tostring(void *p, JanetBuffer *buffer) {
- // print ISO 8601
- strftime_buffer("%F %T%z", gmtime(p), buffer);
+ double dt = difftime(*(time_t*)p, 0);
+ janet_formatb(buffer, "%f", dt);
}
static const JanetAbstractType jd_time_t = {
diff --git a/src/tm.c b/src/tm.c
index f04e9a9..a029627 100644
--- a/src/tm.c
+++ b/src/tm.c
@@ -215,15 +215,18 @@ struct tm *jd_opttm(Janet *argv, int32_t argc, int32_t n) {
JANET_FN(jd_tm,
"(tm {:sec 0 ...})",
- "Construct a date/tm object from a compatible dictionary.") {
- janet_fixarity(argc, 1);
- JanetDictView view = janet_getdictionary(argv, 0);
+ "Construct a date/tm object from a compatible dictionary.\n"
+ "Note that you *must* immediate pass this into timegm or mktime.") {
+ janet_arity(argc, 0, 1);
struct tm *out = jd_maketm();
+ // default values
memset(out, 0, sizeof(struct tm));
-#ifdef TM_GMTOFF
- out->TM_GMTOFF = 0;
-#endif
+ out->tm_mday = 1; // range is 1-31
+
+ if (argc == 0 || janet_checktype(argv[0], JANET_NIL)) return janet_wrap_abstract(out);
+
+ JanetDictView view = janet_getdictionary(argv, 0);
for (int32_t i = 0; i < view.cap; i++) {
const JanetKV e = view.kvs[i];
diff --git a/test/02-api.janet b/test/02-api.janet
index eb0666f..2a9c0ec 100644
--- a/test/02-api.janet
+++ b/test/02-api.janet
@@ -19,3 +19,11 @@
(assert (date/format now :default true))
# format string
(assert (date/format now :%c))
+
+# ensure tm + gmtime are spec-compliant
+(def u (date/utc {:year 1970}))
+(def l (date/local {:year 1970}))
+(assert (= u
+ (:gmtime (:timegm u))))
+(assert (= l
+ (:localtime (:mktime l))))