Post Reply 
Deltadays and date functions.
05-12-2017, 08:04 PM
Post: #21
RE: Deltadays and date functions.
(05-10-2017 01:28 PM)Vtile Wrote:  I have been in seach of simple algorithm to calculate dDays between two dates.

Now that various aspects of the algorithm have been discussed, here are three complete program listings for the 15C. Enter day [ENTER] month [ENTER] year, call [D] and get a serial number that allows to calculate the number of days between two dates by simple subtraction.

1. Compact version (33 steps), works for dates between 1 Mar 1900 and 28 Feb 2100.
If you want the Julian day number, add 1720982 to the result.

Code:
001  LBL D
002  STO 0
003  R↓
004  3
005  x≤y?
006  GTO 0
007  +
008  9
009  +
010  1
011  STO-0
012  LBL 0
013  R↓
014  1
015  +
016  3
017  0
018  ,
019  6
020  x
021  INT
022  +
023  RCL 0
024  3
025  6
026  5
027  ,
028  2
029  5
030  x
031  INT
032  +
033  RTN

2. Standard version (44 steps) that works down to the first day of the Gregorian calendar (15 Oct 1582).
If you want the Julian day number, add 1720997 to the result.

Code:
001  LBL D
002  STO 0
003  R↓
004  3
005  x≤y?
006  GTO 0
007  +
008  9
009  +
010  1
011  STO-0
012  LBL 0
013  R↓
014  1
015  +
016  3
017  0
018  ,
019  6
020  x
021  INT
022  +
023  RCL 0
024  3
025  6
026  5
027  ,
028  2
029  5
030  x
031  INT
032  +
033  RCL 0
034  EEX
035  2
036  /
037  INT
038  -
039  LSTx
040  4
041  /
042  INT
043  +
044  RTN

3. Deluxe version (64 steps) with automatic switch between Julian and Gregorian calendar (4↔15 Oct 1582). Works down to 1 Mar 0000, returns Julian day number.

Code:
001  LBL D
002  STO 0
003  R↓
004  3
005  x≤y?
006  GTO 0
007  +
008  9
009  +
010  1
011  STO-0
012  LBL 0
013  R↓
014  1
015  +
016  3
017  0
018  ,
019  6
020  x
021  INT
022  +
023  RCL 0
024  3
025  6
026  5
027  ,
028  2
029  5
030  x
031  INT
032  +
033  5
034  7
035  8
036  1
037  6
038  5
039  -
040  x≤0? (TEST 4)
041  GTO 1
042  RCL 0
043  EEX
044  2
045  /
046  INT
047  -
048  LSTx
049  4
050  /
051  INT
052  +
053  2
054  +
055  LBL 1
056  2
057  2
058  9
059  9
060  1
061  6
062  0
063  +
064  RTN

In all versions one stack level is preserved so that date differences can be easily calculated with two successive runs of the program.

28 [ENTER] 2 [ENTER] 2100  f[D]  →  2488128 (assuming deluxe version)
  1 [ENTER] 3 [ENTER] 1900  f[D]  →  2415080 (assuming deluxe version)
[–]  →  73048 days

Dieter
Find all posts by this user
Quote this message in a reply
05-12-2017, 11:15 PM
Post: #22
RE: Deltadays and date functions.
It won't work back until 1 March 0000.

There were some differences in the Julian calendar early on. I also understand that there wasn't a year zero.

On the 34S we only claimed that dates before year 8AD can be incorrect.


Pauli
Find all posts by this user
Quote this message in a reply
05-12-2017, 11:58 PM
Post: #23
RE: Deltadays and date functions.
Well nice really nice, thanks for any participants. Interesting subject.

I now understand what the 3/5 does with floor, as 3 changes in five, but I can still not figure out the other parts. I need to make more calculation examples.
Find all posts by this user
Quote this message in a reply
05-13-2017, 01:32 PM
Post: #24
RE: Deltadays and date functions.
(05-12-2017 11:15 PM)Paul Dale Wrote:  It won't work back until 1 March 0000.

There were some differences in the Julian calendar early on. I also understand that there wasn't a year zero.

Yes, the first years after the introduction of the Julian calendar applied the leap year rules differently, so the Julian calendar as we know it was not implemented before sometime between the years 4 and 8.

While there was no year zero, this is a common designation for 1 BC. Likewise 333 BC equals year –332. I think the 34s uses the same convention.

Dieter
Find all posts by this user
Quote this message in a reply
05-13-2017, 01:33 PM
Post: #25
RE: Deltadays and date functions.
(05-12-2017 11:58 PM)Vtile Wrote:  I now understand what the 3/5 does with floor, as 3 changes in five,

?!?

(05-12-2017 11:58 PM)Vtile Wrote:  but I can still not figure out the other parts.

What parts exactly?

Dieter
Find all posts by this user
Quote this message in a reply
05-13-2017, 07:15 PM (This post was last modified: 05-13-2017 08:22 PM by Vtile.)
Post: #26
RE: Deltadays and date functions.
(05-13-2017 01:33 PM)Dieter Wrote:  
(05-12-2017 11:58 PM)Vtile Wrote:  I now understand what the 3/5 does with floor, as 3 changes in five,

?!?
I'm just trying to understand how this behaviour is written on the fraction numbers. I have not had much exposure of "algorithm math" and I haven't though the system from this point of view before.
Code:

1 *(3/5)=0
   (1. State change)
2 *(3/5)=1
3 *(3/5)=1
   (2. State change)
4 *(3/5)=2
   (3. State change)
5 *(3/5)=3
---
6 *(3/5)=3
    (1. State change)
7 *(3/5)=4
8 *(3/5)=4
    (2. State change)
9 *(3/5)=5
    (3. State change)
10*(3/5)=6
Floor("no. of state changes"/"Length of sequence")
It is obvious as it is the same a 1/4 mentioned earlier, but 1/4 is simpler as is 1/10 etc. to internalise from other common uses of fractions. Of course this is also same case without floor operator, the sequence have exactly same number of integer changes, I just have not though it from this point of view as said.

With CEIL operator the nominator gives "no. of different numbers" in sequence length.

Above is not entirely universal, ie. 1/5 if you start look 0 to 4 it doesn't have any change, but.. I'm working on this (self-evidence). Actually this relates also to one oldish topic in here, how the math is written/spoken in different languages, if there is difference how one interpret a fraction if you say one per five or if you say 1 part of five, which atleast here the first case is what I commonly see (conception I have ) in older books while the latter is the more seen on modern books (x per y is almost non-existent .. again conception what I have while thinking of it).

(05-13-2017 01:33 PM)Dieter Wrote:  
(05-12-2017 11:58 PM)Vtile Wrote:  but I can still not figure out the other parts.

What parts exactly?

Dieter
[/quote]
How it then sums up to 31-30-31-31... sequence (I _think_ I know the mechanics in this case, but I still don't understand it intuitively). It does something to do with odd and even summation and and the pattern the fraction creates (the pattern part I need to dive next, to see if there is any common denominator between fractions). But I'm getting there, I just had some unexpected appointments and work in last few days. Smile
Find all posts by this user
Quote this message in a reply
05-13-2017, 08:57 PM
Post: #27
RE: Deltadays and date functions.
(05-13-2017 07:15 PM)Vtile Wrote:  ....much...

I have read this a few times but I am still not sure if I understand you correctly.

So here is a short description of the way the JDN formula works. Forget about everything else and give it a try:

First of all we define that a year starts with 1 March. This way the irregularity in February appears at the very end of a year where it does not matter if for the last day of the year 28 or 29 days are finally added. So January and February are considered months 13 and 14 of the previous year (m:=m+12, y:=y-1).

Since 1 March of "year 0" there were y full years with 365 days each, i.e. 365*y days. Plus one additional day every 4 years, i.e. int(y/4) more days. Remember that Jan and Feb belong to the previous year, so if y is a leap year the one more day is only added for dates in March and later: if y is divisible by 4, y–1 is not and one less day is added.

This way we get the number of days between 1 March 0 and 1 March of year y.

Next we add the number of days from 1 March in year y to the first day of month m.
This is the tricky part - we need a function that returns the accumulated number of days in the previous months since March, i.e. something like this:

Code:
month  #days
  3       0
  4      31
  5      61
  6      92
  7     122
  8     153
  9     184
 10     214
 11     245
 12     275
 13     306
 14     337

Example: at the beginning of month 5 (May) there were 61 days in previous months (31 in March plus 30 in April).

Note that #days adds up only months with 30 or 31 days because February is the last month of the year, so the last added days (306 to 337) are are the 31 in January.

This is a nearly linear function, so a straight line can be interpolated:

Code:
month  30,6*m - 91,4
  3       0,4
  4      31
  5      61,6
  6      92,2
  7     122,8
  8     153,4
  9     184
 10     214,6
 11     245,2
 12     275,8
 13     306,4
 14     337

The interpolation line's slope of 30,6 equals 153/5. This is because the number of days sequence consists of two groups of five months with 31–30–31–30–31 days, i.e. 153 altogether. Which means an average of 30,6 days per month. Note the 153 and 306 days in the table.

Now simply take the integer part of the right column and the result is exactly what we want.
So the days from 1 March to the first day of month m are

int(30,6*m - 91,4) = int(30,6*m + 30,6 – 122) = int(30,6*(m+1)) – 122.

Now we got the number of days in previous years plus the day count until the first of month m. Finally add the day d and we're done.

So the complete formula is

day number = 365*y + int(y/4) + int(30,6*(m+1)) – 122 + d

Since the constant 122 only determines from which day in the past we are counting, it can also be omitted:

day number = 365*y + int(y/4) + int(30,6*(m+1)) + d
or
day number = int(365,25*y) + int(30,6*(m+1)) + d

This is the simplified method that assumes every fourth year is a leap year. As it is true for the Julian calendar, or the Gregorian calendar between 1 Mar 1900 and 28 Feb 2100.

For a correct implementation of the complete Gregorian calendar we have to add the 100-year- and 400-year-exceptions: Subtract the century years that are no leap years, and finally add back the 400-year cases that are. So the result is

day number = 365*y + int(y/4) – int(y/100) + int(y/400) + int(30,6*(m+1)) + d
or
day number = int(365,25*y) – int(y/100) + int(y/400) + int(30,6*(m+1)) + d

Or with integer arithmetics, where "div" denotes an integer division:

day number = 365*y + y div 4 – y div 100 + y div 400 + (153*(m+1)) div 5 + d

That's all. No magic, just simple math. ;-)

Dieter
Find all posts by this user
Quote this message in a reply
05-13-2017, 10:30 PM (This post was last modified: 05-13-2017 11:03 PM by Vtile.)
Post: #28
RE: Deltadays and date functions.
Sorry, I'm actually not speaking date/JDN formula anymore on that above post, but how the sequences are formed with the fractions (and floor function/operator). Big Grin I must stop mixing this thread with my reverse-engineering of that int(153*(m+1)/5).

I will return from this sidetrack soon (in a few days). Again I need to thank you for your thorough explanation in above post, I'll look that (with great pleasure) and the previous long and thoughfull explations in a few days with better attention span (when I get my sidetrack sorted out or loose interest of it.). Smile

My side track atm. is just to see how in example:
1,2,3,4,5,6,7,8 (A1...An)
turns to (B1...Bn):
(0),2,4,7,9,11,14,16,18,21
with Bn-(B(n-1))
2,2,3,2,2,3,2,2,3
When A is multiplied with 7/3

.. I'll getting hang of it slowly. Ie. 25/7 creates rather amusing pattern, since 4/7 is rather interesting as it is kind of mirroring fractions 2/3 pattern. My wording is gibberish and propably doesn't make sense, especially since I don't have right mathematical terms I suppose.
Find all posts by this user
Quote this message in a reply
05-14-2017, 05:21 PM (This post was last modified: 05-14-2017 05:29 PM by Dieter.)
Post: #29
RE: Deltadays and date functions.
(05-12-2017 11:15 PM)Paul Dale Wrote:  It won't work back until 1 March 0000.

There were some differences in the Julian calendar early on. I also understand that there wasn't a year zero.

On the 34S we only claimed that dates before year 8AD can be incorrect.

Of course Pauli is right regarding the first AD years. Also the Julian calendar was introduced as late as 46 BC, and JDN calculations for all dates before this assume that the calendar's final form was used even centuries and millenniums before. But this assumption is common practice (proleptic calendar), just as the astronomical year numbering where e.g. 333 BC equals year –332. All this is also the way the 34s works.

So here finally is another program version for the 15C (and most other classic RPN HPs) that – with the mentioned caveats – works down to 1 Jan –4712, i.e. 1 Jan 4713 BC, which is considered day 0 of the Julian day number system. Using a small trick, the missing floor() function for negative years was replaced with the 15C's int().

Code:
001  LBL D
002  STO 0
003  R↓
004  3
005  x≤y?
006  GTO 0
007  +
008  9
009  +
010  1
011  STO-0
012  LBL 0
013  R↓
014  1
015  +
016  3
017  0
018  ,
019  6
020  x
021  INT
022  +
023  RCL 0
024  4
025  7
026  1
027  6
028  +
029  3
030  6
031  5
032  ,
033  2
034  5
035  x
036  INT
037  +
038  1
039  5
040  2
041  4
042  -
043  2
044  2
045  9
046  9
047  1
048  6
049  1     ' 2299161 is JDN of first day of Gregorian calendar, 15 Oct 1582
050  x>y?  ' TEST 7 on 15C
051  GTO 1
052  R↓
053  RCL 0
054  EEX
055  2
056  /
057  INT
058  -
059  LSTx
060  4
061  /
062  INT
063  +
064  2
065  +
066  ENTER
067  LBL 1
068  CLX
069  +
070  RTN

Check:
  1 [ENTER]  1  [ENTER] -4712  f[D] → 0
  4 [ENTER] 10 [ENTER]  1582  f[D] → 2299160
15 [ENTER] 10 [ENTER]  1582  f[D] → 2299161
  4 [ENTER]  7  [ENTER]  1979  f[D] → 2444059

As usual, the program does the transition between Julian and Gregorian calendar on the official switch date, i.e. from 4 to 15 Oct 1582 (cf. example above). You may adjust this date by changing the hardcoded constant 2299161 (JDN of 15 Oct 1582) to another value that reflects your local situation. This value is obtained by determining the JDN of the first Gregorian date (using the unmodified program). For instance in Great Britain and its colonies, including the US, 2 Sep 1752 was followed by 14 Sep 1752. So enter 14 Sep 1752 and get 2361222, which then is the value to code in line 043...049.

Dieter
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: