MDY Error Calculator
by _sir
HTML
<script src="https://unpkg.com/[email protected]/moment.js"></script>
<h1>
DMY to MDY Error Calculator
</h1>
<p>
Identify issues caused by unintentionally translating between DD/MM/YYYY and MM/DD/YYYY formats with the range of selectable dates.
</p>
<hr>
<div id="yearly">
<h2>
Whole Year Calculations
</h2>
<p>
Collect the available options for every day of a year and reports the aggregate counts.
</p>
<section>
<form name="yearly" id="yearlyForm" onsubmit="return false">
<fieldset>
<legend>Yearly Settings</legend>
<div><label><span>Minimum Offset</span> <input name="offsetMin" type="number" value="0"></label></div>
<div><label><span>Maximum Offset</span> <input name="offsetMax" type="number" value="42"></label></div>
<div><label><span>Include Weekends</span> <input name="weekends" type="checkbox"></label></div>
<div><label><span></span> <button id="calcYearly">Calculate</button></label></div>
</fieldset>
</form>
<fieldset>
<legend>Yearly Reporting</legend>
<div id="yearlyReport"></div>
</fieldset>
</section>
</div>
<div id="yearly">
<h2>
Specific Day Issues
</h2>
<p>
Report the available issues for a single day as an issue object.
</p>
<section>
<form name="day" id="dayForm" onsubmit="return false">
<fieldset>
<legend>Daily Detail</legend>
<div><label><span>Date (ISO format)</span> <input id="todayDate" name="isoDate" type="text" value=""></label></div>
<div><label><span>Minimum Offset</span> <input name="offsetMin" type="number" value="0"></label></div>
<div><label><span>Maximum Offset</span> <input name="offsetMax" type="number" value="42"></label></div>
<div><label><span>Include Weekends</span> <input name="weekends" type="checkbox"></label></div>
<div><label><span></span> <button id="calcDay">Calculate</button></label></div>
</fieldset>
</form>
<fieldset>
...
CSS
body {
margin: 1em;
}
section {
display: flex;
}
fieldset {
width: 40%;
min-width: 30em;
margin: 1em;
}
legend {
font-weight: bold;
}
fieldset label>span {
display: inline-block;
width: 10em;
text-align: right;
padding-right: 1em;
}
fieldset>div {
margin: 5px;
}
JavaScript
const ISO = 'YYYY-MM-DD';
const MDY = 'MM/DD/YYYY';
const DMY = 'DD/MM/YYYY';
const DOY = 'DDD YYYY';
const makeDateFromDoY = (dayOfYear) => moment(`${dayOfYear} 2023`, DOY);
const parseIso = (isoDate) => moment(isoDate, ISO);
const isoToDMY = (isoDate) => parseIso(isoDate).format(DMY);
const isoToMDY = (isoDate) => parseIso(isoDate).format(MDY);
const changeDMYtoMDYfromIso = (isoDate) => moment(isoToDMY(isoDate), MDY);
const isDMYValidMDY = (isoDate) => changeDMYtoMDYfromIso(isoDate).isValid();
const isNotWeekend = (isoDate) => ![0, 6].includes(parseIso(isoDate).weekday());
const isFlipNotWeekend = (isoDate) => isNotWeekend(changeDMYtoMDYfromIso(isoDate));
// Build Source Data
const dates = new Array(365).fill('')
.map((v, i) => makeDateFromDoY(i + 1).format(ISO));
const validDMY = dates.filter(isDMYValidMDY);
const isInValidMDY = (isoDate) => validDMY.includes(isoDate);
// Second-round functions
const checkMDYOffsets = (isoDate, minOffset, maxOffset, includeWeekends = false) => {
const weekendFilter = includeWeekends ? () => true : isNotWeekend;
const startDate = parseIso(isoDate);
const validDates = new Array(maxOffset - minOffset).fill('')
.map((v, i) => parseIso(isoDate).add(i + minOffset, 'days').format(ISO))
.filter(weekendFilter);
const checkDates = validDates.filter(isDMYValidMDY);
const pastDates = checkDates.filter((date) => changeDMYtoMDYfromIso(date).isBefore(startDate, 'day'));
const validFlips = checkDates.filter((date) => changeDMYtoMDYfromIso(date).diff(startDate, 'days') <= maxOffset).filter(isFlipNotWeekend);
const futureDates = checkDates.filter((date) => changeDMYtoMDYfromIso(date).diff(startDate, 'days') > maxOffset);
const futureWeekends = futureDates.filter((date) => !isNotWeekend(changeDMYtoMDYfromIso(date)));
const futureOutOfRange = futureDates
const problemCount = pastDates.length + futureDates.length - (includeWeekends ? futureWeekends.length : 0);
return {
date: isoDate,
minOffset,
...