This program is based on routines by Marwan Joury presented in an article (http://www.hpmuseum.org/cgi-sys/cgiwrap ... ?read=1131) at the old MoHPC Articles Forum.
My version for the DM42 is primarily based on the HP-41CV or 41C with time module version since the DM42 has the time and date functions. I changed the program control (setting up a menu) and the output (using the 2-line alpha output to display sunrise, sunset and day length). Also added automatic handling of daylight saving time, or British Summer time, or whatever you might call seasonal shifting of the clock. The entire program listing below handles DST for the dates used in the US and some other areas, that being from the 2nd Sunday in March to the 1st Sunday in November. Following the full program listing is a listing for the DST subroutine to determine if daylight saving time is in effect for the dates used in Europe and elsewhere, from the last Sunday in March to the last Sunday in October. Also attached is a raw file of the entire program with the European DST module. If your DST dates vary from both the US and European dates, hopefully the logic I used* will be obvious and easy to revise as needed. If you would like notice that the calculated times are based on DST being in effect, delete the “CF 01” command in step 39. That will leave flag 1 set and light the Flag 1 annunciator on the DM42 to provide visual indication that DST was applied. If you don't observe DST or care to have it applied to your calculated times, simply delete the XEQ D instruction in step 18 and all of the DST subroutine beginning in step 189. You can still manually set DST mode by setting flag 1, so make sure it is clear if you don't want DST applied. (A few more steps, 156 through 159, could be eliminated if you want to completely remove the ability to handle DST.)
Program use: First, edit steps 22, 27 and 29 to your desired offset from GMT, latitude (in decimal degrees), and longitude (in decimal degrees), respectively, as these values are hard-coded into the program. From run mode, pressing XEQ "SUN" will bring up a menu. Press "TODAY" to calculate sunrise and sunset times and day length for today. Press "TMROW" to calculate for tomorrow. For any other date, key it in (in whatever date mode is currently in effect on the calculator, dd.mmyyyy or mm.ddyyyy) and press "ANY".
* - My DST logic is based on logic developed by Dieter, applied in the similar sunrise/sunset program I wrote for the WP-34S, presented here: http://www.hpmuseum.org/forum/thread-452.html Full credit and thanks given to Dieter. Note that the USA DST calculations take advantage of the fact that the 1st Sunday in November is always 238 days after the second Sunday in March. For the Euro DST calculations, sometimes the last Sunday in October is 210 days after the last Sunday in March, and sometimes it is 217 days later, so the day of year for the last Sunday in October must be calculated explicitly. Just requires a few more steps.
edited to correct typo and add instruction that longitude and latitude are entered in decimal degrees.
Code: Select all
Step Function Comments
001 LBL "SUN"
002 "TODAY" Set up menu structure…
003 KEY 1 XEQ 01 ...to calculate...
004 "TOMRW" ...sunrise/sunset/
005 KEY 2 XEQ 02 ...length of day…
006 "ANY" ...for today (TODAY)…
007 KEY 3 XEQ 03 ...tomorrow (TOMRW)…
008 MENU ...or any (ANY) date keyed in.
009 STOP stop and wait for TODAY, TMROW, or ANY selection from menu
010 LBL 01 label to calculate sunrise/sunset/length for today
011 DATE what is today's date?
012 GTO 03 go calculate
013 LBL 02 label to calculate sunrise/sunset/length for tomorrow
014 DATE what is today's date?
015 1 enter 1
016 DATE+ add 1 to today's date
017 LBL 03 label to calculate sunrise/sunset/length for entered date
018 XEQ D execute subroutine to see if DST in effect for date being calculated
019 DEG set degrees mode
020 FIX 02 set FIX 2 for sunrise/sunset times
021 CF 02 clear flag used in main calculation routine to tell sunrise from sunset
022 -5 GMT offset, west is negative
023 STO 03 store GMT offset
024 90.5 sun elevation at sunrise/sunset, entered in HMS…
025 ->HR ...and converted to HR mode, less bytes than direct HR entry of -90.833333
026 STO 06 store solar elevation at sunrise/sunset
027 40.00002 latitude (entered in decimal degrees)
028 STO 01 store latitude
029 -90.00007 longitude, west is negative (decimal degrees)
030 STO 02 store longitude.
031 15
032 ÷
033 STO 07
034 XEQ 04
035 STO 15
036 SF 02
037 XEQ 04
038 RCL 15
039 CF 01
040 CLA
041 CLK12 set clock 12 display mode for AM and PM rise/set times
042 "^=" use up arrow symbol for rise
043 ATIME
044 |-" \v=" use down arrow symbol for set
045 X<>Y
046 ATIME
047 X<>Y
048 RCL ST Y
049 RCL ST Y
050 HMS-
051 |-" DAY LENGTH=" need space at beginning to get day length on second alpha line
052 FIX 04
053 ATIME24 append day length in 24 hour format
054 AVIEW View results
055 RTN
056 LBL 04 All Label 4 verbatim from M. Joury original program
057 6
058 FS? 02
059 18
060 RCL 07
061 -
062 24
063 ÷
064 RCL 05
065 +
066 STO 08
067 0.9856
068 ×
069 3.289
070 -
071 STO 09
072 SIN
073 1.916
074 ×
075 RCL 09
076 +
077 2
078 RCL 09
079 ×
080 SIN
081 0.02
082 ×
083 +
084 282.634
085 +
086 360
087 MOD
088 STO 10
089 TAN
090 0.91764
091 ×
092 ATAN
093 360
094 MOD
095 STO 11
096 RCL 10
097 90
098 ÷
099 XEQ F execute floor subroutine
100 90
101 ×
102 +
103 RCL 11
104 90
105 ÷
106 XEQ F execute floor subroutine
107 90
108 ×
109 -
110 15
111 ÷
112 STO 11
113 RCL 10
114 SIN
115 0.39782
116 ×
117 STO 12
118 ASIN
119 COS
120 STO 13
121 RCL 06
122 COS
123 RCL 01
124 SIN
125 RCL 12
126 ×
127 -
128 RCL 01
129 COS
130 RCL 13
131 ×
132 ÷
133 ACOS
134 FS?C 02
135 GTO 05
136 360
137 X<>Y
138 -
139 LBL 05
140 15
141 ÷
142 RCL 11
143 +
144 0.06571
145 RCL 08
146 ×
147 -
148 6.622
149 -
150 24
151 MOD
152 RCL 07
153 -
154 RCL 03
155 +
156 FS? 01 is DST in effect?
157 1
158 FS? 01 is DST in effect?
159 + if yes add 1 hour to sunrise/sunset time
160 ->HMS
161 RTN end of main calculation routine.
162 LBL F Floor subroutine
163 IP
164 X<>Y
165 X<> ST L
166 X<Y?
167 DSE ST Y
168 LBL 00
169 X<> ST L
170 X<>Y
171 RTN end of floor subroutine
172 LBL G Subroutine to determine day of year
173 RCL ST X
174 100
175 ×
176 FP
177 1E-4
178 -
179 FC? 31
180 1231
181 FS? 31
182 3112
183 +
184 100
185 ÷
186 X<>Y
187 DDAYS
188 RTN end of day of year subroutine
189 LBL D Subroutine to determine if DST in effect for input date.
190 XEQ G execute day of year subroutine to find DOY of input date
191 STO 05 store input day of year in register 5 for later use by DST routine and main program.
192 LASTX recall input date
193 100 enter 100
194 × form mmdd.yyyy or ddmm.yyyy
195 FP extract year
196 FC? 31 determine dmy or mdy
197 314 if mdy, add 314 to .year
198 FS? 31 if dmy…
199 1403 ...if dmy, add 1403 to .year
200 + form 314.yyyy or 1403.yyyy
201 100 enter 100
202 ÷ divide by 100 to form mm.ddyyyy or dd.mmyyyy
203 DOW find day of week for 14th of March (latest possible second Sunday)
204 +/- change sign
205 LASTX recall 3.14yyyy or 14.03yyyy
206 XEQ G execute day of year subroutine
207 + add to negated day of week to find second Sunday in March
208 RCL 05 recall DOY of input date
209 - subtract DOY of input date from DOY DST begins
210 CF 01 clear flag 01
211 X>0? is input day of year less than DST begin day of year?
212 RTN if true, DST not in effect, done
213 238 enter 238 (days between 2nd Sunday in March and 1st Sunday in November)
214 + add 238 to DOY DST begin minus DOY date
215 X>0? if positive...
216 SF 01 …DST in effect, SF 01
217 RTN if false, DST not in effect, end DST subroutine
218 END
Code: Select all
Step Function Comments
189 LBL D Subroutine to determine if DST in effect for input date for Euro DST dates.
190 XEQ G execute day of year subroutine to find DOY of input date
191 STO 05 store input day of year in register 5 for later use by DST routine and main program.
192 LASTX recall input date
193 100 enter 100
194 × form mmdd.yyyy or ddmm.yyyy
195 FP extract year
196 STO 00 store for later use
197 FC? 31 determine dmy or mdy
198 1031 if mdy, add 1031 to .year
199 FS? 31 if dmy…
200 3110 ...if dmy, add 3110 to .year
201 + form 1031.yyyy or 3110.yyyy
202 100 enter 100
203 ÷ divide by 100 to form mm.ddyyyy or dd.mmyyyy
204 DOW find day of week for 31st of October, latest possible Sunday in October, obviously
205 +/- change sign
206 LASTX recall 1031.yyyy or 3110.yyyy
207 XEQ G execute day of year subroutine to find DOY for 31st of October
208 + add to negated day of week to find last Sunday in October
209 STO 02 store for later use
210 RCL 00 recall year of input date
211 FC? 31 determine dmy or mdy
212 331 if mdy, add 331 to .year
213 FS? 31 if dmy…
214 3103 ...if dmy, add 3103 to .year
215 + form 331.yyyy or 3103.yyyy
216 100 enter 100
217 ÷ divide by 100 to form mm.ddyyyy or dd.mmyyyy
218 DOW find day of week for 31st of March, , latest possible Sunday in March, obviously
219 +/- change sign
220 LASTX recall 331.yyyy or 3103.yyyy
221 XEQ G execute day of year subroutine to find DOY for 31st of March
222 + add to negated day of week to find last Sunday in March
223 RCL 05 recall DOY of input date
224 SF 01 set flag 01, DST in effect
225 X<Y? is input day of year less than DST begin day of year?
226 CF 01 if true, DST not in effect, clear flag 01
227 RCL 02 recall day of year of last Sunday in October
228 X<=Y? is day of year for last Sunday in October less than or equal to input day of year?
229 CF 01 if true, DST not in effect, clear flag 01
230 RTN if false, DST in effect, Flag 1 stays set, end DST subroutine
231