2758. Next Day 🔒
Problem Description
The problem asks you to extend the JavaScript Date
object by adding a new method called nextDay()
. This method should be available on any date object and when called, it should return a string representing the next day's date in the format YYYY-MM-DD
.
For example, if you have a date object representing "2014-06-20"
and you call nextDay()
on it, the method should return "2014-06-21"
as a string. The method needs to handle all cases including month boundaries (like going from June 30th to July 1st) and year boundaries (like going from December 31st to January 1st of the next year).
The implementation works by:
- Creating a new
Date
object from the current date's value to avoid modifying the original date - Adding 1 day to this new date using
setDate(getDate() + 1)
, which automatically handles month and year rollovers - Converting the resulting date to ISO string format using
toISOString()
which gives a format like"2014-06-21T00:00:00.000Z"
- Extracting just the date portion (first 10 characters) using
slice(0, 10)
to get"YYYY-MM-DD"
The solution uses TypeScript's global declaration to properly type the new method being added to the Date
prototype, ensuring type safety when using this enhanced functionality.
Intuition
When we need to add functionality to all instances of an existing JavaScript object type, the natural approach is to extend its prototype. Since we want every Date
object to have a nextDay()
method, we add this method to Date.prototype
.
The key insight is that JavaScript's Date
object already has built-in intelligence for handling date arithmetic. When we use setDate()
with a value that exceeds the current month's days, it automatically rolls over to the next month. For example, if we're on June 30th and add 1 day using setDate(31)
, JavaScript knows June only has 30 days and automatically advances to July 1st. Similarly, it handles year transitions seamlessly.
To preserve the original date object (following good practice of not mutating input), we create a copy using new Date(this.valueOf())
. The valueOf()
method returns the timestamp, ensuring we get an exact copy of the date.
For formatting, we leverage the toISOString()
method which always returns dates in a consistent format: "YYYY-MM-DDTHH:mm:ss.sssZ"
. Since we only need the date portion (YYYY-MM-DD
), we can simply take the first 10 characters using slice(0, 10)
. This is more elegant and reliable than manually constructing the string with getFullYear()
, getMonth()
, and getDate()
, especially since we'd need to handle zero-padding for single-digit months and days.
The TypeScript declaration at the beginning ensures type safety by informing the compiler that we're intentionally adding a new method to the Date
interface, preventing type errors when using the enhanced functionality.
Solution Approach
The implementation extends the native Date
prototype to add the nextDay()
method. Here's a step-by-step breakdown:
1. TypeScript Declaration
declare global {
interface Date {
nextDay(): string;
}
}
This declaration tells TypeScript that we're adding a new method to the Date
interface globally, preventing type errors when calling nextDay()
on date objects.
2. Prototype Extension
Date.prototype.nextDay = function () {
// Implementation here
}
By adding the method to Date.prototype
, every Date
instance automatically inherits this method.
3. Creating a Copy
const date = new Date(this.valueOf());
this.valueOf()
returns the primitive value (timestamp in milliseconds) of the current date object- Creating a new
Date
object from this timestamp ensures we don't modify the original date - This follows the principle of immutability
4. Adding One Day
date.setDate(date.getDate() + 1);
getDate()
returns the day of the month (1-31)- Adding 1 to this value and passing it to
setDate()
advances the date by one day - JavaScript's
Date
object automatically handles edge cases:- Month boundaries:
setDate(32)
in January becomes February 1st - Year boundaries: December 31st + 1 day becomes January 1st of the next year
- Leap years: February 28th/29th transitions are handled correctly
- Month boundaries:
5. Formatting the Output
return date.toISOString().slice(0, 10);
toISOString()
returns a string in ISO 8601 format:"YYYY-MM-DDTHH:mm:ss.sssZ"
slice(0, 10)
extracts the first 10 characters, giving us exactly"YYYY-MM-DD"
- This approach guarantees correct formatting with zero-padding for single-digit months and days
The entire solution leverages JavaScript's built-in date handling capabilities rather than manually calculating days, months, and years, making it both concise and robust.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with a concrete example to see how it handles different scenarios:
Example 1: Regular Day Transition
const date1 = new Date('2014-06-20');
console.log(date1.nextDay()); // "2014-06-21"
Step-by-step execution:
- Start with date object representing June 20, 2014
this.valueOf()
returns the timestamp (e.g., 1403222400000)- Create new date:
new Date(1403222400000)
getDate()
returns 20, sosetDate(20 + 1)
sets day to 21toISOString()
produces"2014-06-21T00:00:00.000Z"
slice(0, 10)
extracts"2014-06-21"
Example 2: Month Boundary
const date2 = new Date('2014-06-30');
console.log(date2.nextDay()); // "2014-07-01"
Step-by-step execution:
- Start with June 30, 2014 (last day of June)
- Create copy of the date
getDate()
returns 30, sosetDate(30 + 1)
attempts to set day to 31- JavaScript knows June has only 30 days, automatically rolls to July 1st
toISOString()
produces"2014-07-01T00:00:00.000Z"
slice(0, 10)
extracts"2014-07-01"
Example 3: Year Boundary
const date3 = new Date('2014-12-31');
console.log(date3.nextDay()); // "2015-01-01"
Step-by-step execution:
- Start with December 31, 2014 (last day of year)
- Create copy of the date
getDate()
returns 31, sosetDate(31 + 1)
attempts to set day to 32- JavaScript knows December has only 31 days, automatically rolls to January 1st of 2015
toISOString()
produces"2015-01-01T00:00:00.000Z"
slice(0, 10)
extracts"2015-01-01"
The beauty of this solution is that we don't need to write any special logic for these edge cases - JavaScript's Date
object handles all the complex date arithmetic automatically when we use setDate()
with values beyond the valid range for the current month.
Solution Implementation
1from datetime import datetime, timedelta
2
3class ExtendedDate(datetime):
4 """Extended datetime class with additional nextDay method"""
5
6 def nextDay(self):
7 """
8 Returns the next day's date as a string in YYYY-MM-DD format
9
10 Returns:
11 str: The next day's date in YYYY-MM-DD format
12 """
13 # Create a new date by adding one day to the current date
14 # timedelta(days=1) represents a one-day duration
15 next_date = self + timedelta(days=1)
16
17 # Convert to string format YYYY-MM-DD
18 # strftime formats the datetime object according to the specified format
19 return next_date.strftime('%Y-%m-%d')
20
21
22# Alternative approach using monkey patching to extend the built-in datetime class
23def add_next_day_to_datetime():
24 """
25 Adds nextDay method to the datetime class
26 This approach modifies the built-in datetime class directly
27 """
28 def next_day(self):
29 """
30 Returns the next day's date as a string in YYYY-MM-DD format
31
32 Returns:
33 str: The next day's date in YYYY-MM-DD format
34 """
35 # Create a new datetime object by adding one day
36 next_date = self + timedelta(days=1)
37
38 # Format and return as YYYY-MM-DD string
39 return next_date.strftime('%Y-%m-%d')
40
41 # Attach the method to datetime class
42 datetime.nextDay = next_day
43
44
45# Example usage:
46# Using ExtendedDate class
47# date = ExtendedDate(2014, 6, 20)
48# date.nextDay() # Returns "2014-06-21"
49
50# Using monkey patching approach
51# add_next_day_to_datetime()
52# date = datetime(2014, 6, 20)
53# date.nextDay() # Returns "2014-06-21"
54
1import java.time.LocalDate;
2import java.time.format.DateTimeFormatter;
3
4/**
5 * Custom Date class that extends functionality to include nextDay method
6 * This class wraps LocalDate to provide similar functionality to the TypeScript Date extension
7 */
8public class CustomDate {
9 // The internal date representation
10 private LocalDate date;
11
12 // Date formatter for YYYY-MM-DD format
13 private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
14
15 /**
16 * Constructor that creates a CustomDate from a date string
17 * @param dateString Date string in YYYY-MM-DD format
18 */
19 public CustomDate(String dateString) {
20 this.date = LocalDate.parse(dateString, DATE_FORMATTER);
21 }
22
23 /**
24 * Constructor that creates a CustomDate from a LocalDate object
25 * @param date LocalDate object
26 */
27 public CustomDate(LocalDate date) {
28 this.date = date;
29 }
30
31 /**
32 * Returns the next day's date as a string in YYYY-MM-DD format
33 * This method does not modify the original date
34 * @return String representation of the next day in YYYY-MM-DD format
35 */
36 public String nextDay() {
37 // Create a new LocalDate object incremented by one day
38 // This prevents modifying the original date
39 LocalDate nextDate = this.date.plusDays(1);
40
41 // Format and return the date as YYYY-MM-DD string
42 return nextDate.format(DATE_FORMATTER);
43 }
44
45 /**
46 * Get the internal LocalDate value
47 * @return The LocalDate object
48 */
49 public LocalDate valueOf() {
50 return this.date;
51 }
52
53 // Example usage demonstration
54 public static void main(String[] args) {
55 // Create a new CustomDate instance
56 CustomDate date = new CustomDate("2014-06-20");
57
58 // Get the next day's date
59 System.out.println(date.nextDay()); // Output: "2014-06-21"
60 }
61}
62
1#include <iostream>
2#include <iomanip>
3#include <sstream>
4#include <ctime>
5#include <string>
6
7class Date {
8private:
9 std::tm timeinfo;
10
11public:
12 // Constructor that parses a date string in "YYYY-MM-DD" format
13 Date(const std::string& dateStr) {
14 // Initialize the tm structure to zero
15 std::memset(&timeinfo, 0, sizeof(timeinfo));
16
17 // Parse the date string
18 int year, month, day;
19 char dash1, dash2;
20 std::istringstream iss(dateStr);
21 iss >> year >> dash1 >> month >> dash2 >> day;
22
23 // Set the date components (tm_year is years since 1900, tm_mon is 0-based)
24 timeinfo.tm_year = year - 1900;
25 timeinfo.tm_mon = month - 1;
26 timeinfo.tm_mday = day;
27
28 // Normalize the time structure
29 std::mktime(&timeinfo);
30 }
31
32 // Constructor from tm structure
33 Date(const std::tm& tm) : timeinfo(tm) {
34 // Normalize the time structure
35 std::mktime(&timeinfo);
36 }
37
38 // Method to get the next day's date as a string in YYYY-MM-DD format
39 std::string nextDay() const {
40 // Create a copy of the current date's tm structure
41 // This prevents modifying the original date
42 std::tm nextDateTm = timeinfo;
43
44 // Increment the date by one day
45 nextDateTm.tm_mday += 1;
46
47 // Normalize the date (handles month/year rollover automatically)
48 std::mktime(&nextDateTm);
49
50 // Format the date as YYYY-MM-DD string
51 std::ostringstream oss;
52 oss << std::setfill('0')
53 << std::setw(4) << (nextDateTm.tm_year + 1900) << "-"
54 << std::setw(2) << (nextDateTm.tm_mon + 1) << "-"
55 << std::setw(2) << nextDateTm.tm_mday;
56
57 return oss.str();
58 }
59
60 // Helper method to convert current date to string (for debugging/display)
61 std::string toString() const {
62 std::ostringstream oss;
63 oss << std::setfill('0')
64 << std::setw(4) << (timeinfo.tm_year + 1900) << "-"
65 << std::setw(2) << (timeinfo.tm_mon + 1) << "-"
66 << std::setw(2) << timeinfo.tm_mday;
67
68 return oss.str();
69 }
70};
71
72// Example usage:
73int main() {
74 // Create a Date object from string
75 Date date("2014-06-20");
76
77 // Get the next day
78 std::string nextDayStr = date.nextDay();
79
80 // Output: "2014-06-21"
81 std::cout << nextDayStr << std::endl;
82
83 return 0;
84}
85
1// Extend the global Date interface to include the nextDay method
2declare global {
3 interface Date {
4 nextDay(): string;
5 }
6}
7
8// Add nextDay method to Date prototype
9// This method returns the next day's date as a string in YYYY-MM-DD format
10Date.prototype.nextDay = function(): string {
11 // Create a new Date object from the current date's value
12 // This prevents modifying the original date
13 const nextDate: Date = new Date(this.valueOf());
14
15 // Increment the date by one day
16 nextDate.setDate(nextDate.getDate() + 1);
17
18 // Convert to ISO string format and extract only the date portion (YYYY-MM-DD)
19 // toISOString() returns format: "YYYY-MM-DDTHH:mm:ss.sssZ"
20 // slice(0, 10) extracts the first 10 characters: "YYYY-MM-DD"
21 return nextDate.toISOString().slice(0, 10);
22};
23
24// Example usage:
25// const date = new Date("2014-06-20");
26// date.nextDay(); // Returns "2014-06-21"
27
28// Export an empty object to make this a module
29export {};
30
Time and Space Complexity
Time Complexity: O(1)
The nextDay
method performs a constant number of operations:
new Date(this.valueOf())
- creates a new Date object inO(1)
timedate.setDate(date.getDate() + 1)
- getting and setting the date are bothO(1)
operationsdate.toISOString()
- converts the date to ISO string format inO(1)
timeslice(0, 10)
- extracts the first 10 characters (YYYY-MM-DD) inO(1)
time
All operations execute in constant time regardless of the input date value.
Space Complexity: O(1)
The method allocates a fixed amount of memory:
- One new
Date
object is created - One string is generated from
toISOString()
- One substring is created from
slice(0, 10)
The space used does not scale with any input size and remains constant.
Common Pitfalls
1. Timezone Issues with ISO String Conversion
The JavaScript implementation uses toISOString()
which always returns UTC time. If the original date is in local time near midnight, the conversion to UTC might shift the date backward or forward by a day.
Example Problem:
// If you're in UTC-5 timezone and create a date for midnight local time
const date = new Date('2014-06-20'); // Interpreted as midnight local time
console.log(date.nextDay()); // Might return "2014-06-20" instead of "2014-06-21"
Solution: Use local date methods instead of ISO string:
Date.prototype.nextDay = function() {
const date = new Date(this.valueOf());
date.setDate(date.getDate() + 1);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
2. Mutating the Original Date Object
Forgetting to create a copy of the date before modification will mutate the original date object, causing unexpected side effects.
Example Problem:
Date.prototype.nextDay = function() {
this.setDate(this.getDate() + 1); // WRONG: Modifies original date
return this.toISOString().slice(0, 10);
}
const today = new Date('2014-06-20');
const tomorrow = today.nextDay();
console.log(today); // Date has been changed to 2014-06-21!
Solution: Always create a new Date instance as shown in the correct implementation.
3. Python: Losing Time Information
In the Python implementation, if you need to preserve time information while getting the next day, the current implementation only returns the date string without time.
Example Problem:
date = ExtendedDate(2014, 6, 20, 15, 30, 45) # 3:30:45 PM
next = date.nextDay() # Returns "2014-06-21" without time
Solution: Provide an option to return the full datetime object or include time in the string:
def nextDay(self, include_time=False):
next_date = self + timedelta(days=1)
if include_time:
return next_date.strftime('%Y-%m-%d %H:%M:%S')
return next_date.strftime('%Y-%m-%d')
4. Edge Case: Daylight Saving Time Transitions
During DST transitions, a "day" might be 23 or 25 hours. Using setDate()
handles this correctly, but manual hour-based calculations would fail.
Example Problem:
// WRONG approach using hours
Date.prototype.nextDay = function() {
const date = new Date(this.getTime() + 24 * 60 * 60 * 1000); // Add 24 hours
return date.toISOString().slice(0, 10);
}
Solution:
Stick with setDate()
method which properly handles DST transitions by working with calendar days rather than fixed time periods.
What does the following code do?
1def f(arr1, arr2):
2 i, j = 0, 0
3 new_arr = []
4 while i < len(arr1) and j < len(arr2):
5 if arr1[i] < arr2[j]:
6 new_arr.append(arr1[i])
7 i += 1
8 else:
9 new_arr.append(arr2[j])
10 j += 1
11 new_arr.extend(arr1[i:])
12 new_arr.extend(arr2[j:])
13 return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2 int i = 0, j = 0;
3 List<Integer> newArr = new ArrayList<>();
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.add(arr1[i]);
8 i++;
9 } else {
10 newArr.add(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.add(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.add(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
1function f(arr1, arr2) {
2 let i = 0, j = 0;
3 let newArr = [];
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.push(arr1[i]);
8 i++;
9 } else {
10 newArr.push(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.push(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.push(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!