// utilities function used for both the watch and the calendar // MOONPHASES PICTO // ============================================================================ //shapes of the moon from north hemispheres //otherwise the picto are left-right inversed (and at the equator the crescent are in the bottom-top direction) const MOONPHASES = [ { name_en: 'new moon', //not visible: not in nightsky, and in daysky it's the hidden side that's light up by the sun name_fr: 'nouvelle lune', name_nl: 'nieuwe maan', name_es: 'luna nueva', picto: '🌑', }, { name_en: 'waxing crescent', //in daysky, but a bit in the west: from late morning to post-dusk, not in nightsky name_fr: 'premier croissant', name_nl: 'jonge maansikkel', name_es: 'creciente cóncava', picto: '🌒', }, { name_en: 'first quarter', //at the west intersection of night and day skies -> begin to appear in night: afternoon to early evening name_fr: 'premier quartier', name_nl: 'eerste kwartier', name_es: 'cuarto creciente', picto: '🌓', }, { name_en: 'waxing gibbous', //in the nightsky, but a bit in the west: from late afternoon to most of the night name_fr: 'gibbeuse croissante', name_nl: 'wassende maan', name_es: 'creciente gibosa', picto: '🌔', }, { name_en: 'full moon', //all night: sunset to sunrise name_fr: 'pleine lune', name_nl: 'volle maan', name_es: 'luna llena', picto: '🌕', }, { name_en: 'waning gibbous', //in the nightsky, but a bit in the east: most of the night to early morning name_fr: 'gibbeuse décroissante', name_nl: 'krimpende maan', name_es: 'menguante gibosa', picto: '🌖', }, { name_en: 'last quarter', //at the east intersection of night and day skies -> begin to appear in day: late night to morning name_fr: 'dernier quartier', name_nl: 'laatste kwartier', name_es: 'cuarto menguante', picto: '🌗', }, { name_en: 'waning crescent', //in daysky, but a bit in the east: from pre-dawn to early afternoon, not in nightsky name_fr: 'dernier croissant', name_nl: 'krimpende maansikkel', name_es: 'menguante cóncava', picto: '🌘', } ] function getLocalFromURL(){ let local = ""; let url = window.location.href; let filename = url.split("/").pop().split(".")[0]; let lang_split = filename.split("_"); if (lang_split.length == 1){ local = "en-gb"; } else{ if (lang_split[1] == "fr"){ local = "fr-be"; } else if (lang_split[1] == "nl"){ local = "nl-be"; } else if (lang_split[1] == "es"){ local = "es-es"; } } return local; } // JS DATE FORMATING // ============================================================================ function format_date_time(date){ // format date object everywhere the same on the website formated_date = {} formated_date['day'] = new Intl.DateTimeFormat('en-GB', { weekday: 'long' }).format(date); // formated_date['date'] = new Intl.DateTimeFormat('fr-BE', { // day: 'numeric', // month: 'numeric', // year: 'numeric' // }).format(date); formated_date['date'] = { day: ('0' + date.getDate()).slice(-2), month: ('0' + String(date.getMonth()+1)).slice(-2), year: date.getFullYear().toString().slice(-2) } formated_date['date'] = Object.values(formated_date['date']).join("."); formated_date['time'] = new Intl.DateTimeFormat('fr-BE', { // timeStyle: 'long' timeStyle: 'short' }).format(date); return formated_date; } function format_luxon_date(date){ formated_date = {}; date = date.setLocale(window.current_local); // date = date.setLocale('en-gb'); // date = date.setLocale('fr-be'); // date = date.setLocale('sp'); // date = date.setLocale('nl-be'); formated_date['day'] = date.toLocaleString({weekday: 'long'}); formated_date['date'] = date.toLocaleString({month: '2-digit', day: '2-digit', year: '2-digit'}); formated_date['time'] = date.toLocaleString({timeStyle: 'short'}); // for stylistic purposes formated_date['date'] = formated_date['date'].split("/").join("."); return formated_date; } // MOON COMPUTATION // ============================================================================ // average length of a lunation const LUNATION = 29.53058770576; // eps is the little interval around singular event to consider them as short period // otherwise we will never show "full moon" for example // 0.5, means we show "full moon" 12h before and 12h after the exact event const EPS = 0.5 / LUNATION; function getMoonDataFromPhase(phase){ // take a 0 ot 1 number and return an object with all data for display if (phase < EPS) return MOONPHASES[0]; else if(phase < 0.25 - EPS) return MOONPHASES[1]; else if(phase < 0.25 + EPS) return MOONPHASES[2]; else if(phase < 0.5 - EPS) return MOONPHASES[3]; else if(phase < 0.5 + EPS) return MOONPHASES[4]; else if(phase < 0.75 - EPS) return MOONPHASES[5]; else if(phase < 0.75 + EPS) return MOONPHASES[6]; else if(phase < 1 - EPS) return MOONPHASES[7]; else return MOONPHASES[0]; } function getMoonStateFromDate(date, lat=0, long=0){ // return a moon object containing everything that we need let mooncalc_illumination = SunCalc.getMoonIllumination(date); let moon = getMoonDataFromPhase(mooncalc_illumination.phase); moon['illumination'] = mooncalc_illumination.fraction; moon['phase'] = mooncalc_illumination.phase; /* TODO: those data depend of the location on earth!! lat and lon to precise */ let mooncalc_position = SunCalc.getMoonPosition(date, lat, long); moon['distance'] = mooncalc_position.distance; return moon; } function getSunStateFromDate(date, lat=0, long=0, timezone){ // --- get suncalc sun object // for complementary info such as: sunset time // Note: suncalc gives us sunset time as a date object // meaning if we just print it it will print in local user time // what we need to do: // js sunset_time --> ISO string in UTC --> luxon sunset_time // set proper timezone to luxon sunset_time // print it in it's timezone let sun_calc = SunCalc.getTimes(date, lat, long); let sunrise = sun_calc["sunrise"]; let sunset = sun_calc["sunset"]; let offset_sunset = luxon.DateTime.fromISO(sunset.toISOString()); offset_sunset = offset_sunset.setZone(timezone); let offset_sunrise = luxon.DateTime.fromISO(sunrise.toISOString()); offset_sunrise = offset_sunrise.setZone(timezone); return [offset_sunrise, offset_sunset]; } // PHASE TO TYPO // ============================================================================ function mapValue(value, min, max, new_min, new_max){ return (((value - min) / (max - min)) * (new_max - new_min)) + new_min; } function getCircle(value){ // return a (x, y) tuple describing a circle of radius 1 at (0,0) // value goes from 0 to 1 // with i=0 being the top pole, and i=0.5 is the bottom pole let theta = value * 2 * Math.PI; let x = Math.sin(theta); let y = Math.cos(theta); // console.log(i, x, y); // NOTE: at i=0.5 we should have x=0 and y = -1, 7 // but we get a js rounding error for x return [x,y]; } function updateAxis($element, value, secondAxis=true){ // take a jquery element and a value from 0 to 1 // and write the css line to update the two variable font axis // OLD CODE for losange // 0 at new moon, 1 at full moon // let x = (Math.abs(i - 0.5) * -2) + 1; // 1 at first quart and last quarter, 0 at new and full moon // let y = (Math.abs(x - 0.5) * -2) + 1; let [x, y] = getCircle(value); // let weight = mapValue(x, 0, 1, 100, 500); // let wght = '"wght" ' + weight; // let slant = mapValue(y, 0, 1, 0, -10); // let slnt = '"slnt" ' + slant; let axis_1 = '"SERI" ' + mapValue(y, -1, 1, 100, 0); let axis_2 = '"slnt" ' + mapValue(x, -1, 1, -100, 100); let settings = secondAxis ? axis_1 + ", " + axis_2 : axis_1; $element.css("font-variation-settings", settings); $element.addClass("computed"); } $(document).ready(function(){ window.current_local = getLocalFromURL(); });