Ticket #934 (closed enhancement: fixed)

Opened 2 years ago

Last modified 2 years ago

ENCODE-UNIVERSAL-TIME returns negative values for times before 1900

Reported by: fare Owned by:
Priority: normal Milestone:
Component: ANSI CL Compliance Version: trunk
Keywords: Cc:

Description

Ethan H. Schwartz 2009-08-03 11:09:54 EDT

The CLHS says: Universal time is an absolute time represented as a single non-negative integer---the number of seconds since midnight, January 1, 1900 GMT [...] Because universal time must be a non-negative integer, times before the base time of midnight, January 1, 1900 GMT cannot be processed by Common Lisp.

 http://www.lispworks.com/documentation/HyperSpec/Body/25_adb.htm

? (ENCODE-UNIVERSAL-TIME 0 0 19 31 12 1899) 0 ? (ENCODE-UNIVERSAL-TIME 59 59 18 31 12 1899) -1

The right thing to do would probably be to signal a type error.

Change History

comment:1 Changed 2 years ago by fare

This was ITA bug 65449.

comment:2 Changed 2 years ago by fare

Comment 2 Paul Weiss 2009-08-19 22:30:24 EDT

I realize that the spec says that it should be a non-megative integer, but CCL doesn't even return the correct non-negative integer when year < 1900:

QRES-GDS> (- (encode-universal-time 0 0 0 1 3 1804 0)

(encode-universal-time 0 0 0 29 2 1804 0))

0 QRES-GDS> (- (encode-universal-time 0 0 0 1 3 1904 0) (encode-universal-time 0 0 0 29 2 1904 0)) 86400

I'm pretty sure that 3/1/1804 and 2/29/1804 were not the same day, were they?

comment:3 Changed 2 years ago by fare

For reference, pgweiss committed on 2009-08-21 15:09:27 EDT a workaround in our library, shadowing the CL encode/decode universal-time primitives, which in addition to non-standardly returning a negative result to suit some of our tests, is probably not actually valid before the adoption of the Gregorian calendar (which varies depending on country):

(defconstant-equal +400-years-of-seconds+  
  (- (cl:encode-universal-time 0 0 0 1 4 (+ 400 2010) 0) 
     (cl:encode-universal-time 0 0 0 1 4 2010 0)) 
  "The number of seconds in four hundred years") 
 
(defun encode-universal-time (second minute hour date month year &optional time-zone) 
  "Extend to return negative values for years < 1900" 
  (check-type year (integer 0)) 
  (if (< 99 year 1900) 
    (- (encode-universal-time second minute hour date month (+ year 400) time-zone) 
       +400-years-of-seconds+) 
    (cl:encode-universal-time second minute hour date month year time-zone))) 
 
(defun decode-universal-time (universal-time &optional time-zone) 
  "Extend to decode negative numbers" 
  (if (< universal-time 0) 
    (multiple-value-bind (second minute hour date month year day daylight timezone) 
        (decode-universal-time (+ universal-time +400-years-of-seconds+) time-zone) 
      (values second minute hour date month (- year 400) day daylight timezone)) 
    (cl:decode-universal-time universal-time time-zone)))

comment:4 Changed 2 years ago by gb

  • Type changed from defect to enhancement

comment:5 Changed 2 years ago by gb

  • Status changed from new to closed
  • Resolution set to fixed

(In [15304]) DECODE-UNIVERSAL-TIME: handle time-zone arg correctly.

ENCODE-UNIVERSAL-TIME: explicitly typecheck args, check for valid combinations of year/month/day. If we somehow would get a negative answer, error.

Fixes ticket:934.

Note: See TracTickets for help on using tickets.