1 const paMacros = require('./pa-macros.js');
  2 const paTypes = require('./pa-types.js');
  3 const paUtils = require('./pa-utils.js');
  4 
  5 /**
  6  * Gets the date of Easter for the year specified.
  7  */
  8 function getDateOfEaster(inputYear) {
  9     var year = inputYear;
 10 
 11     var a = year % 19;
 12     var b = Math.floor(year / 100);
 13     var c = year % 100;
 14     var d = Math.floor(b / 4);
 15     var e = b % 4;
 16     var f = Math.floor((b + 8) / 25);
 17     var g = Math.floor((b - f + 1) / 3);
 18     var h = ((19 * a) + b - d - g + 15) % 30;
 19     var i = Math.floor(c / 4);
 20     var k = c % 4;
 21     var l = (32 + 2 * (e + i) - h - k) % 7;
 22     var m = Math.floor((a + (11 * h) + (22 * l)) / 451);
 23     var n = Math.floor((h + l - (7 * m) + 114) / 31);
 24     var p = (h + l - (7 * m) + 114) % 31;
 25 
 26     var day = p + 1;
 27     var month = n;
 28 
 29     return [month, day, year];
 30 }
 31 
 32 /**
 33  * Calculate day number for a date.
 34  */
 35 function civilDateToDayNumber(month, day, year) {
 36     if (month <= 2) {
 37         month = month - 1;
 38         month = (paUtils.isLeapYear(year)) ? month * 62 : month * 63;
 39         month = Math.floor(month / 2);
 40     }
 41     else {
 42         month = Math.floor((month + 1) * 30.6);
 43         month = (paUtils.isLeapYear(year)) ? month - 62 : month - 63;
 44     }
 45 
 46     return month + day;
 47 }
 48 
 49 /**
 50  * Convert a Civil Time (hours,minutes,seconds) to Decimal Hours
 51  */
 52 function civilTimeToDecimalHours(hours, minutes, seconds) {
 53     return paMacros.HMStoDH(hours, minutes, seconds);
 54 }
 55 
 56 /**
 57  * Convert Decimal Hours to Civil Time
 58  */
 59 function decimalHoursToCivilTime(decimalHours) {
 60     var hours = paMacros.decimalHoursHour(decimalHours);
 61     var minutes = paMacros.decimalHoursMinute(decimalHours);
 62     var seconds = paMacros.decimalHoursSecond(decimalHours);
 63 
 64     return [hours, minutes, seconds];
 65 }
 66 
 67 /**
 68  * Convert local Civil Time to Universal Time
 69  */
 70 function localCivilTimeToUniversalTime(lctHours, lctMinutes, lctSeconds, isDaylightSavings, zoneCorrection, localDay, localMonth, localYear) {
 71     var lct = civilTimeToDecimalHours(lctHours, lctMinutes, lctSeconds);
 72 
 73     var daylightSavingsOffset = (isDaylightSavings) ? 1 : 0;
 74 
 75     var utInterim = lct - daylightSavingsOffset - zoneCorrection;
 76     var gdayInterim = localDay + (utInterim / 24);
 77 
 78     var jd = paMacros.civilDateToJulianDate(gdayInterim, localMonth, localYear);
 79 
 80     var gDay = paMacros.julianDateDay(jd);
 81     var gMonth = paMacros.julianDateMonth(jd);
 82     var gYear = paMacros.julianDateYear(jd);
 83 
 84     var ut = 24 * (gDay - Math.floor(gDay));
 85 
 86     return [
 87         paMacros.decimalHoursHour(ut),
 88         paMacros.decimalHoursMinute(ut),
 89         paMacros.decimalHoursSecond(ut),
 90         Math.floor(gDay),
 91         gMonth,
 92         gYear
 93     ];
 94 }
 95 
 96 /**
 97  * Convert Universal Time to local Civil Time
 98  */
 99 function universalTimeToLocalCivilTime(utHours, utMinutes, utSeconds, isDaylightSavings, zoneCorrection, gwDay, gwMonth, gwYear) {
100     var dstValue = (isDaylightSavings) ? 1 : 0;
101     var ut = paMacros.HMStoDH(utHours, utMinutes, utSeconds);
102     var zoneTime = ut + zoneCorrection;
103     var localTime = zoneTime + dstValue;
104     var localJDPlusLocalTime = paMacros.civilDateToJulianDate(gwDay, gwMonth, gwYear) + (localTime / 24);
105     var localDay = paMacros.julianDateDay(localJDPlusLocalTime);
106     var integerDay = Math.floor(localDay);
107     var localMonth = paMacros.julianDateMonth(localJDPlusLocalTime);
108     var localYear = paMacros.julianDateYear(localJDPlusLocalTime);
109 
110     var lct = 24 * (localDay - integerDay);
111 
112     return [
113         paMacros.decimalHoursHour(lct),
114         paMacros.decimalHoursMinute(lct),
115         paMacros.decimalHoursSecond(lct),
116         integerDay,
117         localMonth,
118         localYear
119     ];
120 }
121 
122 /**
123  * Convert Universal Time to Greenwich Sidereal Time
124  */
125 function universalTimeToGreenwichSiderealTime(utHours, utMinutes, utSeconds, gwDay, gwMonth, gwYear) {
126     var jd = paMacros.civilDateToJulianDate(gwDay, gwMonth, gwYear);
127     var s = jd - 2451545;
128     var t = s / 36525;
129     var t01 = 6.697374558 + (2400.051336 * t) + (0.000025862 * t * t);
130     var t02 = t01 - (24.0 * Math.floor(t01 / 24));
131     var ut = paMacros.HMStoDH(utHours, utMinutes, utSeconds);
132     var a = ut * 1.002737909;
133     var gst1 = t02 + a;
134     var gst2 = gst1 - (24.0 * Math.floor(gst1 / 24));
135 
136     var gstHours = paMacros.decimalHoursHour(gst2);
137     var gstMinutes = paMacros.decimalHoursMinute(gst2);
138     var gstSeconds = paMacros.decimalHoursSecond(gst2);
139 
140     return [gstHours, gstMinutes, gstSeconds];
141 }
142 
143 /**
144  * Convert Greenwich Sidereal Time to Universal Time
145  */
146 function greenwichSiderealTimeToUniversalTime(gstHours, gstMinutes, gstSeconds, gwDay, gwMonth, gwYear) {
147     var jd = paMacros.civilDateToJulianDate(gwDay, gwMonth, gwYear);
148     var s = jd - 2451545;
149     var t = s / 36525;
150     var t01 = 6.697374558 + (2400.051336 * t) + (0.000025862 * t * t);
151     var t02 = t01 - (24 * Math.floor(t01 / 24));
152     var gstHours1 = paMacros.HMStoDH(gstHours, gstMinutes, gstSeconds);
153 
154     var a = gstHours1 - t02;
155     var b = a - (24 * Math.floor(a / 24));
156     var ut = b * 0.9972695663;
157     var utHours = paMacros.decimalHoursHour(ut);
158     var utMinutes = paMacros.decimalHoursMinute(ut);
159     var utSeconds = paMacros.decimalHoursSecond(ut);
160 
161     var warningFlag = (ut < 0.065574) ? paTypes.WarningFlag.Warning : paTypes.WarningFlag.OK;
162 
163     return [utHours, utMinutes, utSeconds, warningFlag];
164 }
165 
166 /**
167  * Convert Greenwich Sidereal Time to Local Sidereal Time
168  */
169 function greenwichSiderealTimeToLocalSiderealTime(gstHours, gstMinutes, gstSeconds, geographicalLongitude) {
170     var gst = paMacros.HMStoDH(gstHours, gstMinutes, gstSeconds);
171     var offset = geographicalLongitude / 15;
172     var lstHours1 = gst + offset;
173     var lstHours2 = lstHours1 - (24 * Math.floor(lstHours1 / 24));
174 
175     var lstHours = paMacros.decimalHoursHour(lstHours2);
176     var lstMinutes = paMacros.decimalHoursMinute(lstHours2);
177     var lstSeconds = paMacros.decimalHoursSecond(lstHours2);
178 
179     return [lstHours, lstMinutes, lstSeconds];
180 }
181 
182 /**
183  * Convert Local Sidereal Time to Greenwich Sidereal Time
184  */
185 function localSiderealTimeToGreenwichSiderealTime(lstHours, lstMinutes, lstSeconds, geographicalLongitude) {
186     var gst = paMacros.HMStoDH(lstHours, lstMinutes, lstSeconds);
187     var longHours = geographicalLongitude / 15;
188     var gst1 = gst - longHours;
189     var gst2 = gst1 - (24 * Math.floor(gst1 / 24));
190 
191     var gstHours = paMacros.decimalHoursHour(gst2);
192     var gstMinutes = paMacros.decimalHoursMinute(gst2);
193     var gstSeconds = paMacros.decimalHoursSecond(gst2);
194 
195     return [gstHours, gstMinutes, gstSeconds];
196 }
197 
198 
199 module.exports = {
200     getDateOfEaster,
201     civilDateToDayNumber,
202     civilTimeToDecimalHours,
203     decimalHoursToCivilTime,
204     localCivilTimeToUniversalTime,
205     universalTimeToLocalCivilTime,
206     universalTimeToGreenwichSiderealTime,
207     greenwichSiderealTimeToUniversalTime,
208     greenwichSiderealTimeToLocalSiderealTime,
209     localSiderealTimeToGreenwichSiderealTime
210 };
211