hp41programs

Calendars

Julian & Gregorian Calendars for the HP-41


Overview
 

 1°) Date >>> Number of days since 2000/01/01 0h

   a) Program#1
   b) Program#2
   c) Program#3 - Gregorian Calendar only - ( Time Module required ) ( 2 versions )
   d) M-Code Routine - Gregorian Calendar only - HP41CX

 2°) Number of days since 2000/01/01 0h >>> Date

   a) Program#1
   b) Program#2
   c) Program#3 - Gregorian Calendar only - ( Time Module required ) ( 2 versions )

 3°) Date <> Day of the Year

   a) Program#1
   b) Program#2  ( Time Module required )
 

-The "B.C." years are counted astronomically:
   year  0 = 1 B.C.
   year -1 = 2 B.C. ...etc...
-All the dates are expressed in YMD format.
-The Gregorian Calendar would have been perfect in the year  3841 B.C. ( cf "Sidereal year, tropical year & lunar month for the HP-41" )
 

1°) Date >>> Number of days since 2000/01/01 0h
 

     a) Program#1
 

-This program computes the number of days since 2000/01/01  0h ( i-e the Julian Day number minus 2451544.5 )
  in X-register and the day of the week in T-register.
-Registers Y and Z are saved.
-The Gregorian calendar reform is taken into account: The day following 1582/10/04 is 1582/10/15
-"J0" ( and "DT" - cf 2°)a) ) are valid at least since 4713 B.C. up to ... the next calendar reform!

-Synthetic registers M, N, O, P can be replaced by R00, R01, R02, R03.
 

Data Registers: /
Flags: /
Subroutines: /
 
 

01  LBL "J0" 
02  STO O
03  ENTER^
04  INT
05  STO N        
06  -
07  ABS
08   E2
09  *
10  ENTER^
11  INT
12  STO M
13  -
14   E2
15  *
16  X<> M 
17  3
18  +
19  6
20  X>Y?
21  DSE N        
22  LBL 00
23  X<=Y?
24  CHS
25  +
26  4
27  +
28  30.6
29  *
30  INT
31  730550 
32  -
33  ST+ M
34  CLX
35  RCL N        
36  487
37  *
38  X<0?
39  DSE X
40  LBL 00
41  .75
42  *
43  INT
44  ST+ M
45  CLX
46  RCL O
47  1582.1015 
48  -
49  X<0?
50  GTO 01
51  X<> N        
52   E2
53  /
54  INT
55  25
56  %
57  INT
58  -
59  2
60  -
61  ST- M
62  LBL 01
63  CLX
64  RCL M        
65  1
66  -
67  7
68  MOD
69  INT
70  STO T
71  X<> O
72  SIGN
73  X<> M
74  CLA
75  END

 
    ( 123 Bytes / SIZE 000 )
 
 

        STACK          INPUTS       OUTPUTS
             T               /           dow
             Z               Z             Z
             Y               Y             Y
             X   YYYY.MNDDdd             N
             L               /   YYYY.MNDDdd

  ( dow = day of week = 0 for Sunday, 1 for Monday, ... , 6 for Saturday )

-N= the number of days between a date YYYY.MMDDdd and 2000/01/01 at 0h  = the Julian Day number minus 2451544.5

Examples:

  April 4th 2134 at 6h AM    2134.040425  XEQ "J0"  >>>     N = 49036.25   RDN  RDN   dow = 0 = Sunday

    1234.0428    R/S   >>>   N = -279651  RDN  RDN  dow = 5 = Friday

   -4123.0707   R/S   >>>   N = -2236225  RDN  RDN  dow = 1 = Monday
 

     b) Program#2
 

-The following program is only a variant of a routine listed in the PPC ROM user's manual.
-Y-register is saved in Y Z T
-Synthetic register M may be replaced by any standard register ( like R00 )
 

Data Registers: /
Flag:  F04             Set flag F04 for the Julian Calendar
                           Clear flag F04 for the Gregorian Calendar
Subroutines: /
 
 

01  LBL "J1" 
02  ENTER^
03  INT
04  ST- Y
05  X<>Y
06   E2
07  *
08  ENTER^
09  INT
10  STO M        
11  -
12   E2
13  *
14  X<> M        
15  1
16  E^X
17  -
18  12
19  /
20  +
21  INT
22  ST- M
23  LASTX        
24  367
25  *
26  INT
27  ST+ M
28  SIGN
29  FS? 04
30  ISG X
31  %
32  INT
33  .75
34  ST* Z
35  *
36  X<>Y 
37  ST- M
38  CLX
39  X<> M        
40  INT
41  X<>Y
42  -
43  INT
44  730434        
45  -
46  END

 
    ( 75 bytes / SIZE 000 )
 
 

      STACK        INPUTS      OUTPUTS
           T             /            Y
           Z             /            Y
           Y            Y            Y
           X   YYYY.MNDD            N

 
Examples:

  CF 04  2134.0404  XEQ "J1"  >>>     N =    49036
  SF 04  1234.0428      R/S        >>>     N = -279651

Notes:

-Here, the days cannot have decimals
-You can choose the Julian Calendar after 1582/10/15
  and you can choose the Gregorian Calendar before 1582/10/04

-This program only works since 0000/03/01  ( March 1st Year 0 )

-However, it will work for all dates - including negative years - if you have programmed a FLOOR function in M-Code:

   >>>   Replace lines 43-40-32-26-21  by  FLOOR  add  CLX  after line 27  and add  ABS  after line 05

-If you don't have a  FLOOR  function, replace it by  RCL X   1  MOD  -   ( lines 43-40-32-26 )
  replace line 23 by  R^  and replace line 22 by  ENTER^   STO Z   1  MOD  -

-The day of the week may be computed by  ( N-1) MOD 7
 

     c) Program#3 - Gregorian Calendar only - TIME Module required
 

-The functions of the TIME Module work for dates between 1582/10/15 and 4320/09/10
-"J2" overcomes these limitations and it is shorter than "J0" & "J1"
 

Data Registers: /
Flags: /
Subroutines: /

-Delete line 30 if you are living in a MDY country.
 
 

01  LBL "J2"
02  MDY
03  ENTER^
04  FRC
05  STO N        
06  -
07  RCL X
08  400
09  MOD
10  STO M        
11  -
12  2 E3
13  ST+ M
14  -
15  365.2425
16  *
17  X<> M        
18   E6
19  /
20  RCL N
21  ABS
22   E2
23  *
24  +
25  1.012
26  X<>Y
27  DDAYS 
28  RCL M        
29  +
30  DMY          
31  CLA
32  END

 
    ( 66 bytes / SIZE 000 )
 
 

      STACK        INPUTS      OUTPUTS
           T             /            Y
           Z             /            Y
           Y            Y            Y
           X   YYYY.MNDD            N

 
Examples:

 10234.0704  XEQ "J2"  >>>   N = 3007591
  2134.0404       R/S       >>>   N =    49036
  1234.0428       R/S       >>>   N = -279658
-4123.0707       R/S       >>>   N = -2236192 


Notes:

-If the dates are between 1582/10/15 and 4320/09/10 , we can write a shorter program.
-LBL "J" employs synthetic programming


 01 LBL "J"
 02 FRC
 03 LASTX
 04 INT
 05  E6
 06 /
 07 X<>Y
 08  E2
 09 *
 10 +
 11 1.012
 12 X<>Y
 13 MDY
 14 DDAYS
 15 DMY
 16 END


 ( 31 bytes / SIZE 000 )
 

 

     d) M-Code Routine - Gregorian Calendar only - HP41CX
 

-The same results are returned faster with the following code:
 

0B2  "2"
00A  "J"
1B9   ?NCXQ
144    MDY
2A0   SETDEC
0F8   C=X
128   L=C
088   C
0ED  =
064   Int(C)
10E   A=C ALL
268   Q=C
04E   C
35C
110   =
130
002   400
0E8   C
044
070   =
171
064   A mod C
070   N=C ALL
2BE  C=-C
10E   A=C ALL
278   C=Q
01D   C=
060    A+C
0F8   C=X
35C   PT=12
090    LD@PT- 2
226    C=C+1 S&X
268    Q=C
2BE   C=-C
025   C=
061   AB+C
04E   C
35C
0D0
190
150
090   =
110
090
150
130
002   365.2425
13D  C=
060   AB*C
0F0   C<>N ALL
10E   A=C ALL
278   C=Q
01D  C=
060   A+C
106   A=C S&X
130   LDI S&X
006   006
246   C=A-C S&X
0E8   X=C
0B0   C=N ALL
268   Q=C
138   C=L
05E   C=| C |
084   C
0ED  =
064   frc(C)
226   C=C+1 S&X
226   C=C+1 S&X
10E   A=C ALL
0F8   C=X
01D   C=
060   A+C
0E8   X=C
2A1   C
140    =
025   number of days
170   since 1582/10/15
10E   A=C ALL                      this word seems superfluous, but I'm not quite sure...
278   C=Q
01D  C=
060   A+C
04E   C
2BE
35C
050
150
090   =
0D0
210
110
130
005   -152384
025   C=
060   AB+C
0E8   X=C
1E5   ?NCGO                  Replace these 2 words by  3E0  RTN
146    DMY                      if you are living in a MDY country.

 ( 97 words )
 
 

      STACK        INPUTS      OUTPUTS
           T             T            T
           Z             Z            Z
           Y             Y            Y
           X   YYYY.MNDD            N
           L              L  YYYY.MNDD

 
Examples:

 10234.0704  XEQ "J2"  >>>   N = 3007591
  2134.0404   XEQ "J2"  >>>   N =    49036
  1234.0428   XEQ "J2"  >>>   N = -279658
-4123.0707   XEQ "J2"  >>>   N = -2236192

Notes:

-If DD has decimals, you will get DATA ERROR or ... meaningless results !
-Synthetic register Q is used.
-The date routines are at different places in the TIME module.
-There is no check for alpha data.
 

2°) Number of days since 2000/01/01 0h >>> Date
 

-These 3 programs are the inverses of   "J0" "J1" "J2"
 

     a) Program#1
 

Data Registers: /
Flags: /
Subroutines: /
 
 

01  LBL "DT"
02  STO O
03  2453069
04  +
05  ENTER^
06  FRC
07  STO M
08  -
09  STO N        
10  2300685
11  -
12  X<0?
13  GTO 01
14  4
15  *
16  1727779
17  +
18  146097
19  /
20  INT
21  ST+ N 
22  4
23  /
24  INT
25  ST- N
26  ISG N
27  LBL 01
28  CLX
29  RCL N        
30  122.1
31  -
32  365.25
33  STO P
34  /
35  INT
36  ST* P
37  RCL P 
38  INT
39  ST- N
40  CLX
41  4715
42  -
43  X<> N
44  ST+ M
45  30.61
46  STO P        
47  /
48  INT
49  ST* P
50  RCL P        
51  INT
52  ST- M
53  CLX
54  13
55  X<Y?
56  X=0?
57  SIGN 
58  -
59   E2
60  ST/ M
61  LOG
62  X<Y?
63  DSE N
64  CLX
65  X<> M
66  +
67   E2
68  /
69  RCL N        
70  SIGN
71  *
72  RCL N 
73  +
74  RCL O
75  SIGN
76  RDN
77  CLA
78  END

 
    ( 151 bytes / SIZE 000 )
 
 

        STACK          INPUTS       OUTPUTS
             Z               Z             Z
             Y               Y             Y
             X               N   YYYY.MNDDdd
             L               /             N

 
Examples:

   N =   49036.25    XEQ "DT"  >>>   2134.040425
   N = -279651             R/S       >>>   1234.0428
   N = -2236225           R/S       >>>  -4123.0707
 

     b) Program#2
 

-Like "J1", this program is also a variant of a routine listed in the PPC ROM user's manual.
-Y-register is saved in Y Z T
-Synthetic register M may be replaced by any standard register ( like R00 )
 

Data Registers: /
Flag:  F04             Set flag F04 for the Julian Calendar
                           Clear flag F04 for the Gregorian Calendar
Subroutines: /
 
 

01  LBL "D1"
02  730425.8
03  +
04  RCL X        
05  36524.25
06  /
07  INT
08  25
09  %
10  INT
11  -
12  2
13  FS? 04
14  X<>Y
15  RDN
16  +
17  RCL X        
18  365.25
19  ST/ Y
20  X<>Y
21  INT
22  STO M
23  *
24  INT
25  -
26  .3
27  -
28  RCL X        
29  30.6
30  ST/ Y
31  X<>Y
32  INT
33  *
34  ST- Y
35  ISG Y
36  X<> L
37  3
38  -
39  6
40  X<Y?
41  ISG M        
42  CHS
43  -
44  X<>Y
45  INT
46   E2
47  /
48  +
49   E2
50  /
51  0
52  X<> M        
53  +
54  END

 
     ( 99 bytes / SIZE 000 )
 
 

      STACK        INPUTS      OUTPUTS
           T             /            Y
           Z             /            Y
           Y            Y            Y
           X            N  YYYY.MNDD

 
Examples:

  CF 04  N =    49036   XEQ "D1"  >>>  2134.0404
  SF 04  N = -279651      R/S         >>>  1234.0428

Notes:

-N must be an integer.
-You can choose the Julian Calendar after 1582/10/15
 and you can choose the Gregorian Calendar before 1582/10/04

-This program only works since 0000/03/01  ( March 1st Year 0 )  [  i-e  N >= -730425 in the Gregorian Calendar  ,  N >= -730427 in the Julian Calendar  ]

-But if you have a FLOOR function, "D1" will work for all dates if you
   add  RCL M   SIGN   *         after line 50
           LBL 00   X<Y?   X=0?   after line 41
 replace lines  24-21-10-07  by FLOOR

-Otherwise,

    replace lines 15 to 24 by  X<> M  +  RCL X  365.25  /  RCL X  1  MOD  -  STO M  365.25  *  RCL X  1  MOD  -
    replace lines 10 and 07 by  RCL X  1  MOD  -
    replace line 04 by  STO M
 

     c) Program#3 - Gregorian Calendar only - TIME Module required
 

Data Registers: /
Flags: /
Subroutines: /

-Delete line 31 if you are living in MDY country.
 
 

01  LBL "D2"
02  MDY
03  RCL X        
04  146097
05  MOD
06  STO M
07  ST- Y
08  X<> L
09  /
10  400
11  *
12  X<> M        
13  1.012
14  X<>Y
15  DATE+        
16   E2
17  *
18  ENTER^
19  FRC
20  ST- Y
21   E4
22  ST/ Z
23  *
24  0
25  X<> M        
26  +
27  STO Z 
28  SIGN
29  *
30  +
31  DMY          
32  END

 
     ( 64 bytes / SIZE 000 )
 
 

      STACK        INPUTS      OUTPUTS
           T             /            Y
           Z             /            Y
           Y            Y            Y
           X            N  YYYY.MNDD

 
Examples:

    1000000  XEQ "D2"  >>>        4737.1128
  -1000000       R/S       >>>         -738.0203 

Notes:

-If the dates are between 1582/10/15 and 4320/09/10 , we can write a shorter program.
-Like LBL "J" , LBL "D" employs synthetic programming


 01 LBL "D"
 02 1.012
 03 X<>Y
 04 MDY
 05 DATE+
 06 DMY
 07  E2
 08 *
 09 INT
 10 LASTX
 11 FRC
 12  E4
 13 ST/ Z
 14 *
 15 +
 16 END


 ( 32 bytes / SIZE 000 )

 

 3°) Date <> Day of the Year
 

     a) Program#1
 

Data Registers: /
Flags:  F04 & F00     Set flag F04 for the Julian Calendar                      F00 is cleared for a common year
                                Clear flag F04 for the Gregorian Calendar               F00 is set for a leap year
Subroutines: /
 
 

01  LBL "DOY" 
02  FRC
03  LASTX
04  INT
05  XEQ 00
06  RDN
07  ABS
08   E2
09  *
10  FRC
11  LASTX
12  INT
13  RCL X          
14  XEQ 02
15  X<>Y
16   E2
17  *
18  +
19  30
20  -
21  RTN
22  LBL "YN-D"
23  X<>Y
24  STO M
25  XEQ 00
26  CLX
27  32
28  RCL Y          
29  X<Y?
30  ST- Z
31  RCL Z
32  2
33  FS? 00
34  SIGN
35  +
36  9
37  *
38  275
39  /
40  .98
41  +
42  INT
43  RCL M          
44  SIGN
45  %
46  ST+ M
47  RDN
48  ENTER^
49  XEQ 02
50  30
51  -
52  -
53   E4
54  /
55  RCL M
56  SIGN
57  *
58  0
59  X<> M
60  +
61  RTN
62  LBL 00 
63  CF 00
64  1
65  %
66  FRC
67  FC? 04
68  X#0?
69  GTO 01
70  X<> L          
71  INT
72  4
73  MOD
74  ST+ Y
75  LBL 01
76  CLX
77  4
78  MOD
79  X=0?
80  SF 00
81  RTN
82  LBL 02 
83  275
84  *
85  9
86  ST+ Z
87  /
88  INT
89  X<>Y          
90  12
91  /
92  INT
93  FC? 00
94  ST+ X
95  -
96  END

 
     ( 151 bytes / SIZE 000 )
 

1- Date >>> Day of the Year
 
 

      STACK        INPUTS      OUTPUTS
           X  YYYY.MNDD         DOY

 
Example:

  CF 04 ( Gregorian Calendar )   2134.0707  XEQ "DOY"  >>>>  doy = 188    Flag F00 is clear:  2134 is a common year
  SF 04    ( Julian Calendar )        1248.0707  XEQ "DOY" >>>>  doy = 189     Flag F00 is set:     1248 is a leap year

2-Day of the Year >>> Date
 
 

      STACK        INPUTS      OUTPUTS
           Y         YYYY            N
           X            N  YYYY.MNDD

 
Example:

  CF 04  ( Gregorian Calendar )   2134  ENTER^  188  XEQ "YN-D" >>>  Date = 2134.0707    Flag F00 is clear:  2134 is a common year
  SF 04     ( Julian Calendar )       1248  ENTER^  189  XEQ "YN-D" >>>  Date = 1248.0707    Flag F00 is set:     1248 is a leap year
 

Notes:

-This program works for positive and negative years,
  but it doesn't work in 1582 between October 15th and December 31st ( subtract 10 to DOY )
-LBL 00  ( lines 62 to 81 ) determines whether a given year is a common year ( F00 is cleared ) or a leap year ( F00 is set )
-These lines may constitute a separate subroutine.
 

     b) Program#2 - TIME Module required
 

-Here is a shorter version if you have a TIME Module
 

Data Registers: /
Flags:  F04 & F00     Set flag F04 for the Julian Calendar                      F00 is cleared for a common year
                                Clear flag F04 for the Gregorian Calendar               F00 is set for a leap year
Subroutines: /

-Delete lines 43 & 19 if you are living in a MDY coutry.
 
 

01  LBL "DOY" 
02  FRC
03  LASTX
04  INT
05  XEQ 00        
06  RDN
07  ABS
08   E2
09  *
10  XEQ 02
11  +
12  1.01
13  LASTX
14  +
15  X<>Y
16  DDAYS
17  1
18  +
19  DMY
20  RTN
21  LBL "YN-D"
22  X<>Y
23  STO M
24  XEQ 00        
25  SIGN
26  -
27  XEQ 02
28  1.01
29  +
30  X<>Y
31  DATE+
32   E2
33  *
34  INT
35   E4
36  /
37  RCL M 
38  SIGN
39  *
40  0
41  X<> M
42  +
43  DMY
44  RTN
45  LBL 00        
46  MDY
47  CF 00
48  1
49  %
50  FRC
51  FC? 04
52  X#0?
53  GTO 01        
54  X<> L
55  INT
56  4
57  MOD
58  ST+ Y
59  LBL 01
60  CLX
61  4
62  MOD
63  X=0?
64  SF 00
65  RTN
66  LBL 02         
67  2001
68  FS? 00
69  DSE X
70   E6
71  /
72  END

 
     ( 124 bytes / SIZE 000 )
 

1- Date >>> Day of the Year
 
 

      STACK        INPUTS      OUTPUTS
           X  YYYY.MNDD         DOY

 
Example:

  CF 04 ( Gregorian Calendar )   2134.0707  XEQ "DOY"  >>>>  doy = 188    Flag F00 is clear:  2134 is a common year
  SF 04    ( Julian Calendar )        1248.0707  XEQ "DOY" >>>>  doy = 189     Flag F00 is set:     1248 is a leap year

2-Day of the Year >>> Date
 
 

      STACK        INPUTS      OUTPUTS
           Y         YYYY            /
           X            N  YYYY.MNDD

 
Example:

  CF 04  ( Gregorian Calendar )   2134  ENTER^  188  XEQ "YN-D" >>>  Date = 2134.0707    Flag F00 is clear:  2134 is a common year
  SF 04     ( Julian Calendar )       1248  ENTER^  189  XEQ "YN-D" >>>  Date = 1248.0707    Flag F00 is set:     1248 is a leap year
 

Notes:

-This program works for positive and negative years,
  but it doesn't work in 1582 between October 15th and December 31st ( subtract 10 to DOY )
-LBL 00  ( lines 45 to 65 ) determines whether a given year is a common year ( F00 is cleared ) or a leap year ( F00 is set )
 
 

References:

[1]  Jean Meeus , "Astronomical Algorithms" - Willmann-Bell  -  ISBN 0-943396-61-1
[2]  PPC ROM user's manual