Algorithm Friendly Date Ranges - thelastmile/FreeCodeCamp GitHub Wiki
Algorithm Friendly Date Ranges
:triangular_flag_on_post: Remember to use Read-Search-Ask
if you get stuck. Try to pair program :busts_in_silhouette: and write your own code :pencil:
:checkered_flag: Problem Explanation:
Create a program that will take two dates and convert them into a more easy to understand date such as January 1st, 2017
. It will also check the difference between them, and handles cases with no difference, more than a day, more than a month, more than a year, and more than a month and less than a year respectively.
Relevant Links
:speech_balloon: Hint: 1
Split the string into an array where you get "YYYY", "MM", "DD".
try to solve the problem now
:speech_balloon: Hint: 2
You need to handle the case for "st", "nd", and "th". Note that 13 is "th" not "rd".
try to solve the problem now
:speech_balloon: Hint: 3
If you are using Date()
to create instances of dates to work with, then use UTC time to avoid errors due to time zone difference between servers.
try to solve the problem now
Spoiler Alert!
Solution ahead!
:beginner: Basic Code Solution:
function makeFriendlyDates(str) {
var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
// Convert a YYYY-MM-DD string into a date object.
function convertDate(str) {
// Split the dates to work independently.
var dateStr = str.split('-');
// Force the dates into Universal time to avoid issues due to timezones.
return (new Date(Date.UTC(dateStr[0], dateStr[1] - 1, dateStr[2])));
}
// Handles the case of the day's endings.
function dateEnding(val) {
switch (val) {
case 1:
case 21:
case 31:
return val + 'st';
case 2:
case 22:
return val + 'nd';
case 3:
case 23:
return val + 'rd';
default:
return val + 'th';
}
}
// Checks for the real difference in months to avoid errors
function monthDiff(date1, date2) {
var month2 = date2.getUTCFullYear() * 12 + date2.getUTCMonth();
var month1 = date1.getUTCFullYear() * 12 + date1.getUTCMonth();
return month2 - month1;
}
//day diff
function dayDiff(date1, date2) {
if(date2.getUTCMonth() === date1.getUTCMonth()){
return date1.getUTCDate()-date2.getUTCDate();
}
return 0;
}
// Get's the right month string.
function getMonth(date) {
return months[date.getUTCMonth()];
}
function displayDate() {
// Handles same day
if (date2.getTime() - date1.getTime() === 0) {
return [getMonth(date1) + ' ' + dateEnding(date1.getUTCDate()) + ', ' + date1.getUTCFullYear()];
}
// Handles same month
if (date1.getUTCMonth() === date2.getUTCMonth() && date1.getUTCFullYear() === date2.getUTCFullYear()) {
return [getMonth(date1) + ' ' + dateEnding(date1.getUTCDate()), dateEnding(date2.getUTCDate())];
}
// Handles more than a month of difference, but less than 12 months and different year
if (monthDiff(date1, date2) < 12 && date1.getUTCFullYear() !== date2.getUTCFullYear() ) {
return [getMonth(date1) + ' ' + dateEnding(date1.getUTCDate()), getMonth(date2) + ' ' + dateEnding(date2.getUTCDate())];
}
// Handles same month but different year
if (monthDiff(date1, date2) <= 12 && dayDiff(date1, date2)>0) {
return [getMonth(date1) + ' ' + dateEnding(date1.getUTCDate())+', '+date1.getUTCFullYear(), getMonth(date2) + ' ' + dateEnding(date2.getUTCDate())];
}
// Handles more than a month of difference, but less than 12 months and same year
if (monthDiff(date1, date2) < 12) {
return [getMonth(date1) + ' ' + dateEnding(date1.getUTCDate())+', '+date1.getUTCFullYear(), getMonth(date2) + ' ' + dateEnding(date2.getUTCDate())];
}
// Handles cases with more than 12 months apart.
return [getMonth(date1) + ' ' + dateEnding(date1.getUTCDate()) + ', ' + date1.getUTCFullYear(), getMonth(date2) + ' ' + dateEnding(date2.getUTCDate()) + ', ' + date2.getUTCFullYear()];
}
var date1 = convertDate(str[0]);
var date2 = convertDate(str[1]);
return displayDate();
}
// test here
makeFriendlyDates(['2016-07-01', '2016-07-04']);
:rocket: Run Code
Code Explanation:
- The function
convertDate()
converts a string in the format YYYY-MM-DD to a date object.split()
the dates on - to work independently.- Force the dates into universal time to avoid timezone issues.
- The function
dateEnding()
handles day's ending i.e., appending st, nd, rd or th. - The function
monthDiff()
checks the real difference in month to avoid errors. - The function
dayDiff()
checks the real difference in day to avoid errors. - The function
getMonth()
returns month string for particular date. - The function
displayDate()
displays the date correctly. Following provisions are made:- Handles same day.
- Handles same month.
- Handles more than a month of difference, but less than 12 months and different year.
- Handles same month but different year.
- Handles more than a month of difference, but less than 12 months and same year.
- Handles cases with more than 12 months apart.
Relevant Links
- JS String Prototype Split
- Date.UTC()
- Date.prototype.getUTCFullYear()
- Date.prototype.getUTCMonth()
- Date.prototype.getUTCDate()
- Date.prototype.getTime()
:trophy: Credits:
If you found this page useful, you may say thanks to the contributors by copying and pasting the following line in the main chat:
Thanks @Rafase282 @guyjoseph @dakshshah96 for your help with Algorithm: Friendly Date Ranges
:clipboard: NOTES FOR CONTRIBUTIONS:
- :warning: DO NOT add solutions that are similar to any existing solutions. If you think it is similar but better, then try to merge (or replace) the existing similar solution.
- Add an explanation of your solution.
- Categorize the solution in one of the following categories — Basic, Intermediate and Advanced. :traffic_light:
- Please add your username only if you have added any relevant main contents. (:warning: DO NOT remove any existing usernames)
See :point_right:
Wiki Challenge Solution Template
for reference.