Add Months to a Date

Problem

Read a valid date (day month year) and an integer k (can be negative). Move the date by k months. If the new month has fewer days than the day of the month, use the last day of the new month instead (31 Jan + 1 month = 29 Feb in a leap year). Print the new date as: day month year. The result year stays between 1 and 9999.

Constraints

  • The date is valid
  • -1200 <= k <= 1200

Examples

Input

31 1 2024 1

Output

29 2 2024

Solutions

Best approachTime O(1)Space O(1)

Months have different lengths, so adding months is not the same as adding 30 days. Counting months from year 0 turns the problem into one addition; floor division brings back the year and month. Java's LocalDate.plusMonths uses the same clamping rule.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process a date.
 * Input   : One line of text.
 * Output  : The new date.
 * Approach: day month year k.
 * Time    : O(1)
 * Space   : O(1)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static String solve(String s) {
        // Step 1: Read day, month, year and the number of months to add.
        String[] part = s.trim().split("\\s+");
        int day = Integer.parseInt(part[0]);
        int month = Integer.parseInt(part[1]);
        int year = Integer.parseInt(part[2]);
        int shift = Integer.parseInt(part[3]);
        // Step 2: Count months from year 0. Then the shift is a plain addition. floorDiv works for negative values.
        int total = year * 12 + (month - 1) + shift;
        int newYear = Math.floorDiv(total, 12);
        int newMonth = Math.floorMod(total, 12) + 1;
        // Step 3: Find the length of the new month. February has 29 days in a leap year.
        boolean leap = (newYear % 4 == 0 && newYear % 100 != 0) || newYear % 400 == 0;
        int[] days = {31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        // Step 4: Clamp the day to the length of the new month.
        return Math.min(day, days[newMonth - 1]) + " " + newMonth + " " + newYear;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.hasNextLine() ? scanner.nextLine() : "";
        System.out.println(solve(s));
    }
}
Hints (1)
  1. Why is 31 Jan + 1 month not 31 Feb?