generateYearData.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import * as MeeusSunMoon from 'meeussunmoon';
  2. import * as luxon from 'luxon';
  3. import { equinoxes } from './equinoxes';
  4. import * as fs from 'fs';
  5. const latitudeTihran = 35.68;
  6. const longitudeTihran = 51.42;
  7. const nawRuzEndTihranUTC = (equinox: string): luxon.DateTime => {
  8. const vernalEquinox = luxon.DateTime.fromISO(equinox, { zone: 'UTC' });
  9. let nawRuzTihran = MeeusSunMoon.sunset(vernalEquinox, latitudeTihran, longitudeTihran) as luxon.DateTime;
  10. if (vernalEquinox > nawRuzTihran) {
  11. nawRuzTihran = MeeusSunMoon.sunset(
  12. vernalEquinox.plus({ days: 1 }), latitudeTihran, longitudeTihran) as luxon.DateTime;
  13. }
  14. return nawRuzTihran;
  15. };
  16. const calculateTwinBirthdays = (nawRuzTihran: luxon.DateTime): number[] => {
  17. let eighthNewMoon: luxon.DateTime;
  18. const nawRuzEnd = MeeusSunMoon.sunset(nawRuzTihran, latitudeTihran, longitudeTihran);
  19. const newMoons = MeeusSunMoon.yearMoonPhases(nawRuzTihran.year, 0);
  20. let index = 0;
  21. // Count the new moons since Naw-Rúz and keep the eighth one
  22. for (let i = 0; i < newMoons.length; i++) {
  23. if (newMoons[i] > nawRuzEnd) {
  24. index++;
  25. }
  26. if (index === 8) {
  27. eighthNewMoon = newMoons[i];
  28. break;
  29. }
  30. }
  31. // Convert to the proper timezone and calculate sunset.
  32. eighthNewMoon.setZone('Asia/Tehran');
  33. const newMoonSunset = MeeusSunMoon.sunset(eighthNewMoon, latitudeTihran, longitudeTihran);
  34. // If sunset is before the new moon, the new moon is on the next Badí' date.
  35. // Then we add another day because it's the day after the occurence of the
  36. // eighth new moon.
  37. if (newMoonSunset < eighthNewMoon) {
  38. eighthNewMoon = eighthNewMoon.plus({ days: 1 });
  39. }
  40. eighthNewMoon = eighthNewMoon.plus({ days: 1 });
  41. const dayOfBadiYear = eighthNewMoon.ordinal - nawRuzTihran.ordinal + 1;
  42. const day2OfBadiYear = dayOfBadiYear + 1;
  43. return [Math.floor((dayOfBadiYear - 1) / 19 + 1), (dayOfBadiYear - 1) % 19 + 1,
  44. Math.floor((day2OfBadiYear - 1) / 19 + 1), (day2OfBadiYear - 1) % 19 + 1];
  45. };
  46. const yearList = () => {
  47. let longList = 'const badiYears = {';
  48. let shortList = 'const badiYears = [\n';
  49. // Stop at end of 2350 AD / 507 BE as the Naw-Rúz 509 BE is potentially too
  50. // close to call
  51. const equinoxesLength = 337;
  52. for (let i = 0; i < equinoxesLength - 1; i++) {
  53. const nawRuzTihran = nawRuzEndTihranUTC(equinoxes[i]);
  54. const nextNawRuzTihran = nawRuzEndTihranUTC(equinoxes[i + 1]);
  55. const ayyamiHaLength = Math.round(nextNawRuzTihran.diff(nawRuzTihran).as('days') - 361);
  56. const twinBirthdays = calculateTwinBirthdays(nawRuzTihran);
  57. longList += `
  58. ${(i + 172).toString()}: {
  59. ayyamiHaLength: ${ayyamiHaLength},
  60. nawRuz: '${nawRuzTihran.toFormat('yyyy-MM-dd')}',
  61. twinBirthdays: [${twinBirthdays[0]}, ${twinBirthdays[1]}, ${twinBirthdays[2]}, ${twinBirthdays[3]}],
  62. },`;
  63. shortList += `${i % 14 === 0 ? ' ' : ''}'${shortListString(
  64. nawRuzTihran, ayyamiHaLength, twinBirthdays)}',${i % 14 === 13 ? '\n' : ' '}`;
  65. }
  66. shortList += '];\n\nexport { badiYears };\n';
  67. longList += '\n};\n\nexport { badiYears };\n';
  68. fs.writeFileSync('./res/badiYearsLongFormat.ts', longList, 'utf8');
  69. fs.writeFileSync('./src/badiYears.ts', shortList, 'utf8');
  70. };
  71. const shortListString = (nawRuz, ayyamiHaLength, twinBirthdays) => `${nawRuz.day.toString(36)}${
  72. ayyamiHaLength.toString(36)}${twinBirthdays[0].toString(36)}${twinBirthdays[1].toString(36)}`;
  73. yearList();
  74. export { latitudeTihran, longitudeTihran, nawRuzEndTihranUTC, calculateTwinBirthdays, yearList };