The following is a function to provide an 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 precision requires
horrible, complex (= 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/enabled during the night, thus precision is not required - within 5 or 10 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 an 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.
On the upside: Because it is very maths light, it is really quick, <4ms @ 48MHz so it doesn't cost much if you want to call it from the main loop.
The numbers in the first
Case
statement are the STart and FiNish of daylight as minutes from midnight for the first day of the relevant month with
no daylight saving time. I did try this with the times on the 22nd of each month so the function would be exactly right on the longest and shortest days of the year but it resulted in a much higher fluctuation over the remainder of the month due to the 22 day offset early on in each month and only 8 days after.
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. There are 13 groups; having an additional month for January after December removes the need for a modulo and so is a tiny speed increase at the expense of a bit of program space. The times shown are for London, UK rounded up or down to 5 minutes - you can change these for your own location but do not include daylight saving times.
This version includes an optional parameter to return the start and finish times of daylight also: Opt=1 returns the start of daylight in minutes since midnight on the given date. Opt=2 returns the end of daylight.
Requires a single string which is a concatenation of the standard DATE$ and TIME$ strings as argument - see the
Now() Function for an easy interface. NOTE does not support the international date sort form (yyyy-mm-dd...) - yet.
Syntax:
x=IsDayLight(strDateTime,opt)
Do not use Daylight saving datetime format is "dd-mm-yyyy hh:mm:ss"
Example Uses:
DaylightAug5am=IsDayLight("17/08/2017 05:00:00")
If IsDayLight(Now()) Then LightsOff Else LightsOn
Print IsDayLight("12/10/2020 15:30:00",1)
show the start time of daylight (in minutes since midnight) for the given date
Print IsDayLight(Now(),2)
show the end time of daylight
Dependancieis:
DatePart()Code
Function IsDayLight(dt$,opt as integer) As Integer
'opt = 1, return daytime start, 2, return daytime end anything else return bool of daytime now
Local Integer mn,st,fn,st0,fn0,dd,mm
dd=DatePart("dd",dt$):mm=DatePart("mm",dt$)
Do
Select Case mm
Case 1:st=490:fn=960
Case 2:st=460:fn=1010
Case 3:st=405:fn=1060
Case 4:st=335:fn=1115
Case 5:st=275:fn=1165
Case 6:st=230:fn=1210
Case 7:st=230:fn=1220
Case 8:st=265:fn=1190
Case 9:st=315:fn=1115
Case 10:st=360:fn=1060
Case 11:st=415:fn=990
Case 12:st=470:fn=955
Case 13:st=490:fn=960
End Select
If fn0<>0 Then Exit Do
fn0=fn:st0=st
mm=mm+1
Loop
st=st0-(((st0-st)/30)*dd):fn=fn0-(((fn0-fn)/30)*dd)
Select Case opt
Case 1
IsDayLight=st
Case 2
IsDayLight=fn
Case Else
mn=(DatePart("h",dt$)*60)+DatePart("m",dt$)
IsDayLight=(mn>=st) And (mn<fn)
End Select
End Function
Mins2TimeFunction to convert minutes from midnight (0 - 1439) to an actual HH:MM:SS time. Primarily intended for converting values returned by options 1 & 2 above. No error checking.
Dependencies:
ZPad$()Syntax=Mins2Time(n)
ExamplesPrint "Civil daylight today starts at ";Mins2Time(IsDayLight(Now(),1))
SunSet$=Mins2Time(IsDayLight(Now(),2))
Function Mins2Time(t As Integer) As String
Local Integer h
h=(t\60)
Mins2Time=ZPad$(h,2)+":"+ZPad$(t-(h*60),2)+":00"
End Function