Use JavaScript to Find the Week Day from a Date

In Brief
For a valid date‑only string in YYYY-MM-DD form, use getUTCDay() on the parsed Date and map 0 to Sunday through 6 to Saturday. The examples below accept Gregorian dates from year 0001 to 9999 and reject invalid inputs. The arithmetic version avoids Date altogether.
Whilst recently sitting in on a technical interview, our candidate was asked to write a JavaScript/TypeScript function that accepts a date and, by return, determines which day of the week that date falls (or fell) on.
Something like this:
getDayOfWeek('2024-11-01'); // => "Friday"
getDayOfWeek('2022-01-01'); // => "Saturday"In JavaScript, this is a fairly straightforward problem to solve as long as you are familiar with JavaScript's built‑in Date object, but what if that wasn't allowed, or that was an area of JavaScript that the candidate wasn't familiar with or didn't know how to use?
Fortunately, we're not that mean during interviews, but it did raise a question that I wanted to explore further...
A simple solution using Date
For these examples, I'm accepting date‑only strings in YYYY-MM-DD form, for valid Gregorian dates from year 0001 to 9999. An ISO date‑only string is parsed at midnight UTC, so getUTCDay() gives us a consistent weekday: 0 for Sunday through 6 for Saturday. We can use that number as an array index.
Here is the TypeScript version, including a check for invalid dates:
const getDayOfWeek = (dateString: string): string => {
const daysOfWeek = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
];
if (!/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(dateString) ||
dateString.startsWith('0000-')) {
throw new RangeError('Expected a date from 0001-01-01 to 9999-12-31');
}
const date = new Date(dateString);
if (Number.isNaN(date.getTime()) ||
date.toISOString().slice(0, 10) !== dateString) {
throw new RangeError('Invalid date');
}
return daysOfWeek[date.getUTCDay()];
};How It Works
- Check the input shape and reject invalid calendar dates, including dates which
Datewould otherwise normalise into the next month. getUTCDay()retrieves the UTC weekday as an integer from the parseddate.- We then use that integer as an index into the
daysOfWeekarray, returning the name of the day.
The format and calendar checks are deliberate. A string that produces a Date is not necessarily a valid input for this function: some out‑of‑range day values are normalised into the following month. Comparing the resulting ISO date with the input catches that too.
The UTC weekday is independent of the client's time zone. That is the behaviour we want for a date without a time, but it is easy to lose if we mix date‑only parsing with local‑time methods.
Time Zones and the Date() Solution
The distinction is worth explaining in an interview, because the same instant can fall on different local dates.
Date Parsing
Date parses different string forms differently. An ISO date‑only string such as 2024-11-01 represents midnight UTC. A date‑time string without an offset is interpreted in the local time zone; that is a different input from the date‑only strings accepted here.
Calling getDay() on new Date('2024-11-01') first uses the client's local time. West of UTC, that instant can still be Thursday 31 October. getUTCDay() reads Friday directly from the UTC date.
Daylight Saving Time (DST)
Daylight saving changes local offsets, so it matters when translating instants into local calendar dates. Our date‑only function does not make that translation: it parses and reads the weekday in UTC.
Using Universal Time (UTC) instead
That is why the example above already uses getUTCDay(). Switching just the getter would not make every possible input format safe; the explicit YYYY-MM-DD restriction matters as well.
If we use this approach, then we can ensure consistent results from our function, regardless of the user's local time zone. Being able to explain this to your interviewer should hopefully gain you a few extra points too!
Another Approach Using Arithmetic and Remainders
We can also count Gregorian calendar days from 1 January AD 1, a Monday when that calendar is extended backwards. The % remainder operator then gives a weekday index from the non‑negative day count. This is calendar arithmetic, without converting the date to a local time.
Here's what that might look like:
const getDayOfWeekManual = (dateString: string): string => {
const daysOfWeek = [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday',
];
if (!/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/.test(dateString)) {
throw new RangeError('Expected YYYY-MM-DD');
}
const [year, month, day] = dateString.split('-').map(Number);
const isLeapYear = (year: number): boolean =>
(year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
const daysInMonth = (month: number, year: number): number => {
const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
return month === 2 && isLeapYear(year) ? 29 : days[month - 1];
};
if (year < 1 || month < 1 || month > 12 ||
day < 1 || day > daysInMonth(month, year)) {
throw new RangeError('Invalid date');
}
const totalDays =
Array.from({ length: year - 1 }, (_, i) => i + 1).reduce(
(sum, y) => sum + (isLeapYear(y) ? 366 : 365),
0
) +
Array.from({ length: month - 1 }, (_, i) => i + 1).reduce(
(sum, m) => sum + daysInMonth(m, year),
0
) +
day;
const dayIndex = (totalDays - 1) % 7;
return daysOfWeek[dayIndex];
};How It Works
As you might expect, this has a few more moving parts than the first example, but it's still a relatively straightforward process:
- This array starts with Monday, the reference weekday, whereas the
Dateexample starts with Sunday. - Check the
YYYY-MM-DDshape, then split the input intoyear,monthandday. Reject dates outside the stated range or calendar rules. Check for Leap Years
via a helper function which determines whether a year is a leap year so that we can account for the extra day in February.Calculate Days in a Month
: another helper function which returns the number of days in a given month using an array of days per month, and adjusting for February if the year is a leap year.- Sum the days for all years before the input year (adding 366 for leap years, 365 otherwise).
- Add the days for all months before the input month in the current year, using
daysInMonth. - Add the days in the current month.
- The inclusive total counts the reference date as day
1. Subtract1, then use(totalDays - 1) % 7to obtain the index into the Monday‑first array.
This uses Gregorian leap‑year and month‑length rules throughout, including years before countries adopted that calendar. It counts calendar days, not elapsed 24‑hour periods, so local time zones and daylight saving do not enter the calculation.
However, as you can see, it's a much more complex implementation and requires careful handling of leap years and month lengths.
Wrapping Up
Both solutions are valid and have their own merits. In an interview scenario, using Date is exactly what I ‑ and my colleagues ‑ would expect, leveraging native JavaScript capabilities and doing 'enough' to show your understanding of the subject.
The modulo‑based approach showcases deeper algorithmic thinking and avoids potential pitfalls with time zone handling, although it's also much more complicated and ‑ probably ‑ totally unnecessary in a real‑world use case.
Key Takeaways
- For valid
YYYY-MM-DDdates, UTC parsing andgetUTCDay()avoid a client‑time‑zone shift. Validate the calendar date as well as the string's shape. - A manual day count can give the same weekday without
Date, but needs the same explicit date range and Gregorian calendar rules.
In this case, it boils down to simplicity vs. finite control.