Page History: Quick and Dirty Daylight Indicator
Compare Page Revisions
Page Revision: 2017/10/18 07:18
The following is a function to provide a Boolean indicator of whether the given time occurs during "Civil Daylight" on the given date. This is the light period of the day considered between the twilights of sunrise and sunset. To do this with any precision requires
horrible, complex (read slow) maths and it's a huge overkill for a simple Go/NoGo test.
This function was written to provide some intelligence to exterior lighting so that it is only activated during the hours of darkness, thus precision is not required, within a few minutes either way is fine.
On the downside: It is very rough and ready: The sunrise/set times change considerably between the start and finish of say, March. This function uses the start of the current month and the start of the next to create a linear progression based around 30 divisions (days). If you graphed it, it wouldn't be a smooth sine wave over the year but rather a close analogue made up of a series of straight lines (with some jaggies around month change because for simplicity it assumes there are 30 days in every month). The use of Civil Daylight means there is a tendency to over-compensate for darkness anyway so it shouldn't be a problem. The other compromise is that the daylight start/stop times of the solstice months and their +1 are the same to make the advance/retard logic work at the change of the year - the sunrise/sunset times change slowly around here as we are at the peak or trough of the sine wave so again it doesn't make a significantly meaningful difference for dusk-to-dawn lighting.
On the upside: Because it is very maths light, it is really quick, <4ms @ 48MHz so it doesn't "cost" much when called in the main loop.
The numbers in the
Case
statements are the STart and FiNish of daylight as minutes from midnight for the first day of the relevant month with
no daylight saving time. A day contains 1440 minutes and so daylight may start at the 405th minute and continue until the 1060th minute (i.e. 06:45 until 17:40). This sunrise/set
online tool was used to obtain the daylight times with a few tweaks. Converting to the numbers here is simply the first day of each month, and I based them on civil twilight start and stop times; HH*60+MM. Obviously, there are 12 groups - the ones in the below example are for London, UK - you will need to change these for your own location and time format if necessary, but for anywhere in the UK south of a line from The Wash to The Wirral, these are probably OK as we aren't after astronomical precision.
Accepts the standard DATE$ and TIME$ strings as argument, any seconds on the time string are ignored e.g both
hh:mm:ss
and
hh:mm
are fine.
Syntax:
x=Daylight(strDateDDMMYYYY,strTime24H)
Do not use Daylight savingExample Uses:
DaylightAug5am=Daylight("17/08/2017","05:00:00")
or
DaylightAug5am=Daylight("17/08/2017","05:00")
If Daylight(Date$,Time$) Then LightsOff Else LightsOn
Code
Function DayLight(dt$,tm$) As Integer ' DT must be dd/mm/yyyy as per DATE$, tm$ is hh:mm[:ss] so TIME$ will work
Local Integer mn,st,fn,st0,fn0,dd,mm,h,m
Local Float q0,q1
dd=Val(Left$(dt$,2)):mm=Val(Mid$(dt$,4,2)):h=Val(Left$(tm$,2)):m=Val(Mid$(tm$,4,2))
Do
Select Case mm
Case 1:st=490:fn=960 '08h10-16h00 start/end of full daylight GMT, London UK
Case 2:st=465:fn=1010 '07h45-16h50
Case 3:st=410:fn=1060 '06h50-17h40
Case 4:st=340:fn=1115 '05h40-18h35
Case 5:st=275:fn=1165 '04h35-19h25
Case 6:st=230:fn=1210 '03h50-20h10
Case 7:st=230:fn=1210 '03h50-20h10
Case 8:st=265:fn=1190 '04h25-19h50
Case 9:st=315:fn=1125 '05h15-18h45
Case 10:st=365:fn=1060 '06h05-17h40
Case 11:st=420:fn=990 '07h00-16h30
Case 12:st=490:fn=960 '08h10-16h00
End Select
If fn0<>0 Then Exit Do
fn0=fn:st0=st
mm=mm+1:If mm>12 Then mm=1
Loop
q0=Abs(st0-st)/30:q1=Abs(fn0-fn)/30 ' assume all months are 30 days (told you it was dirty)
If mm<7 Then
st=st0-Fix(q0*dd):fn=fn0+Fix(q1*dd) ' advance daylight
Else
st=st0+Fix(q0*dd):fn=fn0-Fix(q1*dd) ' retard daylight
EndIf
mn=(h*60)+m ' mins of day
DayLight=(mn>=st) And (mn<fn)
End Function