/* * This algorithm accepts a month in the format mm/yyyy. * And prints out the month's calendar. * It uses an epoch of 1/1/1900, Monday. */ import { isLeapYear } from '../Maths/LeapYear' class Month { constructor() { this.Days = ['M', 'T', 'W', 'Th', 'F', 'S', 'Su'] this.BDays = ['M', 'Su', 'S', 'F', 'Th', 'W', 'T'] this.epoch = { month: 1, year: 1900 } this.monthDays = [31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] this.monthDaysLeap = [31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] } printCal(days, startDay, output = (value) => console.log(value)) { output('M T W Th F S Su') const dates = [] let i for (i = 1; i <= days; i++) { dates.push(i) } for (i = 0; i < this.Days.indexOf(startDay); i++) { dates.unshift(' ') } while (true) { let row = '' for (i = 0; i < 7 && dates.length !== 0; i++) { row += dates.shift() while (row.length % 4 !== 0) { row += ' ' } } output(row) if (dates.length === 0) break } } parseDate(date) { const dateAr = [] let block = '' let i for (i = 0; i < date.length; i++) { if (date[i] === '/') { dateAr.push(parseInt(block)) block = '' continue } block += date[i] } dateAr.push(parseInt(block)) if (dateAr.length !== 2) throw new Error('Improper string encoding') const dateOb = { month: dateAr[0], year: dateAr[1] } return dateOb } isGreater(startDate, endDate) { if (startDate.year > endDate.year) { return true } else if (startDate.year < endDate.year) { return false } else if (startDate.month > endDate.month) { return true } else if (startDate.month < endDate.month) { return false } return true } getDayDiff(startDate, endDate) { if (this.isGreater(startDate, endDate) === null) { return 0 } else if (this.isGreater(startDate, endDate) === true) { const midDate = startDate startDate = endDate endDate = midDate } let diff = 0 while (startDate.year !== endDate.year) { diff += isLeapYear(startDate.year) ? 366 : 365 startDate.year = startDate.year + 1 } while (startDate.month !== endDate.month) { if (startDate.month < endDate.month) { if (isLeapYear(startDate.year)) diff += this.monthDaysLeap[startDate.month] else diff += this.monthDays[startDate.month] startDate.month = startDate.month + 1 } else { if (isLeapYear(startDate.year)) diff -= this.monthDaysLeap[startDate.month - 1] else diff -= this.monthDays[startDate.month - 1] startDate.month = startDate.month - 1 } } return diff } generateMonthCal(date) { const Month = this.parseDate(date) let day = '' let difference = this.getDayDiff(this.epoch, Month) difference = difference % 7 let Month2 = this.parseDate(date) day = this.isGreater(Month2, this.epoch) ? this.Days[difference] : this.BDays[difference] Month2 = this.parseDate(date) if (isLeapYear(Month2.year)) this.printCal(this.monthDaysLeap[Month2.month], day) else this.printCal(this.monthDays[Month2.month], day) } } export { Month } // const x = new Month() // x.generateMonthCal('1/2021')