solar-time
Version:
This library provides functions to calculate local solar time, also known as local apparent time, based on a given location and date.
2 lines (1 loc) • 3.13 kB
JavaScript
;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function E(t){const n=t.getUTCFullYear(),e=t.getUTCMonth(),a=t.getUTCDate(),s=Date.UTC(n,0,0),o=Date.UTC(n,e,a)-s;return Math.floor(o/(1e3*60*60*24))}function l(t){if(t.endsWith("Z"))return 0;const n=t.match(/([+-])(\d{2}):(\d{2})$/);if(!n)return 0;const e=n[1]==="+"?1:-1,a=parseInt(n[2],10),s=parseInt(n[3],10);return e*(a+s/60)}function L(t){const n=new Date(t),e=l(t),a=n.getTime()+e*60*60*1e3,s=new Date(a),c=new Date(Date.UTC(s.getUTCFullYear(),s.getUTCMonth(),s.getUTCDate(),0,0,0,0));return e!==0?I(c,e):c.toISOString()}function f(t,n,e){const a=new Date(t),s=new Date(a.getTime()+n*60*1e3);return e!==0?I(s,e):s.toISOString()}function I(t,n){const e=new Date(t.getTime()+n*60*60*1e3),a=e.getUTCFullYear(),s=String(e.getUTCMonth()+1).padStart(2,"0"),c=String(e.getUTCDate()).padStart(2,"0"),o=String(e.getUTCHours()).padStart(2,"0"),r=String(e.getUTCMinutes()).padStart(2,"0"),i=String(e.getUTCSeconds()).padStart(2,"0"),M=n>=0?"+":"-",h=Math.abs(n),u=String(Math.floor(h)).padStart(2,"0"),d=String(Math.round(h%1*60)).padStart(2,"0");return`${a}-${s}-${c}T${o}:${r}:${i}${M}${u}:${d}`}function R(t){const n=new Date(t),e=l(t);let s=n.getUTCHours()*60+n.getUTCMinutes()+n.getUTCSeconds()/60+e*60;return s<0&&(s+=1440),s>=1440&&(s-=1440),s}function z(t){if(typeof t!="number"||Number.isNaN(t))throw new Error("Longitude must be a valid number");if(t<-180||t>180)throw new Error("Longitude must be between -180 and 180 degrees")}function Y(t){if(typeof t!="string")throw new Error("DateTime must be an ISO 8601 string");const n=new Date(t);if(Number.isNaN(n.getTime()))throw new Error("Invalid ISO 8601 datetime string")}const p=(t,n)=>{Y(t),z(n);const e=new Date(t),a=l(t),s=15*a,c=E(e),o=2*Math.PI*(c-1)/365,r=1440/(2*Math.PI)*(75e-7+.001868*Math.cos(o)-.032077*Math.sin(o)-.014615*Math.cos(2*o)-.040849*Math.sin(2*o)),M=(.006918-.399912*Math.cos(o)+.070257*Math.sin(o)-.006758*Math.cos(2*o)+907e-6*Math.sin(2*o)-.002697*Math.cos(3*o)+.00148*Math.sin(3*o))*(180/Math.PI),h=360/365*(c-1),u=4*(n-s)+r;return{LST:f(t,u,a),TC:u,EoT:r,B:h,LSTM:s,declination:M}};function A(t){if(typeof t!="number"||Number.isNaN(t))throw new Error("Latitude must be a valid number");if(t<-90||t>90)throw new Error("Latitude must be between -90 and 90 degrees")}const j=(t,n,e)=>{A(n);const a=p(t,e),{declination:s,EoT:c}=a,o=l(t),r=n*(Math.PI/180),i=s*(Math.PI/180),M=90.833*(Math.PI/180),h=(Math.cos(M)-Math.sin(r)*Math.sin(i))/(Math.cos(r)*Math.cos(i)),u=L(t);let d=null,S=null;if(Math.abs(h)<=1){const U=Math.acos(h)*(180/Math.PI),v=720-4*(e+U)-c,$=720-4*(e-U)-c;d=f(u,v,o),S=f(u,$,o)}const D=720-4*e-c,O=f(u,D,o);let g=(R(t)+a.TC)/60;g<0&&(g+=24),g>=24&&(g-=24);const w=15*(g-12)*(Math.PI/180),C=Math.sin(r)*Math.sin(i)+Math.cos(r)*Math.cos(i)*Math.cos(w),T=Math.asin(C),b=T*(180/Math.PI),P=90-b,y=-Math.sin(w)*Math.cos(i)/Math.cos(T),N=(Math.sin(i)-Math.sin(r)*C)/(Math.cos(r)*Math.cos(T));let m=Math.atan2(y,N)*(180/Math.PI);return m<0&&(m+=360),{sunrise:d,sunset:S,solarNoon:O,azimuth:m,elevation:b,zenith:P}};exports.getSolarTime=p;exports.getSunPosition=j;