fix: DateToDay (#1125)

This commit is contained in:
Chetan Patil
2022-10-10 08:01:58 +02:00
committed by GitHub
parent e32fdce52f
commit d94929ea0d
2 changed files with 52 additions and 39 deletions

View File

@ -9,35 +9,11 @@
algorithm shown below gives us the number of the day and
finally converts it to the name of the day.
Algorithm & Explanation : https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html
Algorithm & Explanation : https://en.wikipedia.org/wiki/Zeller%27s_congruence
*/
// March is taken as the first month of the year.
const calcMonthList = {
1: 11,
2: 12,
3: 1,
4: 2,
5: 3,
6: 4,
7: 5,
8: 6,
9: 7,
10: 8,
11: 9,
12: 10
}
// show the week day in a number : Sunday - Saturday => 0 - 6
const daysNameList = { // weeks-day
0: 'Sunday',
1: 'Monday',
2: 'Tuesday',
3: 'Wednesday',
4: 'Thursday',
5: 'Friday',
6: 'Saturday'
}
// Array holding name of the day: Saturday - Sunday - Friday => 0 - 1 - 6
const daysNameArr = ['Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
const DateToDay = (date) => {
// firstly, check that input is a string or not.
@ -45,18 +21,40 @@ const DateToDay = (date) => {
return new TypeError('Argument is not a string.')
}
// extract the date
const [day, month, year] = date.split('/').map((x) => Number(x))
let [day, month, year] = date.split('/').map((x) => Number(x))
// check the data are valid or not.
if (day < 0 || day > 31 || month > 12 || month < 0) {
if (day < 1 || day > 31 || month > 12 || month < 1) {
return new TypeError('Date is not valid.')
}
// divide year to century and yearDigit value.
const yearDigit = (year % 100)
// In case of Jan and Feb:
// Year: we consider it as previous year
// e.g., 1/1/1987 here year is 1986 (-1)
// Month: we consider value as 13 & 14 respectively
if (month < 3) {
year--
month += 12
}
// divide year into century and the last two digits of the century
const yearDigits = year % 100
const century = Math.floor(year / 100)
// Apply the algorithm shown above
const weekDay = Math.abs((day + Math.floor((2.6 * calcMonthList[month]) - 0.2) - (2 * century) + yearDigit + Math.floor(yearDigit / 4) + Math.floor(century / 4)) % 7)
// return the weekDay name.
return daysNameList[weekDay]
/*
In mathematics, remainders of divisions are usually defined to always be positive;
As an example, -2 mod 7 = 5.
Many programming languages including JavaScript implement the remainder of `n % m` as `sign(n) * (abs(n) % m)`.
This means the result has the same sign as the numerator. Here, `-2 % 7 = -1 * (2 % 7) = -2`.
To ensure a positive numerator, the formula is adapted: `- 2 * century` is replaced with `+ 5 * century`
which does not alter the resulting numbers mod 7 since `7 - 2 = 5`
The following example shows the issue with modulo division:
Without the adaption, the formula yields `weekDay = -6` for the date 2/3/2014;
With the adaption, it yields the positive result `weekDay = 7 - 6 = 1` (Sunday), which is what we need to index the array
*/
const weekDay = (day + Math.floor((month + 1) * 2.6) + yearDigits + Math.floor(yearDigits / 4) + Math.floor(century / 4) + 5 * century) % 7
return daysNameArr[weekDay] // name of the weekday
}
// Example : DateToDay("18/12/2020") => Friday

View File

@ -1,8 +1,8 @@
import { DateToDay } from '../DateToDay'
test('The date 18/02/2001 is Monday', () => {
test('The date 18/02/2001 is Sunday', () => {
const res = DateToDay('18/02/2001')
expect(res).toBe('Monday')
expect(res).toBe('Sunday')
})
test('The date 18/12/2020 is Friday', () => {
@ -14,7 +14,22 @@ test('The date 12/12/2012 is Wednesday', () => {
const res = DateToDay('12/12/2012')
expect(res).toBe('Wednesday')
})
test('The date 01/01/2001 is Friday', () => {
test('The date 01/01/2001 is Monday', () => {
const res = DateToDay('01/01/2001')
expect(res).toBe('Friday')
expect(res).toBe('Monday')
})
test('The date 1/1/2020 is Wednesday', () => {
const res = DateToDay('1/1/2020')
expect(res).toBe('Wednesday')
})
test('The date 2/3/2014 is Sunday', () => {
const res = DateToDay('2/3/2014')
expect(res).toBe('Sunday')
})
test('The date 28/2/2017 is Tuesday', () => {
const res = DateToDay('28/2/2017')
expect(res).toBe('Tuesday')
})