HP Forums
Year(s) Month(s) Day(s) between 2 dates - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: Not HP Calculators (/forum-7.html)
+--- Forum: Not quite HP Calculators - but related (/forum-8.html)
+--- Thread: Year(s) Month(s) Day(s) between 2 dates (/thread-4969.html)

Pages: 1 2


Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-19-2015 09:33 AM

Hi, I've ported routine of mine from HP41cx to WP34s. Off course it's programmed "à la 41". I wonder if it's a way to load in one list the "31 STO 01 STO 03 etc.", I've check anywhere but I don't find. If it's possible, code will be less longer and speed up. All comments or ideas will be welcome. This routine is precise because we work with really numbers of days into month.

Do XEQ'YMD', ENTER DATE 1 RS (NOT ENTER !) DATE 2 RS (NOT ENTER !)
Enjoy.

Gérard.
Code:

01 LBL'YMD'
02 SSIZE8
03 FIX04
04 CLREGS
05 CLSTK
06 CL[alpha]
07 3
08 1
09 STO 01
10 STO 03
11 STO 05
12 STO 07
13 STO 08
14 STO 10
15 STO 12
16 2
17 8
18 STO 02
19 3
20 0
21 STO 04
22 STO 06
23 STO 09
24 STO 11
25 CLx
26 [alpha]'Ent'
27 [alpha]'er '
28 [alpha]'Dat'
29 [alpha]'e 1'
30 PROMPT
31 DATE->
32 RCL Z
33 LEAP?
34 XEQ 00
35 DROP
36 CL[alpha]
37 [alpha]'Ent'
38 [alpha]'er '
39 [alpha]'Dat'
40 [alpha]'e 2'
41 PROMPT
42 DATE->
43 RCL T
44 -
45 x<0?
46 XEQ 01
47 x<>y
48 RCL A
49 -
50 R[up]
51 -
52 0
53 STO D
54 DROP
55 x<0?
56 EXQ 02
57 RCL Z
58 R[up]
59 -
60 R[up]
61 -
62 x<>Z
63 SDR 002
64 +
65 SDR 002
66 +
67 RTN
68 LBL 00
69 2
70 9
71 STO 02
72 DROP
73 RTN
74 LBL 01
75 RCL->A
76 +
77 1
78 STO D
79 DROP
80 RTN
81 LBL 02
82 1
83 STO D
84 DROP
85 1
86 2
87 +
88 RTN
89 -END-

"Voilà".

As an example :


Well, if you use this routine crossing switch Julian Gregorian, keep in mind to minus result for 10 days : DATE1 = 3.101582 DATE2 = 18.101582 DISPLAY 15 days, but only 15-10 = 5 days !

(I hope my english is better since I've an english methode !)

A good day for all.

Gérard.


RE: Year(s) Month(s) Day(s) between 2 dates - Paul Dale - 10-19-2015 10:01 AM

Why not use the built in function [Delta]DAYS for this?

- Pauli


RE: Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-19-2015 10:50 AM

Bonjour Monsieur,

You are right but sometimes we need to know what means 35872 days. For example, my Mother is dead the 18/07/1978 (RIP), Delta days give me 13607 days, the routine give 37 years 3 months and 1 days. It is more speaking to mind I think.

In Historical riserch, it is impossible to use a number of day. In genealogie too IMHO.

Another example, King LOUIS XIV is on trône 14.051643 to 01.09.1715 :

In Delta Days I get 26407 days, with YMD I get 72 years 3 months 18 days, it is more speaking, in this case only years are importants yes.

I submit, in the past, to forum a littlle routine that convert number of days to ymd.

So I agree with you but depending of the point of view !

Gérard.


RE: Year(s) Month(s) Day(s) between 2 dates - TASP - 10-19-2015 02:06 PM

Be careful what you ask for around here.

I'm expecting a short clever routine that generates years, months, weeks, days, hours, minutes and seconds.

And I'm expecting to see it in 0.00000001417 milli-centuries.

Wink Wink Wink


RE: Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-19-2015 02:43 PM

Well, Already on the net, of course you know this !

LOL


RE: Year(s) Month(s) Day(s) between 2 dates - Dieter - 10-21-2015 01:10 PM

(10-19-2015 09:33 AM)ggauny@live.fr Wrote:  I wonder if it's a way to load in one list the "31 STO 01 STO 03 etc.", I've check anywhere but I don't find.

You do not need a list, you can compute the number of days in a month directly. It's just 12 steps on the 34s:

Code:
01 RCL X
02 #008
03 IDIV
04 RCL+ Y
05 #002
06 MOD
07 #002
08 x≠? Z
09 Clx
10 -
11 #030
12 +

If you perfer a closed formula instead of a test: n = 28 + (m + m div 8) mod 2 + 2 · abs(sign(m–2)).
And if February is neglected (:= 30 days) it even boils down to 30 + (m + m div 8) mod 2.

By the way...

(10-19-2015 09:33 AM)ggauny@live.fr Wrote:  This routine is precise because we work with really numbers of days into month

...in many cases there is no "precise" result. The number of days depends on how you count them. This was already discussed in march when we have been talking about this topic in another thread (cf. post #9 and #12).

Dieter


RE: Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-21-2015 01:49 PM

Thanks Dieter for comments, but I really don't understand how works #. I've tried somme example from goods programers like you, but I don't understand.
With my new owner manual, I hope understand...

Good day.

Gérard


RE: Year(s) Month(s) Day(s) between 2 dates - Dieter - 10-21-2015 06:07 PM

(10-21-2015 01:49 PM)ggauny@live.fr Wrote:  Thanks Dieter for comments, but I really don't understand how works #.

Lines starting with a "#" are constants from the CONST menu (h ENTER). For instance, #c is the constant c from this menue, i.e. the speed of light. As a special feature, integers from 0 to 255 can also be entered this way so that they fit in a single line and execute somewhat faster. To enter such a constant, select "# 0 to 255" from the constants menu. This is the very last entry, so simply press "1" to get to the first constant "1/2", then press the up-arrow to move back to the last menu entry, which is "# 0 to 255". After pressing ENTER simply type the number you want, e.g. "123" or "008".

Of course the constants #002 and#008 can just as well be entered as a simple 2 resp. 8, but using the constants here is good pratice as this runs a tiiiiiiiny bit faster. ;-)

Dieter


RE: Year(s) Month(s) Day(s) between 2 dates - Dieter - 10-21-2015 07:22 PM

(10-19-2015 09:33 AM)ggauny@live.fr Wrote:  Hi, I've ported routine of mine from HP41cx to WP34s.

Your program obviously uses a 0 or 1 in register D as a kind of carry bit. This can be done in a simple and more effective way by using a flag. Here is my version for the 34s. It computes the number of days in a month according to the previously posted formula. Flag 00 serves as a kind of carry flag.

Code:
01 LBL"YMD"
02 STO 02
03 DAY
04 x<> Y
05 STO 01
06 DAY
07  -
08 CF 00
09 x≥0?       ; d2 ≥ d1?
10 GTO 01     ; no adjustment required
11 SF 00      ; else set carry flag
12 RCL 02
13 MONTH
14 DEC X      ; month before m2
15 x≠0?
16 SKIP 002
17 DROP       ; if zero
18 #012       ; it's december
19 #002
20 x≠? Y      ; if it's not February
21 GTO 00     ; compute no. of days in month
22 c DROP     ; else drop two levels (complex drop)
23 #028       ; February has 28 days
24 RCL 02
25 LEAP?      ; in leap years
26 INC Y      ; add one day
27 DROP
28  +         ; add #days to d2-d1
29 GTO 01     ; and continue
30 LBL 00
31 DROP
32 RCL X     ;  compute no. of days in month
33 #008
34 IDIV
35  +
36 #002
37 MOD
38 #030
39  +         ; = no. of days in month before m2
40  +         ; add this to d2-d1
41 LBL 01
42 SDR 004    ; move days to 0,00dd
43 RCL 02
44 MONTH
45 FS?C 00
46 DEC X      ; adjust m2 if carry flag set
47 RCL 01
48 MONTH
49  -
50 x≥0?
51 SKIP 003
52 SF 00      ; set carry flag if m2-m1 negative
53 #012       ; add back 12 months
54  +
55 SDR 002    ; move months to 0,mm
56  +         ; add days to get 0,mmdd
57 RCL 02
58 YEAR
59 FS?C 00
60 DEC X      ; adjust y2 if carry flag set
61 RCL 01
62 YEAR
63  -
64  +         ; add years to get y,mmdd
65 END

date1 [ENTER] date2 XEQ"YMD" => y,mmdd
 

Using the WP34s ΔDAYS function, the code gets a bit shorter:

Code:
01 LBL"YMD"
02 STO 02
03 DAY
04 x<> Y
05 STO 01
06 DAY
07  -
08 CF 00
09 x≥0?       ; d2 ≥ d1?
10 GTO 01     ; no adjustment required
11 SF 00      ; else set carry flag
12 RCL 02
13 DATE->
14 DROP
15 DSZ X      ; month before m2
16 SKIP 003   ; is it > 0, i.e. Jan...Nov? Then continue
17 DROP
18 #012       ; if not, month is December
19 DEC Y      ; of previous year
20 RCL 01
21 DAY        ; now stack holds d1, m2-1, year of m2-1
22 ->DATE     ; generate new date = d1 in month before m2
23 RCL 02
24 ΔDAYS      ; days between date2 and d1 in month before date2
25 LBL 01
26 SDR 004    ; move days to 0,00dd
27 RCL 02
28 MONTH
29 FS?C 00
30 DEC X      ; adjust m2 if carry flag set
31 RCL 01
32 MONTH
33  -
34 x≥0?
35 SKIP 003
36 SF 00      ; set carry flag if m2-m1 negative
37 #012       ; add back 12 months
38  +
39 SDR 002    ; move months to 0,mm
40  +         ; add days to get 0,mmdd
41 RCL 02
42 YEAR
43 FS?C 00
44 DEC X      ; adjust y2 if carry flag set
45 RCL 01
46 YEAR
47  -
48  +         ; add years to get y,mmdd
49 END

Edit: corrected an error in the final steps of both programs.

In both cases your Louis XIV example returns 72,0318, i.e. 72 years, 3 months and 18 days.
As usual, comments and corrections are welcome.

Dieter


RE: Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-22-2015 05:16 AM

Hi,

Wowww ! I wonder how is it possible to write so quickly this kind of complicated codes !!!

Of course thank again, I understant better when I se an example and I 'm studiying these elegants and shorts examples.

May be it's what Walter Bonin would say the other day with the Delta DAYS command ? Surely but I had no understood at this time.

Thanks for help and "private school" !

Gérard.


RE: Year(s) Month(s) Day(s) between 2 dates - Paul Dale - 10-22-2015 06:40 AM

(10-21-2015 06:07 PM)Dieter Wrote:  Of course the constants #002 and#008 can just as well be entered as a simple 2 resp. 8, but using the constants here is good pratice as this runs a tiiiiiiiny bit faster. ;-)

I'd say significantly faster knowing the two different code paths involved. Of course neither takes all that long for fast CPU in the 30b unless you do them a lot of times.


- Pauli


RE: Year(s) Month(s) Day(s) between 2 dates - Paul Dale - 10-22-2015 06:49 AM

Don't be too surprised by the rapidity of coding, Dieter has a lot of experience writing programs for the 34S. He is definitely one of the best around and, I believe, better than I am at this despite the fact that I wrote the bulk of the 34S firmware!


- Pauli


RE: Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-22-2015 10:19 AM

Hi,

I AGRRE WITH YOU SIR §


RE: Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-22-2015 11:44 AM

Hallo Dieter,

In your "YMD" version WP 34s, I think it would be better to code step 47 with "DEC Y" and not with "DEC X". With "DEC X" I get an error of plus one year (comparing with my 3 HP 41, one C and two CX, also with my HP 50g).

But may be have-I miss understanding something in your code. In this case I many beg your pardon.

Mister Dale, say that you are the best programer for WP 34s, I think so too !

Programing has so changed since my HP 25 not C and my HP 67 !!!!

Gérard.


RE: Year(s) Month(s) Day(s) between 2 dates - Dieter - 10-22-2015 12:19 PM

(10-22-2015 11:44 AM)ggauny@live.fr Wrote:  In your "YMD" version WP 34s, I think it would be better to code step 47 with "DEC Y" and not with "DEC X". With "DEC X" I get an error of plus one year

It would be better to use the correct solution. #-) Sorry, the listing at this point had two lines mixed up (probably due to a copy&paste error). Changing the code to DEC Y is not the solution. The last RCL 01 command of course has to move three lines below, right before YEAR. I now have corrected both listings, and I also added a change in the second version (line 14 ff.) that saves two steps.

Dieter


RE: Year(s) Month(s) Day(s) between 2 dates - Didier Lachieze - 10-22-2015 04:00 PM

The program from Dieter is extremely well done. However it’s still possible to squeeze out a few steps Smile

Here is a slightly modified version using local registers instead of global ones and without the need for flag 00:

Code:
01 LBL"YMD"   ; stack: date2, date1
02 LocR 005   ; allocate local registers R.00 to R.04
03 STO.02     ; store date2 in R.02
04 DATE->     ; stack: d2, m2, y2, date1
05 X<>Y       ; stack: m2, d2, y2, date1
06 STO.03     ; store m2 in R.03
07 X<>Z       ; stack: y2, d2, m2, date1
08 STO.04     ; store y2 in R.03
09 <>TYZX     ; stack: date1, d2, m2, y2
10 STO.01     ; Store date1 in R.01
11 DAY        ; stack: d1, d2, m2, y2
12  -         ; stack: d2-d1, m2, y2 – LastX: d1
13 x≥0?       ; d2 ≥ d1?
14 SKIP 011   ; no adjustment required, goto step 26
15 DEC.03     ; adjust m2 in R.03
16 DROP       ; stack: m2, y2 – LastX: d1
17 DSZ X      ; month before m2
18 SKIP 003   ; is it > 0, i.e. Jan...Nov? Then continue
19 DROP
20 #012       ; if not, month is December
21 DEC Y      ; of previous year
22 RCL L      ; now stack holds d1, m2-1, year of m2-1
23 ->DATE     ; generate new date = d1 in month before m2
24 RCL.02
25 ΔDAYS      ; days between date2 and d1 in month before date2
26 SDR 004    ; move days to 0,00dd
27 RCL.01     ; recall date1
28 DATE->     ; stack: d1, m1, y1, 0,00dd
29 DROP       ; stack: m1, y1, 0,00dd
30 cSTO-.03   ; R.03: m2-m1, R.04: y2-y1
31 cDROP      ; stack: 0,00dd
32 RCL.03     ; stack: m2-m1, 0,00dd
33 x≥0?       ; stack: m2-m1, 0,00dd
34 SKIP 003
35 DEC.04     ; adjust y2-y1 in R.04 if m2-m1 negative
36 #012       ; add back 12 months
37  +         ; stack: mm, 0,00dd 
38 SDR 002    ; move months to 0,mm
39  +         ; add days to get 0,mmdd
40 RCL+.04    ; recall and add y2-y1 
41 END        ; return y,mmdd



RE: Year(s) Month(s) Day(s) between 2 dates - ggauny@live.fr - 10-22-2015 04:53 PM

Hi,

Thanks for your routine, it is a festival of so hight programmation ! All people and I say to you, Dieter and Wolfgang, a great "merci", we learn so well with you for programming. You are so goods professors !

It is always time to learn. In the other hand, what a work to understand how you raisonnez ! (reason ?), and look at the Bonin's manual to understand all of yours steps !

Again very thanks, I have "du pain sur la planche !"

Gérard.


RE: Year(s) Month(s) Day(s) between 2 dates - Dieter - 10-22-2015 06:02 PM

(10-22-2015 04:00 PM)Didier Lachieze Wrote:  The program from Dieter is extremely well done. However it’s still possible to squeeze out a few steps Smile
Here is a slightly modified version using local registers instead of global ones and without the need for flag 00:

Ah, great. I like the idea with the complex STO–.03 which calculates y2–y1 and m2–m1 in one single step.

The program now is eight lines shorter. AFAIK this is equivalent to the memory consumption of two data registers, but on the other hand the program requires three additional (local) registers... ;-) As far as I can see R.00 seems to remain unused, so LocR 004 (with adjusted register addresses) should be fine as well. Or do I miss something here?

Dieter


RE: Year(s) Month(s) Day(s) between 2 dates - Didier Lachieze - 10-22-2015 09:46 PM

(10-22-2015 06:02 PM)Dieter Wrote:  The program now is eight lines shorter. AFAIK this is equivalent to the memory consumption of two data registers, but on the other hand the program requires three additional (local) registers... ;-) As far as I can see R.00 seems to remain unused, so LocR 004 (with adjusted register addresses) should be fine as well. Or do I miss something here?

Dieter

You're right. Here is an updated version and with some improvements in the beginning it's even 3 steps shorter :

Code:
01 LBL"YMD"   ; stack: date2, date1
02 LocR 004   ; allocate local registers R.00 to R.03
03 cSTO.00    ; store date2 in R.00 and date1 in R.01
04 DATE->     ; stack: d2, m2, y2, date1
05 <>YZTX     ; stack: m2, y2, date1, d2
06 cSTO.02    ; store m2 in R.02 and y2 in R.03
07 cX<>Z      ; stack: date1, d2, m2, y2
08 DAY        ; stack: d1, d2, m2, y2
09  -         ; stack: d2-d1, m2, y2 – LastX: d1
10 x≥0?       ; d2 ≥ d1?
11 SKIP 011   ; no adjustment required, goto step 23
12 DEC.02     ; adjust m2 in R.02
13 DROP       ; stack: m2, y2 – LastX: d1
14 DSZ X      ; month before m2
15 SKIP 003   ; is it > 0, i.e. Jan...Nov? Then continue
16 DROP
17 #012       ; if not, month is December
18 DEC Y      ; of previous year
19 RCL L      ; now stack holds d1, m2-1, year of m2-1
20 ->DATE     ; generate new date = d1 in month before m2
21 RCL.00
22 ΔDAYS      ; days between date2 and d1 in month before date2
23 SDR 004    ; move days to 0,00dd
24 RCL.01     ; recall date1
25 DATE->     ; stack: d1, m1, y1, 0,00dd
26 DROP       ; stack: m1, y1, 0,00dd
27 cSTO-.02   ; R.02: m2-m1, R.03: y2-y1
28 cDROP      ; stack: 0,00dd
29 RCL.02     ; stack: m2-m1, 0,00dd
30 x≥0?       ; stack: m2-m1, 0,00dd
31 SKIP 003
32 DEC.03     ; adjust y2-y1 in R.03 if m2-m1 negative
33 #012       ; add back 12 months
34  +         ; stack: mm, 0,00dd 
35 SDR 002    ; move months to 0,mm
36  +         ; add days to get 0,mmdd
37 RCL+.03    ; recall and add y2-y1 
38 END        ; return y,mmdd

Notes:
  • line 5: I could have used RDN but it would work only with a 4-level stack while <>YZTX works with both 4- and 8-level stacks
  • line 7 is entered as CPX x<>y but is displayed as cX<>Z



RE: Year(s) Month(s) Day(s) between 2 dates - Didier Lachieze - 10-23-2015 11:25 AM

With some changes starting step 28, one step less, now 37 lines (and 4 local registers):

Code:
01 LBL"YMD"   ; stack: date2, date1
02 LocR 004   ; allocate local registers R.00 to R.03
03 cSTO.00    ; store date2 in R.00 and date1 in R.01
04 DATE->     ; stack: d2, m2, y2, date1
05 <>YZTX     ; stack: m2, y2, date1, d2
06 cSTO.02    ; store m2 in R.02 and y2 in R.03
07 cX<>Z      ; stack: date1, d2, m2, y2
08 DAY        ; stack: d1, d2, m2, y2
09  -         ; stack: d2-d1, m2, y2 – LastX: d1
10 x≥0?       ; d2 ≥ d1?
11 SKIP 011   ; no adjustment required, goto step 23
12 DEC.02     ; adjust m2 in R.02
13 DROP       ; stack: m2, y2 – LastX: d1
14 DSZ X      ; month before m2
15 SKIP 003   ; is it > 0, i.e. Jan...Nov? Then continue
16 DROP
17 #012       ; if not, month is December
18 DEC Y      ; of previous year
19 RCL L      ; now stack holds d1, m2-1, year of m2-1
20 ->DATE     ; generate new date = d1 in month before m2
21 RCL.00
22 ΔDAYS      ; days between date2 and d1 in month before date2
23 SDR 004    ; move days to 0,00dd
24 RCL.01     ; recall date1
25 DATE->     ; stack: d1, m1, y1, 0,00dd
26 DROP       ; stack: m1, y1, 0,00dd
27 cSTO-.02   ; R.02: m2-m1, R.03: y2-y1
28 cX<>.02    ; stack: m2-m1, y2-y1, 0,00dd
29 x≥0?       ; stack: m2-m1, y2-y1, 0,00dd
30 SKIP 003
31 DEC Y      ; adjust y2-y1 if m2-m1 negative
32 #012       ; add back 12 months
33  +         ; stack: mm, y2-y1, 0,00dd 
34 SDR 002    ; move months to 0,mm
35  +         ; add y2-y1  to get y,mm 
36  +         ; add days to get y,mmdd
37 END        ; return y,mmdd