Skip to content

Commit d94929e

Browse files
authored
fix: DateToDay (#1125)
1 parent e32fdce commit d94929e

File tree

2 files changed

+52
-39
lines changed

2 files changed

+52
-39
lines changed

Conversions/DateToDay.js

+33-35
Original file line numberDiff line numberDiff line change
@@ -9,54 +9,52 @@
99
algorithm shown below gives us the number of the day and
1010
finally converts it to the name of the day.
1111
12-
Algorithm & Explanation : https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html
12+
Algorithm & Explanation : https://en.wikipedia.org/wiki/Zeller%27s_congruence
1313
*/
1414

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']
4117

4218
const DateToDay = (date) => {
4319
// firstly, check that input is a string or not.
4420
if (typeof date !== 'string') {
4521
return new TypeError('Argument is not a string.')
4622
}
4723
// 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))
4925
// 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) {
5127
return new TypeError('Date is not valid.')
5228
}
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
5541
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
6058
}
6159

6260
// Example : DateToDay("18/12/2020") => Friday

Conversions/test/DateToDay.test.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { DateToDay } from '../DateToDay'
22

3-
test('The date 18/02/2001 is Monday', () => {
3+
test('The date 18/02/2001 is Sunday', () => {
44
const res = DateToDay('18/02/2001')
5-
expect(res).toBe('Monday')
5+
expect(res).toBe('Sunday')
66
})
77

88
test('The date 18/12/2020 is Friday', () => {
@@ -14,7 +14,22 @@ test('The date 12/12/2012 is Wednesday', () => {
1414
const res = DateToDay('12/12/2012')
1515
expect(res).toBe('Wednesday')
1616
})
17-
test('The date 01/01/2001 is Friday', () => {
17+
test('The date 01/01/2001 is Monday', () => {
1818
const res = DateToDay('01/01/2001')
19-
expect(res).toBe('Friday')
19+
expect(res).toBe('Monday')
20+
})
21+
22+
test('The date 1/1/2020 is Wednesday', () => {
23+
const res = DateToDay('1/1/2020')
24+
expect(res).toBe('Wednesday')
25+
})
26+
27+
test('The date 2/3/2014 is Sunday', () => {
28+
const res = DateToDay('2/3/2014')
29+
expect(res).toBe('Sunday')
30+
})
31+
32+
test('The date 28/2/2017 is Tuesday', () => {
33+
const res = DateToDay('28/2/2017')
34+
expect(res).toBe('Tuesday')
2035
})

0 commit comments

Comments
 (0)