/** * Format a date according to localized custom * @param {Date|string} d The date to convert * @param {boolean} short Short format (default false) * @returns {string} */ export function format_date(d,short){ if(!(d instanceof Date)){ d = new Date(d); } let monthformat = "short"; if(short === true){ monthformat = "numeric"; } else if (short === false) { monthformat = "long"; } return d.toLocaleDateString(document.documentElement.lang,{ year: 'numeric', month: monthformat, day: 'numeric' }); } /** * Provides standardized information about the period between two dates * As * @param {Date|string} first First day of the span * @param {Date|string} last Last day of the span * @returns {Object} Object containing formatted start and end dates and span information */ export function datespaninfo(first,last){ if(!(first instanceof Date)){ first = new Date(first);} if(!(last instanceof Date)){ last = new Date(last);} // Make sure the end date is at the very end of the day and the start date at the very beginning first.setHours(0); first.setMinutes(0); first.setSeconds(0); first.setMilliseconds(0); last.setHours(23); last.setMinutes(59); last.setSeconds(59); last.setMilliseconds(999); const dayspan = Math.round(((last - first)+1)/(24*60*60*1000)); // Add one millisecond to offset the 999 ms const years = Math.floor(dayspan/365); // Yes, we ignore leap years/leap days const ydaysleft = dayspan % 365; const weeks = Math.floor(ydaysleft/7); const wdaysleft = ydaysleft % 7; return { first: first, last: last, totaldays: dayspan, years: years, weeks: weeks, days: wdaysleft, formatted: { first: format_date(first), last: format_date(last), } }; } /** * Format a Date object to YYYY-MM-DD format * @param {Date} date Date object * @returns Date string in YYYY-MM-DD format */ function dateYYYYMMDD(date) { const d = new Date(date); let month = '' + (d.getMonth() + 1); let day = '' + d.getDate(); const year = d.getFullYear(); if (month.length < 2) { month = '0' + month; } if (day.length < 2) { day = '0' + day; } return [year, month, day].join('-'); } /** * String formatting function - replaces {name} in string by value of same key in values parameter * @param {string} datestr String containing date format in YYYY-MM-DD * @param {int} days Object containing keys to replace {key} strings with. Make negative to subtract * @returns Date string in YYYY-MM-DD format */ export function add_days(datestr,days) { const date = new Date(datestr); const newdate = new Date(date.getTime() + (days * 86400000) ); // Add n days in ms. return dateYYYYMMDD(newdate); } /** * Determine start and end dates of a studyplan * @param {*} plan * @returns */ export function studyplanDates(plan) { let earliestStart = null; let latestEnd = null; let openEnded = false; for(const ix in plan.pages) { const page = plan.pages[ix]; const s = new Date(page.startdate); if (! page.enddate) { openEnded = true; // One of the pages has no end date set... } if (!earliestStart || s < earliestStart) { earliestStart = s; } if ( page.enddate ) { const e = new Date(page.enddate); if (!latestEnd || e > latestEnd) { latestEnd = e; } } } return { start: earliestStart, end: (openEnded)?null:latestEnd, }; } /** * Determine past/present/future for a studyplan * @param {*} plan * @returns {string} one of 'past', 'present', 'future' */ export function studyplanTiming(plan) { const now = new Date().getTime(); const dates = studyplanDates(plan); if(dates.start < now){ if( dates.end && now > dates.end) { return 'past'; } else { return 'present'; } } else { return 'future'; } } /** * Determine past/present/future for a studyplan * @param {*} page * @returns {string} one of 'past', 'present', 'future' */ export function studyplanPageTiming(page) { const now = new Date().getTime(); const start = new Date(page.startdate); const end = (page.enddate)?(new Date(page.enddate)):null; if(start < now){ if( end && now > end) { return 'past'; } else { return 'present'; } } else { return 'future'; } }