Das + und - nur wenn man von Azimuth und Elevation spricht.
Bei direkten "floats" nicht.
https://www.esrl.noaa.gov/gmd/grad/solcalc/...click here to try the updated version of NOAA's Solar Calculator
Dann schau dir mal dein MapViewer an.
https://www.esrl.noaa.gov/gmd/grad/solcalc/...click here to try the updated version of NOAA's Solar Calculator
Code: Alles auswählen
unit sunRiseSetUnit;
{$mode objfpc}{$H+}{$R+}{$I+}
//-----------------------------------------------------------------------------
//
// Sunrise/Sunset Time module
//
// 1.0 Apr 2015:
// Original Version:
// 1.1 2021-01
// Six1 https://www.lazarusforum.de/viewtopic.php?p=119263#p119263
// ----------------------------------------------------------------------------
interface
uses
classes,
dateUtils;
function sunRiseSet(
sunMode : integer;
date : TDateTime;
latitude : double;
longitude : double;
var Err : string;
zenithMode : integer = 0;
localOffset : real = 0
) : TDateTime;
// ----------------------------------------------------------------------------
implementation
uses
math,
sysUtils;
function sunRiseSet(
sunMode : integer;
date : TDateTime;
latitude : double;
longitude : double;
var Err : string;
zenithMode : integer = 0;
localOffset : real = 0
) : TDateTime;
const
sunrising = 0;
sunsetting = 1;
zenithOfficial = 0;
zenithCivil = 1;
zenithNautical = 2;
zenithAstronomical = 3;
zenithDeg : array [0 .. 3] of double = (
90.833333,
96.0,
102.0,
108.0
);
var
cosDec : double;
cosH : double;
day : integer;
h : double;
l : double;
lQuadrant : double;
lngHour : double;
m : double;
month : integer;
n : integer;
n1 : integer;
n2 : integer;
n3 : integer;
oldDateSeparator : char;
oldShortDateFormat : string;
ra : double;
raQuadrant : double;
sinDec : double;
t : double;
tLocal : double;
tLocalMean : double;
tUTC : double;
year : integer;
hour, minute:integer;
// the algorith requires degrees NOT radians. These functions are
// wrappers for the various trig functions which convert degrees to radians
function degACOS(
n : double
) : double;
begin
degACOS := (180/pi)*arccos(n);
end; // degACOS
function degASIN(
n : double
) : double;
begin
degASIN := (180/pi)*arcsin(n);
end; // degASIN
function degATAN(
n : double
) : double;
begin
degATAN := (180/pi)*arctan(n);
end; // degATAN
function degCOS(
angle : double
) : double;
begin
degCOS := cos((pi/180)*angle);
end; // degCOS
function degSIN(
angle : double
) : double;
begin
degSin := sin((pi/180)*angle);
end; // degSIN
function degTAN(
angle : double
) : double;
begin
degTAN := tan((pi/180)*angle);
end; //degTAN
begin
Err:='';
if (not(sunMode in [0,1])) then
begin
Err:='sunMode must be 0-1.';
result:=0;
exit;
end;
if (latitude < -90) or (latitude > 90) then
begin
Err:='latitude outside of -90-90 range.';
result:=0;
exit;
end;
if (longitude < -180) or (longitude > 180) then
begin
Err:='longitude outside of -180-180 range.';
result:=0;
exit;
end;
if (not(zenithMode in [0..4])) then
begin
Err:='zenithMode must be 0..3.';
result:=0;
exit;
end;
month := monthof(date);
day := dayof(date);
year := yearof(date);
// Calc day of year
n1 := floor(275 * month / 9);
n2 := floor((month + 9) / 12);
n3 := (1 + floor((year - 4 * floor(year / 4) + 2) / 3));
n := n1 - (n2 * n3) + day - 30;
// Convert longitude to hour and calc approximate time
lngHour := longitude / 15;
if sunMode = sunRising then
t := n + ((6 - lngHour) / 24)
else
t := n + ((18 - lngHour) / 24);
// Calc the Sun's Mean anomaly
m := (0.9856 * t) - 3.289;
// Calc Sun's true longitude
l := m + (1.916 * degSIN(m)) + (0.020 * degSIN(2*M)) + 282.634;
if (l < 0) then
l := l + 360
else if (l > 360) then
l := l - 360;
// Calc the sun's right ascension
ra := degATAN(0.91764 * degTAN(L));
if (ra < 0) then
ra := ra + 360
else if (ra > 360) then
ra := ra - 360;
// Right ascension needs to be in the same quadrant as L
lQuadrant := (floor(l / 90)) * 90;
raQuadrant := (floor(ra / 90)) * 90;
ra := ra + (lQuadrant - raQuadrant);
// Convert Right ascension into hours
ra := ra / 15;
// Calc the Sun's declination
sinDec := 0.39782 * degSIN(l);
cosDec := degCOS(degASIN(sinDec));
// Calc the Sun's local hour angle
cosH := (degCOS(zenithDeg[zenithMode]) - (sinDec * degSIN(latitude))) /
(cosDec * degCOS(latitude));
if (cosH > 1) or (cosH < -1) then
begin
// Sun doesn't rise at this location on this date. We will just
// set it to 12:00
Result := EncodeDate(Year, Month, Day) + EncodeTime(12, 0,0,0);
end;
// Finish calculating H and convert into hours
if sunMode = sunRising then
h := 360 - degACOS(cosH)
else
h := degACOS(cosH);
h := h / 15;
// Calculate local mean time of rising/setting
tLocalMean := h + ra - (0.06571 * t) - 6.622;
// adjust back to UTC
tUTC := tLocalMean - lngHour;
// adjust back to local time
tLocal := tUTC + localOffset;
if (tLocal < 0) then
tLocal := tLocal + 24
else if (tLocal > 24) then
tLocal := tLocal - 24;
// if minutes would round up to 60, go to next hour:
if (round((tLocal-floor(tLocal))*60) = 60) then
tLocal := floor(tLocal) + 1;
hour:=floor(tLocal);
minute:=round((tLocal-floor(tLocal))*60);
Result := EncodeDate(Year, Month, Day) + EncodeTime(hour, minute,0,0);
end; //sunRiseSet
end.
Code: Alles auswählen
uses
...
, sunRiseSetUnit
, DateUtils
...
procedure GetSun;
const
zenithOfficial = 0;
zenithCivil = 1;
zenithNautical = 2;
zenithAstronomical = 3;
var
offset:integer;
Err:string;
begin
offset := trunc((GetLocalTimeOffset * -1)/60);
_sun_rise := sunRiseSet(0, akt_time, Latitude.Value, Longitude.value, Err, zenithOfficial, offset);
if (_sun_rise=0) then
Showmessage( Err);
_sun_set := sunRiseSet(1, akt_time, Latitude.Value, Longitude.value, Err, zenithOfficial, offset);
if (_sun_set=0) then
Showmessage( Err);
end;
Hallosix1 hat geschrieben: Di 26. Jan 2021, 07:01 Ich habe diesen Code gefunden, welcher auf Windows und Linux 1a funktioniert und Sun_set und Sun_rise berechnet:
(Code stammt im Original von http://williams.best.vwh.net/sunrise_su ... orithm.htm )
Code: Alles auswählen
"9/2021 7:56" is not a valid time
Code: Alles auswählen
lat:=50.66057;
lon:=6.78722;
// Fehler:
Date := EncodeDate(2021, 02, 09);
// OK
//Date := EncodeDate(2021, 02, 10);
showmessage('Date: '+datetimetostr(date));
offset := trunc((GetLocalTimeOffset * -1)/60);
_sun_rise := sunRiseSet(0, Date, Lat, Lon, zenithOfficial, offset);
_sun_set := sunRiseSet(1, Date, Lat, Lon, zenithOfficial, offset);
showmessage('Rise: '+datetimetostr(_sun_rise)+chr(13)+
'Set: '+datetimetostr(_sun_set));
Code: Alles auswählen
result := strToDateTime(format('%0.2D/%0.2D/%4D',[month, day, year]) + ' ' +
inttostr(floor(tLocal)) + ':' +
inttostr(round((tLocal-floor(tLocal))*60)));
Code: Alles auswählen
oldShortDateFormat := shortDateFormat;
oldDateSeparator := dateSeparator;
shortDateFormat := 'm/d/y';
dateSeparator := '/';
result := strToDateTime(format('%0.2D/%0.2D/%4D',[month, day, year]) + ' ' +
inttostr(floor(tLocal)) + ':' +
inttostr(round((tLocal-floor(tLocal))*60)));
shortDateFormat := oldShortDateFormat;
dateSeparator := oldDateSeparator;
Code: Alles auswählen
var
oldFormatSettings: TFormatSettings;
...
oldFormatSettings := DefaultFormatSettings;
DefaultFormatSettings.ShortDateFormat := 'm/d/y';
DefaultFormatSettings.DateSeparator := '/';
... hier die Rechnung ...
DefaultFormatSettings := oldFormatSettings;
Code: Alles auswählen
Result := EncodeDate(Year, Month, Day) + tLocal;
Dasselbe kommt aber an ein paar Zeilen höher immer noch vor.six1 hat geschrieben: Sa 30. Jan 2021, 17:51 Edit: Habe den obigen Quellcode geändert auf EncodeDate und EncodeTime