Encode/decode-universal-time and DST

Scott L. Burson Scott at sympoiesis.com
Mon Nov 9 02:03:06 UTC 2015


Oops -- didn't realize I needed to add an autoload.  Updated patch attached.

(Is email the way you like to receive patches?)

-- Scott


On Sun, Nov 8, 2015 at 5:44 PM, Scott L. Burson <Scott at sympoiesis.com> wrote:
> 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))))))))
Index: src/org/armedbear/lisp/Autoload.java
===================================================================
--- src/org/armedbear/lisp/Autoload.java	(revision 14839)
+++ src/org/armedbear/lisp/Autoload.java	(working copy)
@@ -627,6 +627,7 @@
         autoload(PACKAGE_SYS, "function-info", "function_info");
         autoload(PACKAGE_SYS, "get-cached-emf", "EMFCache", true);
         autoload(PACKAGE_SYS, "get-function-info-value", "function_info");
+        autoload(PACKAGE_SYS, "get-time-zone", "Time");
         autoload(PACKAGE_SYS, "hash-table-entries", "HashTableFunctions");
         autoload(PACKAGE_SYS, "hash-table-entries", "HashTableFunctions");
         autoload(PACKAGE_SYS, "layout-class", "Layout", true);


More information about the armedbear-devel mailing list