aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tm.c1
-rw-r--r--test/01-native.janet55
2 files changed, 43 insertions, 13 deletions
diff --git a/src/tm.c b/src/tm.c
index 9385190..a88ac36 100644
--- a/src/tm.c
+++ b/src/tm.c
@@ -11,6 +11,7 @@ static JanetMethod jd_tm_methods[] = {
{NULL, NULL},
};
+// WARNING: this only works if they're BOTH localtime or gmtime
static int jd_tm_compare(void *lhs, void *rhs) {
struct tm lhp = (*(struct tm*)lhs);
struct tm rhp = (*(struct tm*)rhs);
diff --git a/test/01-native.janet b/test/01-native.janet
index ac04364..972e55e 100644
--- a/test/01-native.janet
+++ b/test/01-native.janet
@@ -1,14 +1,15 @@
(use date/native)
-(defn platform [& ps] (some (partial = (os/which)) ps))
-
# you generally start with this
# `time` returns the time in UTC
+# note that it's an *opaque* type
+# you should not try to interpret it except with comparisons
(def now (time))
# you can convert a `time` object into a `tm` object which represents a date
# using :localtime or :gmtime, where gmtime interprets the time as UTC
(def loc (:localtime now))
+(def gmt (:gmtime now))
# you can modify `tm` objects like an associative array
# this means that put, update, keys, values, etc all work
@@ -18,22 +19,50 @@
# if the second count was at 0, it would now be at -1, which is out of range
# that's not a problem though, you can actually already perform comparisons
+# WARN: you can ONLY compare `tm` objects of the same type (localtime vs gmtime)
(assert (< loc* loc))
-# :localtime, :localtime!, :gmtime, :gmtime!, :mktime, and :mktime!
-# all "renormalize" the object
+# :mktime, and :mktime! "renormalize" the object
# :mktime returns a `time` object
# :mktime! does that, and normalizes the `tm` object in place by mutating it
-(assert (= (:mktime loc) now))
+(assert (= (:mktime loc) now))
(assert (< (:mktime loc*) now))
-# :gmtime(!) is equivalent to (:gmtime (:mktime(!) tm)), ditto for localtime
-(def loc* (:localtime! loc*))
-(assert (< loc* loc))
+# you must not call :mktime or :mktime! on the output of a :gmtime
+# the data *will* be wrong, as mktime (as per the spec) presumes :localtime
+(assert (not= (:mktime gmt) now))
+
+# as such, the correct approach is to keep things in `time` format as much as
+# possible, only converting to :localtime or :gmtime for mutation and formatting
+# this is roughly what the janet wrapper does
+(defn- put-date
+ [ds key val]
+ (when val # allow null val for update-time
+ (if (function? val)
+ (update ds key val)
+ (put ds key val))))
+(defn update-time
+ [time &keys {:sec seconds
+ :min minutes
+ :hour hours
+ :mday month-day
+ :mon month
+ :year year}]
+ (assert (= (type time) :date/time))
+ (let [l (:localtime time)
+ p (partial put-date l)]
+ (p :sec seconds)
+ (p :min minutes)
+ (p :hour hours)
+ (p :mday month-day)
+ (p :mon month)
+ (p :year year)
+ (:mktime! l))) # mktime! is slightly more efficient and we're going to GC l anyway
-# macos has a bug in its libc that makes it misinterpret gmtime outputs
-# as localtime under certain conditions, so the gmtime tests are skipped
-# TODO: UTC tests
-(unless (platform :macos))
+# all supported keys can be given a function
+(assert (< now (update-time now :sec inc)))
+(assert (> now (update-time now :sec dec)))
-# TODO: building a UTC datetime
+# or a value to set them to
+(assert (< now (update-time now :sec 61)))
+(assert (> now (update-time now :sec -1)))