var Math2 = require("solar_math_utils.js"); const _MIN_MILLIS = 1000 * 60 ; const _HOUR_MILLIS = _MIN_MILLIS * 60; const _DAY_MILLIS = _HOUR_MILLIS * 24; function _start_of_julian_day(now){ var sod_of_day = new Date(now.getTime()); var local_offset_hours = sod_of_day.getTimezoneOffset()/60; //console.log("local_offset_hours=" + local_offset_hours); sod_of_day.setHours(12 + local_offset_hours,0,0,0); return sod_of_day; } function _date_to_julian_date(now){ var year = now.getFullYear(); var month = now.getMonth() + 1; var day = now.getDate(); var julian_date_full = (1461 * (year + 4800 + (month-14)/12))/4 +(367 * (month-2 - 12*((month - 14)/12)))/12-(3 * ((year + 4900 + (month - 14)/12)/100))/4 + day - 32075; var julian_date = (julian_date_full| 0); return julian_date; } function _to_time(now,day_fraction){ var datetime = new Date(now.getTime()); var hours = (day_fraction * 24) |0; var remainder = day_fraction - hours/24; var mins = (remainder * 24 * 60 | 0); var remainder = remainder - mins/(24*60); var secs = (remainder * 24 * 60 * 60 | 0); var remainder = remainder - secs /(24 * 60 * 60); var millis = remainder * 24 * 60 * 60 * 1000; datetime.setHours(hours, mins, secs,millis); return datetime; } const DateUtils = { DAY_MILLIS : _DAY_MILLIS, HOUR_MILLIS : _HOUR_MILLIS, MIN_MILLIS: _MIN_MILLIS, // calculate the sunrise and sunset information using the NOAA // equations. sunrise_sunset: (now,longitude,latitude, utc_offset)=>{ var sod_julian = _start_of_julian_day(now); var julian_date = _date_to_julian_date(sod_julian); //console.log("julian date=" + julian_date); //var n = julian_date - 2451545.0 + 0.0008; var julian_century = (julian_date-2451545)/36525; //console.log("julian_century=" + julian_century); var geom_mean_long_sun_degrees = (280.46646+julian_century*(36000.76983 + julian_century*0.0003032)) % 360; //console.log("geom_mean_long_sun=" + geom_mean_long_sun_degrees); var geom_mean_anomaly_sun_degrees = 357.52911+julian_century*(35999.05029 - 0.0001537*julian_century); //console.log("solar_mean_anomaly_sun=" + geom_mean_anomaly_sun_degrees); var eccent_earth_orbit = 0.016708634-julian_century*(0.000042037+0.0000001267*julian_century); //console.log("eccent_earth_orbit=" + eccent_earth_orbit); var sun_eq_of_ctr = Math.sin(Math2.to_radians(geom_mean_anomaly_sun_degrees))* (1.914602-julian_century*(0.004817+0.000014*julian_century))+ Math.sin(Math2.to_radians(2*geom_mean_anomaly_sun_degrees))*(0.019993-0.000101*julian_century)+ Math.sin(Math2.to_radians(3*geom_mean_anomaly_sun_degrees))*0.000289; //console.log("sun_eq_of_ctr=" + sun_eq_of_ctr); var sun_true_long_degrees = geom_mean_long_sun_degrees + sun_eq_of_ctr; //console.log("sun_true_long_degrees=" + sun_true_long_degrees); var sun_true_anom_degrees = geom_mean_anomaly_sun_degrees + sun_eq_of_ctr; //console.log("sun_true_anom_degrees=" + sun_true_anom_degrees); var sun_rad_vector_AUs = (1.000001018*(1-eccent_earth_orbit*eccent_earth_orbit))/(1+eccent_earth_orbit*Math.cos(Math2.to_radians(sun_true_anom_degrees))) //console.log("sun_rad_vector_AUs=" + sun_rad_vector_AUs); var sun_app_long_degress = sun_true_long_degrees-0.00569-0.00478*Math.sin(Math2.to_radians(125.04-1934.136*julian_century)); //console.log("sun_app_long_degress=" + sun_app_long_degress); var mean_obliq_ecliptic_degrees = 23+(26+((21.448-julian_century*(46.815+julian_century*(0.00059-julian_century*0.001813))))/60)/60; //console.log("mean_obliq_ecliptic_degrees=" + mean_obliq_ecliptic_degrees); var obliq_corr_degrees = mean_obliq_ecliptic_degrees+0.00256*Math.cos(Math2.to_radians(125.04-1934.136*julian_century)) //console.log("obliq_corr_degrees=" + obliq_corr_degrees); var sun_declin_degrees = Math2.to_degrees( Math.asin(Math.sin(Math2.to_radians(obliq_corr_degrees))*Math.sin(Math2.to_radians(sun_app_long_degress))) ); //console.log("sun_declin_degrees=" + sun_declin_degrees); var var_y = Math.tan(Math2.to_radians(obliq_corr_degrees/2))*Math.tan(Math2.to_radians(obliq_corr_degrees/2)); //console.log("var_y=" + var_y); var eq_of_time = 4*Math2.to_degrees( var_y*Math.sin(2*Math2.to_radians(geom_mean_long_sun_degrees))- 2*eccent_earth_orbit*Math.sin(Math2.to_radians(geom_mean_anomaly_sun_degrees))+ 4*eccent_earth_orbit*var_y*Math.sin(Math2.to_radians(geom_mean_anomaly_sun_degrees))*Math.cos(2*Math2.to_radians(geom_mean_long_sun_degrees))- 0.5*var_y*var_y*Math.sin(4*Math2.to_radians(geom_mean_long_sun_degrees))- 1.25*eccent_earth_orbit*eccent_earth_orbit*Math.sin(2*Math2.to_radians(geom_mean_anomaly_sun_degrees)) ); //console.log("eq_of_time=" + eq_of_time); var HA_sunrise_degrees = Math2.to_degrees( Math.acos( Math.cos(Math2.to_radians(90.833))/(Math.cos(Math2.to_radians(latitude))*Math.cos(Math2.to_radians(sun_declin_degrees)))- Math.tan(Math2.to_radians(latitude))*Math.tan(Math2.to_radians(sun_declin_degrees)) ) ); //console.log("HA_sunrise_degrees=" + HA_sunrise_degrees); var local_offset_hours = new Date().getTimezoneOffset()/60; if(utc_offset == null){ utc_offset = -local_offset_hours; } var timezone_offset_hours = utc_offset; //(utc_offset - local_offset_hours); console.log("timezone_offset_hours=" + timezone_offset_hours + " longitude" + longitude + " utc_offset=" + utc_offset ); var solar_noon = (720-4*longitude-eq_of_time+timezone_offset_hours*60)/1440; var solar_noon_datetime = _to_time(now,solar_noon); console.log("solar_noon=" + solar_noon + "->" + solar_noon_datetime.toISOString()); var sunrise_time_LST = (solar_noon*1440-HA_sunrise_degrees*4)/1440; var sunrise_time_LST_datetime = _to_time(now,sunrise_time_LST); console.log("sunrise_time_LST=" + sunrise_time_LST + "->" + sunrise_time_LST_datetime.toISOString()); var sunset_time_LST =(solar_noon*1440+HA_sunrise_degrees*4)/1440; var sunset_time_LST_datetime = _to_time(now,sunset_time_LST); console.log("sunset_time_LST=" + sunset_time_LST + "->" + sunset_time_LST_datetime.toISOString()); return { day_start: new Date(solar_noon_datetime.getTime() - _DAY_MILLIS / 2), sunrise_date: sunrise_time_LST_datetime, //sunrise_fraction: sunrise_time_LST, sunset_date: sunset_time_LST_datetime, //sunset_fraction: sunset_time_LST, solar_noon: solar_noon_datetime, day_end: new Date(solar_noon_datetime.getTime() + _DAY_MILLIS / 2) }; }, now_fraction_of_day: (now,day_info)=>{ return (now.getTime() - day_info.day_start.getTime())/_DAY_MILLIS; }, } module.exports = DateUtils;