From: Vladimir Zolotykh
Subject: Subtracting dates and DST
Date: 
Message-ID: <opsjeu2cia8k218c@news.eurocom.od.ua>
Hi,

Suppose I want to calculate the difference between two dates
(represented as universal time) in days. Do you think the following
function would do

   (defun delta-days (date-1 date-2)
     (let ((zone-1 (nth-value 8 (decode-universal-time date-1)))
	  (zone-2 (nth-value 8 (decode-universal-time date-2))))
       (if (= zone-1 zone-2)
	(- (floor date-2 86400)
	   (floor date-1 86400))
	(- (floor (- date-2 (* 3600 zone-2)) 86400)
	   (floor (- date-1 (* 3600 zone-1)) 86400)))))

or I should also account daylight-p returned by decode-universal-time
like the following

   (defun delta-days (date-1 date-2)
     (let ((zone-1 (nth-value 8 (decode-universal-time date-1)))
	  (zone-2 (nth-value 8 (decode-universal-time date-2)))
	  (daylight-p-1 (nth-value 7 (decode-universal-time date-1)))
	  (daylight-p-2 (nth-value 7 (decode-universal-time date-2)))
       (if (= zone-1 zone-2)
	(- (floor date-2 86400)
	   (floor date-1 86400))
	(- (floor (- date-2 (* 3600 zone-2) (if daylight-p-2 -3600 0)) 86400)
	   (floor (- date-1 (* 3600 zone-1) (if daylight-p-1 -3600 0)) 86400))))))

This DST constantly puzzles me.

Thanks in advance


-- 
Vladimir Zolotykh 

From: ···············@gmail.com
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <1103727860.607923.91420@z14g2000cwz.googlegroups.com>
Universal time is the number of seconds since some 0 point--it doesn't
matter when that was exactly. There are 24*60*60 seconds in a day, so
the difference in days between any two universal times :
(defun delta-days (ut1 ut2) (/ (- ut1 ut2) 86400))
From: Pascal Bourguignon
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <878y7qcqs0.fsf@thalassa.informatimago.com>
···············@gmail.com writes:

> Universal time is the number of seconds since some 0 point--it doesn't
> matter when that was exactly. There are 24*60*60 seconds in a day, 

It depends on what you call a day.  There are not 86400 seconds in a
solar day, and neither in a sideral day, or in a UTC day.  There are
not 86400 seconds in a legal day hit by DST change.


> so the difference in days between any two universal times :
> (defun delta-days (ut1 ut2) (/ (- ut1 ut2) 86400))

Only if you _define_ "day" to _be_ 86400 seconds.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
The rule for today:
Touch my tail, I shred your hand.
New rule tomorrow.
From: Stefan Scholl
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <17eca4ihlzv79.dlg@parsec.no-spoon.de>
On 2004-12-22 16:10:39, Pascal Bourguignon wrote:
> ···············@gmail.com writes:
>> Universal time is the number of seconds since some 0 point--it doesn't
>> matter when that was exactly. There are 24*60*60 seconds in a day, 
> 
> It depends on what you call a day.  There are not 86400 seconds in a
> solar day, and neither in a sideral day, or in a UTC day.  There are
> not 86400 seconds in a legal day hit by DST change.

This matters when Will wants to enter the Stargate at the exact time
of a solar flare to travel the right amount of years back into his
own time.
From: Steven M. Haflich
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <oUMyd.2080$5R.801@newssvr21.news.prodigy.com>
Pascal Bourguignon wrote:

> Only if you _define_ "day" to _be_ 86400 seconds.

It's actually worse than you think.  UTC is adjusted by leap seconds
now and then to keep UTC synchronized with the earth's rotation.
Most computer time systems basically ignore leap seconds, but that
means the CL time functions are not sufficient for computing elapsed
times (or doing astromomical calculations) between distant times
recorded in UTC.

See http://tycho.usno.navy.mil/leapsec.html and neighboring pages for
more than you ever wanted to know about time.  For even more than that,
with a CL perspective, dig up some of Erik Naggum's writings on the
subject.

However, if the original problem is to determine the number of `days'
between two UTCs, then something like

   (round (abs (- utc1 utc2)) 86400)

will produce an intuitively reasonable integer answer for any time of
interest.
From: ···············@gmail.com
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <1103935532.683841.40020@z14g2000cwz.googlegroups.com>
OK.

Define a "day" to be 86,400 seconds. Feel better?

(If anyone really needs code that takes leap seconds into account,
etc., let me know.)

Will Fitzgerald
From: Pascal Bourguignon
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <87hdmecr8e.fsf@thalassa.informatimago.com>
Vladimir Zolotykh <······@eurocom.od.ua> writes:

> Hi,
> 
> Suppose I want to calculate the difference between two dates
> (represented as universal time) in days. Do you think the following
> function would do
> 
>    (defun delta-days (date-1 date-2)
>      (let ((zone-1 (nth-value 8 (decode-universal-time date-1)))
> 	  (zone-2 (nth-value 8 (decode-universal-time date-2))))
>        (if (= zone-1 zone-2)
> 	(- (floor date-2 86400)
> 	   (floor date-1 86400))
> 	(- (floor (- date-2 (* 3600 zone-2)) 86400)
> 	   (floor (- date-1 (* 3600 zone-1)) 86400)))))
> 
> or I should also account daylight-p returned by decode-universal-time
> like the following
> 
>    (defun delta-days (date-1 date-2)
>      (let ((zone-1 (nth-value 8 (decode-universal-time date-1)))
> 	  (zone-2 (nth-value 8 (decode-universal-time date-2)))
> 	  (daylight-p-1 (nth-value 7 (decode-universal-time date-1)))
> 	  (daylight-p-2 (nth-value 7 (decode-universal-time date-2)))
>        (if (= zone-1 zone-2)
> 	(- (floor date-2 86400)
> 	   (floor date-1 86400))
> 	(- (floor (- date-2 (* 3600 zone-2) (if daylight-p-2 -3600 0)) 86400)
> 	   (floor (- date-1 (* 3600 zone-1) (if daylight-p-1 -3600 0)) 86400))))))
> 
> This DST constantly puzzles me.
> 
> Thanks in advance

Well, it depends on what you call a day?  


If it's the Earth rotation, or if you need precision to the second,
you'd have to take into account leap seconds.

  Happily, or unhappily depending on what dates interest you, Common
  Lisp specifies its so called "universal" time as the _positive_ number
  of seconds since 1900-01-01 00;00:00, and _ignoring_ leap seconds.

  Well when you have a number of seconds, you cannot _ignore_ some
  seconds. What this means is that the functions that convert between
  univeral time and decoded time DO ignore the leap seconds.
  Note that GPS is not adjusted for leap seconds.

  And assuming we're dealing only with dates between 1900-01-01 and now,
  the number of leap seconds is quite limited.

  Note that TAI (International Atomic Time) and GPS are not adjsuted for
  leap seconds either.

  http://tycho.usno.navy.mil/leapsec.html

      Since the first leap second in 1972, all leap seconds have been
      positive and there were 22 leap seconds in the 27 years to
      January, 1999.

      As of 1 January 1999,
          TAI is ahead of UTC   by 32 seconds.
          GPS is ahead of UTC   by 13 seconds.



If what you call a day is 86400 seconds, then go ahead.  This won't
work for historical programs nor for long term programs.
http://www.longnow.org/


In any case, you can always use your own type for time, and implement
your own routines converting "legal" or "usal" day and time names for
any historical time and place.


I'm wondering if this:

 Function DECODE-UNIVERSAL-TIME
 Affected By:
   Implementation-dependent mechanisms for calculating when or if
   daylight savings time is in effect for any given session.

means that DST cannot be changed for the duration of a session. What
about lisp sessions running several years a go?

In any case, it's safe to check the zone between two calls of
DECODE-UNIVERSAL-TIME.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

6 jours, 16 heures, 5 minutes depuis la nouvelle lune.
Nous sommes le 2 Nivose An CCXIII
From: ··············@hotmail.com
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <1103761528.395994.320550@z14g2000cwz.googlegroups.com>
The example in the same section seems to refer to the possibility that
DST could change between two calls to decode-universal-time.

I agree with you in general that the original poster needs to be much
clearer about what concept of "day" he means to calculate. That is
probably a legal or political question, not a technical one.

One important thing that seems to have been missed is that the
time-zone in question is either the one specified by the user in the
call or the one that is apparently in effect for the Lisp session,
which is almost certainly fixed by the operating system running on the
particular machine.

1) there is no way to be sure that the machine properly reflects the
legal reality of any particular place or jurisdiction

2) universal times, in themselves, do not preserve any sense of a time
zone. the original poster seems to be asking whether universal times
date-1 and date-2 are in different time zones.

2a) The lisp implementation does not know where (in what time zone)
the universal time data was originally generated; indeed, the whole
point of universal time is that it is location-, time-zone-, and
DST-independent.

2b) even if it did, the Lisp implementation only is required to tell
the DST and time-zone at the time (and presumed location) of a
particular call to decode-universal-time. It DOES NOT have a
historical/prospective calendar to tell whether DST was in effect for a
particular time zone at a past or future time.

2c) therefore, the only thing those two calls do is tell whether the
DST of the Lisp session changed; which is almost certainly not what he
intended.

3) The meaning of days in Common Lisp is pretty unambiguously 86400
seconds (see the hyperspec entry for leap seconds); this only means
something for a particular time-zone with a particular value for DST.
As you point out, this definition is not universal, or even useful for
a particular purpose.

--Joe
From: Steven M. Haflich
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <F3Nyd.2083$5R.1631@newssvr21.news.prodigy.com>
··············@hotmail.com wrote:

> 2b) even if it did, the Lisp implementation only is required to tell
> the DST and time-zone at the time (and presumed location) of a
> particular call to decode-universal-time. It DOES NOT have a
> historical/prospective calendar to tell whether DST was in effect for a
> particular time zone at a past or future time.

A given CL implementation indeed _might_ have all this information at
it's dispasal.  Locales and time zone support are supposed to be able
to account for these things, and the CL implementation can tap these
resources if the implementors and users agree that it is worth the
bother.  Allegro has the following block of comments explaining the
code that covers recent USA time zones:

   ;; time is seconds in this year.
   ;; return t if daylight savings time is in effect
   ;; This is USA specific
   ;; current rule:
   ;;       it begins at 2am (unadjusted time) on the first sunday in april
   ;;       and ends  at 1am (unadjusted time) on the last sunday in october
   ;;  		[thus it ends at 2am (daylight-savings-time)]
   ;; rule before and including 1987
   ;;       it begins at 2am (unadjusted time) on the last sunday in april
   ;;       and ends  at 1am (unadjusted time) on the last sunday in october
   ;;  		[thus it ends at 2am (daylight-savings-time)]
   ;;   except: in 1974 it ran from jan 6 to the last sunday in nov
   ;;		in 1975 it ran from the last sunday in feb to last sunday in
   ;;		 oct.

Both time zones and daylight savings time are human creations established by
legislation.  Australia and Afghanistan have (or historically have had) time
zones respectively with 1/2 and 1/3 hour shifts.  That is why the ANS allow
the tmie zone to be set in 1/3600 increments, but regardless, the standard
CL machinery is nowhere near sufficient to support sophisticated time
calculations.
From: ··············@hotmail.com
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <1103872707.275615.66530@z14g2000cwz.googlegroups.com>
Yes, computers can be taught the rules; I was trying to make a clear
point, rather than allow for a "sufficiently smart environment."

As far as the US goes, to quote
http://www.boulder.nist.gov/timefreq/general/daylightsavingtime.html

Daylight Saving Time, for the U.S. and its territories, is NOT observed
in Hawaii, American Samoa, Guam, Puerto Rico, the Virgin Islands, the
Eastern Time Zone portion of the State of Indiana, and by most of
Arizona (with the exception of the Navajo Indian Reservation in
Arizona).

The rule is that if a place decides to use daylight savings time, it
must change on the specified dates.

This is all very hard to get right in an automated way.

As for the original poster, his clarification apparently indicates he
wishes to treat calendar dates; in which case he was probably looking
for a shortcut to avoid making a days-in-the-month table and having to
deal with leap years.

*Assuming* the universal times were generated in the timezone that the
caller specifies, it seems safe to normalize to noon on the dates in
question: i.e., coerce the hours:minutes of the decoded time to 12:00.
It seems the only time DST would matter (for the US) is for
universal-times in the 1 to 3 a.m. window, in which case dropping or
gaining 3600 seconds could cross a 86400-second interval. Leap seconds
happen at midnight.

If, on the other hand, we don't know where the universal-time was
generated, we have no way to decide what calendar date is relevant.
From: Vladimir Zolotykh
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <opsjge7zgp8k218c@news.eurocom.od.ua>
The only thing I actually want is to convert the date say December 3d
2004 to the number of days elapsed since the another predetermined day
e.g January 1st 1900. I'm not interested in seconds at all.

I was wondering only if the function I mentioned in my post suits this
purpose. Maybe there is a simpler way to achive the same. I googled
for it for a reasonable time but didn't find no applicable solution.


On 22 Dec 2004 16:00:49 +0100, Pascal Bourguignon <····@mouse-potato.com> 
wrote:

> Vladimir Zolotykh <······@eurocom.od.ua> writes:
>
>> Hi,
>>
>> Suppose I want to calculate the difference between two dates
>> (represented as universal time) in days. Do you think the following
>> function would do
>>
>>    (defun delta-days (date-1 date-2)
>>      (let ((zone-1 (nth-value 8 (decode-universal-time date-1)))
>> 	  (zone-2 (nth-value 8 (decode-universal-time date-2))))
>>        (if (= zone-1 zone-2)
>> 	(- (floor date-2 86400)
>> 	   (floor date-1 86400))
>> 	(- (floor (- date-2 (* 3600 zone-2)) 86400)
>> 	   (floor (- date-1 (* 3600 zone-1)) 86400)))))
>>
>> or I should also account daylight-p returned by decode-universal-time
>> like the following
>>
>>    (defun delta-days (date-1 date-2)
>>      (let ((zone-1 (nth-value 8 (decode-universal-time date-1)))
>> 	  (zone-2 (nth-value 8 (decode-universal-time date-2)))
>> 	  (daylight-p-1 (nth-value 7 (decode-universal-time date-1)))
>> 	  (daylight-p-2 (nth-value 7 (decode-universal-time date-2)))
>>        (if (= zone-1 zone-2)
>> 	(- (floor date-2 86400)
>> 	   (floor date-1 86400))
>> 	(- (floor (- date-2 (* 3600 zone-2) (if daylight-p-2 -3600 0)) 86400)
>> 	   (floor (- date-1 (* 3600 zone-1) (if daylight-p-1 -3600 0)) 
>> 86400))))))
>>
>> This DST constantly puzzles me.
>>
>> Thanks in advance
>
> Well, it depends on what you call a day?
>
>
> If it's the Earth rotation, or if you need precision to the second,
> you'd have to take into account leap seconds.
>
>   Happily, or unhappily depending on what dates interest you, Common
>   Lisp specifies its so called "universal" time as the _positive_ number
>   of seconds since 1900-01-01 00;00:00, and _ignoring_ leap seconds.
>
>   Well when you have a number of seconds, you cannot _ignore_ some
>   seconds. What this means is that the functions that convert between
>   univeral time and decoded time DO ignore the leap seconds.
>   Note that GPS is not adjusted for leap seconds.
>
>   And assuming we're dealing only with dates between 1900-01-01 and now,
>   the number of leap seconds is quite limited.
>
>   Note that TAI (International Atomic Time) and GPS are not adjsuted for
>   leap seconds either.
>
>   http://tycho.usno.navy.mil/leapsec.html
>
>       Since the first leap second in 1972, all leap seconds have been
>       positive and there were 22 leap seconds in the 27 years to
>       January, 1999.
>
>       As of 1 January 1999,
>           TAI is ahead of UTC   by 32 seconds.
>           GPS is ahead of UTC   by 13 seconds.
>
>
>
> If what you call a day is 86400 seconds, then go ahead.  This won't
> work for historical programs nor for long term programs.
> http://www.longnow.org/
>
>
> In any case, you can always use your own type for time, and implement
> your own routines converting "legal" or "usal" day and time names for
> any historical time and place.
>
>
> I'm wondering if this:
>
>  Function DECODE-UNIVERSAL-TIME
>  Affected By:
>    Implementation-dependent mechanisms for calculating when or if
>    daylight savings time is in effect for any given session.
>
> means that DST cannot be changed for the duration of a session. What
> about lisp sessions running several years a go?
>
> In any case, it's safe to check the zone between two calls of
> DECODE-UNIVERSAL-TIME.
>



-- 
Vladimir Zolotykh 
From: Brian Downing
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <zxDyd.230182$5K2.180360@attbi_s03>
In article <··············@thalassa.informatimago.com>,
Pascal Bourguignon  <····@mouse-potato.com> wrote:
>   Note that TAI (International Atomic Time) and GPS are not adjsuted for
>   leap seconds either.
> 
>   http://tycho.usno.navy.mil/leapsec.html
> 
>       Since the first leap second in 1972, all leap seconds have been
>       positive and there were 22 leap seconds in the 27 years to
>       January, 1999.
> 
>       As of 1 January 1999,
>           TAI is ahead of UTC   by 32 seconds.
>           GPS is ahead of UTC   by 13 seconds.

My GPS receiver returns the same value as UTC here.   (Albeit on the
screen; I haven't checked the NMEA data.)

Where does it get the leap second correction factor?

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Brian Downing
Subject: Re: Subtracting dates and DST
Date: 
Message-ID: <8CDyd.700172$mD.197668@attbi_s02>
In article <·······················@attbi_s03>,
Brian Downing  <·············@lavos.net> wrote:
> My GPS receiver returns the same value as UTC here.   (Albeit on the
> screen; I haven't checked the NMEA data.)
> 
> Where does it get the leap second correction factor?

Never mind - I could try reading first:

| For GPS, the leap second correction contained within the UTC data of
| subframe 4, page 18 of the navigation message transmitted by
| satellites will change.
| 
|      Before the leap second
|      GPS-UTC = +12 (i.e., GPS is ahead of UTC by twelve seconds)
| 
|      After the leap second
|      GPS-UTC = +13s (i.e., GPS will be ahead by thirteen seconds)

(from http://tycho.usno.navy.mil/leap.html)

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net>