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