javascript
exercises
exercises.js⚡javascript
/**
* 15.1 Date Fundamentals - Exercises
*
* Practice creating, manipulating, and working with JavaScript Date objects.
*/
/**
* Exercise 1: Date Creator
*
* Create a function that creates a Date from various input formats.
*
* @param {string|number|Date|object} input - Date input
* - string: ISO format or readable format
* - number: milliseconds since epoch
* - Date: clone the date
* - object: { year, month, day, hour?, minute?, second?, ms? }
* Note: month should be 1-12 (human-readable), not 0-11
* @returns {Date|null} - Date object or null if invalid
*/
function createDate(input) {
// Your code here
}
// console.log(createDate("2024-12-25"));
// console.log(createDate(1735084800000));
// console.log(createDate(new Date()));
// console.log(createDate({ year: 2024, month: 12, day: 25 }));
// console.log(createDate({ year: 2024, month: 12, day: 25, hour: 10, minute: 30 }));
// console.log(createDate("invalid")); // null
/**
* Exercise 2: Date Components
*
* Create a function that extracts all components from a date.
*
* @param {Date} date - The date to analyze
* @returns {object} - All date components
*/
function getDateComponents(date) {
// Your code here
// Return: {
// year, month (1-12), day, dayOfWeek (0-6),
// dayName, monthName, hour, minute, second, ms,
// timestamp, isLeapYear, daysInMonth, weekOfYear
// }
}
// console.log(getDateComponents(new Date("2024-12-25T10:30:45.123")));
// {
// year: 2024,
// month: 12,
// day: 25,
// dayOfWeek: 3,
// dayName: "Wednesday",
// monthName: "December",
// hour: 10,
// minute: 30,
// second: 45,
// ms: 123,
// timestamp: 1735123845123,
// isLeapYear: true,
// daysInMonth: 31,
// weekOfYear: 52
// }
/**
* Exercise 3: Date Validator
*
* Create a function that validates if a date is valid and within a range.
*
* @param {any} input - The value to validate
* @param {object} options - Validation options
* @returns {object} - { isValid, date, errors }
*/
function validateDate(input, options = {}) {
// Your code here
// Options can include:
// - minDate: Date - minimum allowed date
// - maxDate: Date - maximum allowed date
// - allowFuture: boolean - allow future dates
// - allowPast: boolean - allow past dates
}
// console.log(validateDate("2024-12-25"));
// { isValid: true, date: Date, errors: [] }
// console.log(validateDate("invalid"));
// { isValid: false, date: null, errors: ["Invalid date format"] }
// console.log(validateDate("2020-01-01", { allowPast: false }));
// { isValid: false, date: Date, errors: ["Date cannot be in the past"] }
/**
* Exercise 4: Day/Month Boundaries
*
* Create functions to get the start and end of various time periods.
*/
function startOf(date, unit) {
// Your code here
// unit: 'day', 'week', 'month', 'year'
}
function endOf(date, unit) {
// Your code here
// unit: 'day', 'week', 'month', 'year'
}
// const date = new Date("2024-06-15T14:30:00");
// console.log(startOf(date, 'day')); // 2024-06-15T00:00:00.000
// console.log(endOf(date, 'day')); // 2024-06-15T23:59:59.999
// console.log(startOf(date, 'week')); // 2024-06-09T00:00:00.000 (Sunday)
// console.log(startOf(date, 'month')); // 2024-06-01T00:00:00.000
// console.log(endOf(date, 'month')); // 2024-06-30T23:59:59.999
// console.log(startOf(date, 'year')); // 2024-01-01T00:00:00.000
// console.log(endOf(date, 'year')); // 2024-12-31T23:59:59.999
/**
* Exercise 5: Date Cloning and Modification
*
* Create a function that clones a date and applies modifications.
*
* @param {Date} date - The original date
* @param {object} changes - Changes to apply
* @returns {Date} - New date with changes applied
*/
function modifyDate(date, changes) {
// Your code here
// changes can include: year, month, day, hour, minute, second, ms
// Should not modify the original date
}
// const original = new Date("2024-06-15T10:30:00");
// console.log(modifyDate(original, { year: 2025 }));
// console.log(modifyDate(original, { month: 12, day: 25 }));
// console.log(modifyDate(original, { hour: 0, minute: 0, second: 0 }));
// console.log(original); // Should be unchanged
/**
* Exercise 6: Date Comparison Utilities
*
* Create functions for comparing dates.
*/
function isSameDay(date1, date2) {
// Your code here
}
function isSameMonth(date1, date2) {
// Your code here
}
function isSameYear(date1, date2) {
// Your code here
}
function isBefore(date1, date2) {
// Your code here
}
function isAfter(date1, date2) {
// Your code here
}
function isBetween(date, start, end, inclusive = true) {
// Your code here
}
// const d1 = new Date("2024-06-15");
// const d2 = new Date("2024-06-15");
// const d3 = new Date("2024-06-20");
// console.log(isSameDay(d1, d2)); // true
// console.log(isSameMonth(d1, d3)); // true
// console.log(isBefore(d1, d3)); // true
// console.log(isBetween(d1, new Date("2024-06-01"), new Date("2024-06-30"))); // true
/**
* Exercise 7: Week Number Calculator
*
* Create a function that calculates the ISO week number.
* ISO weeks start on Monday, and week 1 is the week containing January 4.
*
* @param {Date} date - The date
* @returns {object} - { week: number, year: number }
*/
function getISOWeek(date) {
// Your code here
}
// console.log(getISOWeek(new Date("2024-01-01"))); // { week: 1, year: 2024 }
// console.log(getISOWeek(new Date("2024-12-31"))); // { week: 1, year: 2025 }
// console.log(getISOWeek(new Date("2024-06-15"))); // { week: 24, year: 2024 }
/**
* Exercise 8: Leap Year and Days
*
* Create functions for leap year calculations.
*/
function isLeapYear(year) {
// Your code here
}
function getDaysInMonth(year, month) {
// month: 1-12
// Your code here
}
function getDaysInYear(year) {
// Your code here
}
function getDayOfYear(date) {
// Returns 1-366
// Your code here
}
// console.log(isLeapYear(2024)); // true
// console.log(isLeapYear(2023)); // false
// console.log(isLeapYear(2000)); // true
// console.log(isLeapYear(1900)); // false
// console.log(getDaysInMonth(2024, 2)); // 29 (leap year)
// console.log(getDaysInMonth(2023, 2)); // 28
// console.log(getDaysInYear(2024)); // 366
// console.log(getDayOfYear(new Date("2024-12-31"))); // 366
/**
* Exercise 9: Date Sorting
*
* Create a function that sorts an array of dates or objects with dates.
*
* @param {Array} items - Array of dates or objects
* @param {string} order - 'asc' or 'desc'
* @param {string} key - Property name if items are objects
* @returns {Array} - Sorted array (new array, doesn't modify original)
*/
function sortByDate(items, order = 'asc', key = null) {
// Your code here
}
// const dates = [
// new Date("2024-06-15"),
// new Date("2024-01-01"),
// new Date("2024-12-31")
// ];
// console.log(sortByDate(dates, 'asc'));
// console.log(sortByDate(dates, 'desc'));
// const events = [
// { name: "Event A", date: new Date("2024-06-15") },
// { name: "Event B", date: new Date("2024-01-01") },
// { name: "Event C", date: new Date("2024-12-31") }
// ];
// console.log(sortByDate(events, 'asc', 'date'));
/**
* Exercise 10: Timezone Utilities
*
* Create functions for working with timezones.
*/
function getTimezoneInfo() {
// Return info about current timezone
// Your code here
}
function toUTC(date) {
// Convert local date to UTC date string
// Your code here
}
function fromUTC(utcString) {
// Convert UTC string to local Date
// Your code here
}
function convertTimezone(date, fromOffset, toOffset) {
// Convert between timezone offsets (in hours)
// Your code here
}
// console.log(getTimezoneInfo());
// { name: "America/New_York", offset: -5, offsetMinutes: -300 }
// console.log(toUTC(new Date()));
// "2024-06-15T18:30:00.000Z"
// console.log(convertTimezone(new Date(), -5, +9)); // EST to JST
// ============================================
// SOLUTIONS
// ============================================
/*
// Solution 1
function createDate(input) {
if (input === null || input === undefined) {
return null;
}
let date;
if (input instanceof Date) {
date = new Date(input.getTime());
} else if (typeof input === 'number') {
date = new Date(input);
} else if (typeof input === 'string') {
date = new Date(input);
} else if (typeof input === 'object') {
const { year, month, day, hour = 0, minute = 0, second = 0, ms = 0 } = input;
// Convert month from 1-12 to 0-11
date = new Date(year, month - 1, day, hour, minute, second, ms);
} else {
return null;
}
return isNaN(date.getTime()) ? null : date;
}
// Solution 2
function getDateComponents(date) {
const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December'];
const year = date.getFullYear();
const month = date.getMonth() + 1;
// Check leap year
const isLeapYear = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
// Days in month
const daysInMonth = new Date(year, date.getMonth() + 1, 0).getDate();
// Week of year (simple calculation)
const startOfYear = new Date(year, 0, 1);
const daysSinceStart = Math.floor((date - startOfYear) / (1000 * 60 * 60 * 24));
const weekOfYear = Math.ceil((daysSinceStart + startOfYear.getDay() + 1) / 7);
return {
year,
month,
day: date.getDate(),
dayOfWeek: date.getDay(),
dayName: dayNames[date.getDay()],
monthName: monthNames[date.getMonth()],
hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds(),
ms: date.getMilliseconds(),
timestamp: date.getTime(),
isLeapYear,
daysInMonth,
weekOfYear
};
}
// Solution 3
function validateDate(input, options = {}) {
const errors = [];
let date = null;
// Try to create date
if (input instanceof Date) {
date = input;
} else {
date = new Date(input);
}
// Check if valid
if (isNaN(date.getTime())) {
return { isValid: false, date: null, errors: ['Invalid date format'] };
}
const now = new Date();
// Check minDate
if (options.minDate && date < options.minDate) {
errors.push(`Date cannot be before ${options.minDate.toDateString()}`);
}
// Check maxDate
if (options.maxDate && date > options.maxDate) {
errors.push(`Date cannot be after ${options.maxDate.toDateString()}`);
}
// Check allowFuture
if (options.allowFuture === false && date > now) {
errors.push('Date cannot be in the future');
}
// Check allowPast
if (options.allowPast === false && date < now) {
errors.push('Date cannot be in the past');
}
return {
isValid: errors.length === 0,
date,
errors
};
}
// Solution 4
function startOf(date, unit) {
const result = new Date(date);
switch (unit) {
case 'day':
result.setHours(0, 0, 0, 0);
break;
case 'week':
result.setHours(0, 0, 0, 0);
result.setDate(result.getDate() - result.getDay());
break;
case 'month':
result.setDate(1);
result.setHours(0, 0, 0, 0);
break;
case 'year':
result.setMonth(0, 1);
result.setHours(0, 0, 0, 0);
break;
}
return result;
}
function endOf(date, unit) {
const result = new Date(date);
switch (unit) {
case 'day':
result.setHours(23, 59, 59, 999);
break;
case 'week':
result.setDate(result.getDate() + (6 - result.getDay()));
result.setHours(23, 59, 59, 999);
break;
case 'month':
result.setMonth(result.getMonth() + 1, 0);
result.setHours(23, 59, 59, 999);
break;
case 'year':
result.setMonth(11, 31);
result.setHours(23, 59, 59, 999);
break;
}
return result;
}
// Solution 5
function modifyDate(date, changes) {
const result = new Date(date.getTime());
if (changes.year !== undefined) result.setFullYear(changes.year);
if (changes.month !== undefined) result.setMonth(changes.month - 1);
if (changes.day !== undefined) result.setDate(changes.day);
if (changes.hour !== undefined) result.setHours(changes.hour);
if (changes.minute !== undefined) result.setMinutes(changes.minute);
if (changes.second !== undefined) result.setSeconds(changes.second);
if (changes.ms !== undefined) result.setMilliseconds(changes.ms);
return result;
}
// Solution 6
function isSameDay(date1, date2) {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate();
}
function isSameMonth(date1, date2) {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth();
}
function isSameYear(date1, date2) {
return date1.getFullYear() === date2.getFullYear();
}
function isBefore(date1, date2) {
return date1.getTime() < date2.getTime();
}
function isAfter(date1, date2) {
return date1.getTime() > date2.getTime();
}
function isBetween(date, start, end, inclusive = true) {
const time = date.getTime();
const startTime = start.getTime();
const endTime = end.getTime();
if (inclusive) {
return time >= startTime && time <= endTime;
}
return time > startTime && time < endTime;
}
// Solution 7
function getISOWeek(date) {
const d = new Date(date);
d.setHours(0, 0, 0, 0);
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
const yearStart = new Date(d.getFullYear(), 0, 1);
const weekNumber = Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
return { week: weekNumber, year: d.getFullYear() };
}
// Solution 8
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
function getDaysInMonth(year, month) {
return new Date(year, month, 0).getDate();
}
function getDaysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
function getDayOfYear(date) {
const start = new Date(date.getFullYear(), 0, 0);
const diff = date - start;
const oneDay = 1000 * 60 * 60 * 24;
return Math.floor(diff / oneDay);
}
// Solution 9
function sortByDate(items, order = 'asc', key = null) {
const sorted = [...items].sort((a, b) => {
const dateA = key ? a[key] : a;
const dateB = key ? b[key] : b;
return dateA.getTime() - dateB.getTime();
});
return order === 'desc' ? sorted.reverse() : sorted;
}
// Solution 10
function getTimezoneInfo() {
const offset = new Date().getTimezoneOffset();
const offsetHours = -offset / 60;
// Try to get timezone name
let name;
try {
name = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch {
name = 'Unknown';
}
return {
name,
offset: offsetHours,
offsetMinutes: -offset
};
}
function toUTC(date) {
return date.toISOString();
}
function fromUTC(utcString) {
return new Date(utcString);
}
function convertTimezone(date, fromOffset, toOffset) {
const utc = date.getTime() + (fromOffset * 60 * 60 * 1000);
return new Date(utc - (toOffset * 60 * 60 * 1000));
}
*/