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