Skip to content

fix: DateToDay #1125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 33 additions & 35 deletions Conversions/DateToDay.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,52 @@
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.
if (typeof date !== 'string') {
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
Expand Down
23 changes: 19 additions & 4 deletions Conversions/test/DateToDay.test.js
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand All @@ -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')
})