Encode/decode-universal-time and DST

Scott L. Burson Scott at sympoiesis.com
Mon Nov 9 01:44:42 UTC 2015


Using local-time is not a bad idea, but I worked up a patch for the
existing code anyway.  Attached.

I tried to run the test suite, as requested on the Contributing page,
but it's looking for '../ansi-test/rt-package.lsp' which I don't have,
and don't see in the repo.

-- Scott

On Sat, Nov 7, 2015 at 7:20 AM, Mark Evenson <evenson at panix.com> wrote:
> On 11/2/15 19:26, Scott L. Burson wrote:
>> On Mon, Nov 2, 2015 at 2:34 AM, Mark Evenson <evenson at panix.com> wrote:
>>>
>>> On 2015/11/2 04:39, Scott L. Burson wrote:
>>>> Hi,
>>>>
>>>> As daylight-saving time ended in the US today, I discovered that ABCL's
>>>> interpretation of the CL spec concerning the behavior of
>>>> 'encode/decode-universal-time' around DST is not the usual one.
> […]
>>
>>> If _time-zone_ is supplied, no adjustment for daylight savings time is performed.
>>
>> -- With no statement of what happens when the time zone _isn't_ supplied.
>>
>> That's why I was at pains to show that the "time of the time"
>> interpretation is the de facto standard -- and has been, all the way
>> back to Zetalisp, at least.
>>
>>> In general, we developers (if I may be said to speak for the group) tend
>>> to go the way of the majority of active, open source implementations in
>>> the idea that we should provide the "least surprise" to our users.
>>
>> That would certainly be my recommendation :-)
>>
> […]
>
>> Anyone interested in this area should also be aware of the
>> "local-time" package [0].  I'm not using it, but maybe I should be :-)
>>
>> [0] https://common-lisp.net/project/local-time/
>>
>> -- Scott
>>
>
> Any argument about just using local-time from ABCL?  Setting the special
> *use-political-time* seems to be all that is needed.  I would throw
> local-time into ABCL-CONTRIB if the licensing can be shown to be compatible.
>
> --
> "A screaming comes across the sky.  It has happened before, but there
> is nothing to compare to it now."
-------------- next part --------------
Index: src/org/armedbear/lisp/Time.java
===================================================================
--- src/org/armedbear/lisp/Time.java	(revision 14839)
+++ src/org/armedbear/lisp/Time.java	(working copy)
@@ -117,19 +117,34 @@
       @Override
       public LispObject execute()
       {
-        TimeZone tz = TimeZone.getDefault();
-        //int offset = tz.getOffset(System.currentTimeMillis());
-        // Classpath hasn't implemented TimeZone.getOffset(long).
-        int rawOffset = tz.getRawOffset();
-        final boolean inDaylightTime =
-          tz.inDaylightTime(new Date(System.currentTimeMillis()));
-        if (inDaylightTime)
-          rawOffset += tz.getDSTSavings();
-        // "Time zone values increase with motion to the west..."
-        // Convert milliseconds to hours.
-        return LispThread.currentThread().setValues(
-          Fixnum.getInstance(- rawOffset).divideBy(Fixnum.getInstance(3600000)),
-          inDaylightTime ? T : NIL);
+        return getTimeZone(System.currentTimeMillis());
       }
     };
+
+  private static final LispObject getTimeZone(long unixTimeMillis) {
+    TimeZone tz = TimeZone.getDefault();
+    //int offset = tz.getOffset(System.currentTimeMillis());
+    // Classpath hasn't implemented TimeZone.getOffset(long).
+    int rawOffset = tz.getRawOffset();
+    final boolean inDaylightTime =
+      tz.inDaylightTime(new Date(unixTimeMillis));
+    if (inDaylightTime)
+      rawOffset += tz.getDSTSavings();
+    // "Time zone values increase with motion to the west..."
+    // Convert milliseconds to hours.
+    return LispThread.currentThread().setValues(
+      Fixnum.getInstance(- rawOffset).divideBy(Fixnum.getInstance(3600000)),
+      inDaylightTime ? T : NIL);
+  }
+
+  // ### get-time-zone universal-time => hours-west daylight-p
+  private static final Primitive GET_TIME_ZONE =
+    new Primitive("get-time-zone", PACKAGE_SYS, false)
+    {
+      @Override
+      public LispObject execute(LispObject arg)
+      {
+        return getTimeZone((arg.longValue() - 2208988800L) * 1000);
+      }
+    };
 }
Index: src/org/armedbear/lisp/time.lisp
===================================================================
--- src/org/armedbear/lisp/time.lisp	(revision 14839)
+++ src/org/armedbear/lisp/time.lisp	(working copy)
@@ -53,7 +53,7 @@
     (if time-zone
         (setf seconds-west (* time-zone 3600)
               daylight nil)
-        (multiple-value-bind (time-zone daylight-p) (default-time-zone)
+        (multiple-value-bind (time-zone daylight-p) (get-time-zone universal-time)
           (setf seconds-west (* time-zone 3600)
                 daylight daylight-p)))
     (multiple-value-bind (weeks secs)
@@ -142,4 +142,7 @@
                              (- (leap-years-before year)
                                 (leap-years-before fake-year))))))))
           (t
-           (+ second (* (+ minute (* (+ hours (default-time-zone)) 60)) 60))))))
+           (let* ((tz-guess (get-time-zone (* hours 3600)))
+		  (guess (+ second (* 60 (+ minute (* 60 (+ hours tz-guess))))))
+		  (tz (get-time-zone guess)))
+	     (+ guess (* 3600 (- tz tz-guess))))))))


More information about the armedbear-devel mailing list