Build a calculator that finds the date some days after or before a base date.
The first line gives the base date in the form YYYY-MM-DD.
The second line gives the number of queries n, and each of the next n lines gives one integer k.
A positive k means k days after the base date, a negative k means |k| days before it, and 0 means the base date itself.
The calendar is the Gregorian calendar in use today, and no date before the year 1582 appears.
January, March, May, July, August, October and December have 31 days, April, June, September and November have 30, and February has 28, except 29 in a leap year.
A year is a leap year if it is divisible by 4 but not by 100, or if it is divisible by 400.
So 2000 is a leap year, but 1900 and 2100 are not.
For each query, in input order, print the answer date on its own line in the form YYYY-MM-DD (four digits for the year, two for month and day).
Input
1900-01-01 ≤ base date ≤ 2100-12-31 (a real calendar date), 1 ≤ n ≤ 1,000, -100,000 ≤ k ≤ 100,000
When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).
$ Ready
Open this on a computer to write and run code. On mobile you can read the problem and the solutions.
In other languagesShow solutions by language · 8 languages
Turn a date into one number, "the day count from January 1, 1600"; then k days later is a single addition of k to that number, and you turn it back into a date. The first trap is the addition itself. A line you read is a string, so in JS, TS and Craykon number + "1" is not addition but concatenation ("1540001"). In Java and C#, + also concatenates when one side is a String, and in Python int + str stops with a TypeError. C and C++ read integers from the start with scanf and cin, so they do not have this problem. So convert first: JS/TS Number(line), Craykon ToNumber(), Java Integer.parseInt, C# int.Parse, Python int. The second trap is the leap-year condition: (y % 4 == 0 && y % 100 != 0) || y % 400 == 0 in seven languages, and and / or in Python. && binds tighter than || in all eight languages, so it means the same without the parentheses, but gcc with -Wall warns you to add them. If you write only "a leap year every 4 years", the day after 1900-02-28 becomes 1900-02-29. The third trap is the comparison when you carry the remaining days. If the remaining days equal the number of days in that year exactly, the date is January 1 of the next year, so ask with >=; with > you get dates such as December 32. You can also use a library: Python date + timedelta(days=k), Java LocalDate.plusDays, C# DateTime.AddDays, C++20 std::chrono::sys_days. Be careful with JS Date: new Date("2024-02-28") is read as midnight UTC but getDate() uses local time, so places behind UTC (such as the US) get the day before, and adding 86,400,000 ms at a time in local time fails to move to the next date on the day daylight saving time ends (a 25-hour day). So calculate only in UTC, with getUTCDate and setUTCDate. C and Craykon have no date library, so count by hand (C's mktime is local time too).
Pythonmain.py · 45 lines
BASE = 1600 # 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374)MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]def is_leap(y): # 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년 return (y % 4 == 0 and y % 100 != 0) or y % 400 == 0def year_days(y): return 366 if is_leap(y) else 365def month_days(y, m): return 29 if m == 2 and is_leap(y) else MONTH_DAYS[m - 1]def to_count(y, m, d): total = d - 1 for yy in range(BASE, y): total += year_days(yy) for mm in range(1, m): total += month_days(y, mm) return totaldef from_count(c): y = BASE while c >= year_days(y): # 남은 날이 그해 날 수와 같으면 다음 해 1월 1일이다 c -= year_days(y) y += 1 m = 1 while c >= month_days(y, m): c -= month_days(y, m) m += 1 return y, m, c + 1y, m, d = map(int, input().strip().split("-"))start = to_count(y, m, d)n = int(input())for _ in range(n): k = int(input()) # 수로 바꾼 다음에 더한다 ry, rm, rd = from_count(start + k) print(f"{ry:04d}-{rm:02d}-{rd:02d}")
JavaScriptmain.js · 36 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const BASE = 1600; // 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374)const MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];// 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년const isLeap = (y) => (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0;const yearDays = (y) => (isLeap(y) ? 366 : 365);const monthDays = (y, m) => (m === 2 && isLeap(y) ? 29 : MONTH_DAYS[m - 1]);const toCount = (y, m, d) => { let total = d - 1; for (let yy = BASE; yy < y; yy++) total += yearDays(yy); for (let mm = 1; mm < m; mm++) total += monthDays(y, mm); return total;};const fromCount = (c) => { let y = BASE; while (c >= yearDays(y)) { // 남은 날이 그해 날 수와 같으면 다음 해 1월 1일이다 c -= yearDays(y); y++; } let m = 1; while (c >= monthDays(y, m)) { c -= monthDays(y, m); m++; } return `${String(y).padStart(4, "0")}-${String(m).padStart(2, "0")}-${String(c + 1).padStart(2, "0")}`;};const [y, m, d] = lines[0].trim().split("-").map(Number);const start = toCount(y, m, d);const n = Number(lines[1]);const out = [];for (let i = 0; i < n; i++) { const k = Number(lines[2 + i]); // 문자열 그대로 +하면 이어 붙이기가 된다 → 수로 바꾼 다음에 더한다 out.push(fromCount(start + k));}console.log(out.join("\n"));
TypeScriptmain.ts · 37 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const BASE = 1600; // 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374)const MONTH_DAYS: number[] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];// 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년const isLeap = (y: number): boolean => (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0;const yearDays = (y: number): number => (isLeap(y) ? 366 : 365);const monthDays = (y: number, m: number): number => (m === 2 && isLeap(y) ? 29 : MONTH_DAYS[m - 1]);const toCount = (y: number, m: number, d: number): number => { let total = d - 1; for (let yy = BASE; yy < y; yy++) total += yearDays(yy); for (let mm = 1; mm < m; mm++) total += monthDays(y, mm); return total;};const fromCount = (c: number): string => { let y = BASE; while (c >= yearDays(y)) { // 남은 날이 그해 날 수와 같으면 다음 해 1월 1일이다 c -= yearDays(y); y++; } let m = 1; while (c >= monthDays(y, m)) { c -= monthDays(y, m); m++; } return `${String(y).padStart(4, "0")}-${String(m).padStart(2, "0")}-${String(c + 1).padStart(2, "0")}`;};const [y, m, d] = lines[0].trim().split("-").map(Number);const start = toCount(y, m, d);const n = Number(lines[1]);const out: string[] = [];for (let i = 0; i < n; i++) { const k = Number(lines[2 + i]); // 문자열 그대로 +하면 이어 붙이기가 된다 → 수로 바꾼 다음에 더한다 out.push(fromCount(start + k));}console.log(out.join("\n"));
JavaMain.java · 53 lines
import java.io.BufferedReader;import java.io.InputStreamReader;public class Main { static final int BASE = 1600; // 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374) static final int[] MONTH_DAYS = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년 static boolean isLeap(int y) { return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; } static int yearDays(int y) { return isLeap(y) ? 366 : 365; } static int monthDays(int y, int m) { return (m == 2 && isLeap(y)) ? 29 : MONTH_DAYS[m - 1]; } static int toCount(int y, int m, int d) { int total = d - 1; for (int yy = BASE; yy < y; yy++) total += yearDays(yy); for (int mm = 1; mm < m; mm++) total += monthDays(y, mm); return total; } static String fromCount(int c) { int y = BASE, m = 1; while (c >= yearDays(y)) { // 남은 날이 그해 날 수와 같으면 다음 해 1월 1일이다 c -= yearDays(y); y++; } while (c >= monthDays(y, m)) { c -= monthDays(y, m); m++; } return String.format("%04d-%02d-%02d", y, m, c + 1); } public static void main(String[] args) throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String[] p = in.readLine().trim().split("-"); int start = toCount(Integer.parseInt(p[0]), Integer.parseInt(p[1]), Integer.parseInt(p[2])); int n = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int i = 0; i < n; i++) { int k = Integer.parseInt(in.readLine().trim()); // 문자열과 +하면 이어 붙이기가 된다 → 수로 바꾼다 out.append(fromCount(start + k)).append('\n'); } System.out.print(out); }}
C#Main.cs · 51 lines
using System;using System.Text;class Program{ const int Base = 1600; // 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374) static readonly int[] MonthDaysTable = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; // 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년 static bool IsLeap(int y) => (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; static int YearDays(int y) => IsLeap(y) ? 366 : 365; static int MonthDays(int y, int m) => (m == 2 && IsLeap(y)) ? 29 : MonthDaysTable[m - 1]; static int ToCount(int y, int m, int d) { int total = d - 1; for (int yy = Base; yy < y; yy++) total += YearDays(yy); for (int mm = 1; mm < m; mm++) total += MonthDays(y, mm); return total; } static string FromCount(int c) { int y = Base, m = 1; while (c >= YearDays(y)) // 남은 날이 그해 날 수와 같으면 다음 해 1월 1일이다 { c -= YearDays(y); y++; } while (c >= MonthDays(y, m)) { c -= MonthDays(y, m); m++; } return $"{y:D4}-{m:D2}-{c + 1:D2}"; } static void Main() { string[] p = Console.ReadLine().Trim().Split('-'); int start = ToCount(int.Parse(p[0]), int.Parse(p[1]), int.Parse(p[2])); int n = int.Parse(Console.ReadLine()); var sb = new StringBuilder(); for (int i = 0; i < n; i++) { int k = int.Parse(Console.ReadLine()); // 문자열과 +하면 이어 붙이기가 된다 → 수로 바꾼다 sb.Append(FromCount(start + k)).Append('\n'); } Console.Write(sb); }}
C++main.cpp · 43 lines
#include <array>#include <cstdio>#include <iostream>constexpr int BASE = 1600; // 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374)constexpr std::array<int, 12> MONTH_DAYS{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년bool isLeap(int y) { return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; }int yearDays(int y) { return isLeap(y) ? 366 : 365; }int monthDays(int y, int m) { return (m == 2 && isLeap(y)) ? 29 : MONTH_DAYS[m - 1]; }int toCount(int y, int m, int d) { int total = d - 1; for (int yy = BASE; yy < y; yy++) total += yearDays(yy); for (int mm = 1; mm < m; mm++) total += monthDays(y, mm); return total;}void printDate(int c) { int y = BASE, m = 1; while (c >= yearDays(y)) { // 남은 날이 그해 날 수와 같으면 다음 해 1월 1일이다 c -= yearDays(y); y++; } while (c >= monthDays(y, m)) { c -= monthDays(y, m); m++; } std::printf("%04d-%02d-%02d\n", y, m, c + 1);}int main() { int y, m, d, n; char dash; std::cin >> y >> dash >> m >> dash >> d >> n; int start = toCount(y, m, d); for (int i = 0; i < n; i++) { int k; std::cin >> k; printDate(start + k); }}
Cmain.c · 43 lines
#include <stdio.h>#define BASE 1600 /* 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374) */static const int MONTH_DAYS[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};/* 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년 */int is_leap(int y) { return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; }int year_days(int y) { return is_leap(y) ? 366 : 365; }int month_days(int y, int m) { return (m == 2 && is_leap(y)) ? 29 : MONTH_DAYS[m - 1]; }int to_count(int y, int m, int d) { int total = d - 1; for (int yy = BASE; yy < y; yy++) total += year_days(yy); for (int mm = 1; mm < m; mm++) total += month_days(y, mm); return total;}void print_date(int c) { int y = BASE, m = 1; while (c >= year_days(y)) { /* 남은 날이 그해 날 수와 같으면 다음 해 1월 1일이다 */ c -= year_days(y); y++; } while (c >= month_days(y, m)) { c -= month_days(y, m); m++; } printf("%04d-%02d-%02d\n", y, m, c + 1);}int main(void) { int y, m, d, n; scanf("%d-%d-%d", &y, &m, &d); scanf("%d", &n); int start = to_count(y, m, d); for (int i = 0; i < n; i++) { int k; scanf("%d", &k); print_date(start + k); } return 0;}
Craykonmain.cray · 66 lines
BASE = 1600; // 날짜를 1600-01-01부터 센 날 수로 바꾼다(답의 연도는 1626 ~ 2374)MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];// 4로 나누어떨어지고 100으로는 안 나누어떨어지거나, 400으로 나누어떨어지면 윤년윤년인가(y){ return y % 4 == 0 && y % 100 != 0 || y % 400 == 0;}해의날수(y){ if (윤년인가(y)) { return 366; } return 365;}달의날수(y, m){ if (m == 2 && 윤년인가(y)) { return 29; } return MONTH_DAYS[m - 1];}센날수(y, m, d){ total = d - 1; for (yy = BASE; yy < y; yy++) { total += 해의날수(yy); } for (mm = 1; mm < m; mm++) { total += 달의날수(y, mm); } return total;}날짜로(c){ y = BASE; while (c >= 해의날수(y)) { c -= 해의날수(y); y += 1; } m = 1; while (c >= 달의날수(y, m)) { c -= 달의날수(y, m); m += 1; } return ("" + y).PadLeft(4, "0") + "-" + ("" + m).PadLeft(2, "0") + "-" + ("" + (c + 1)).PadLeft(2, "0");}칸 = Console.ReadLine().Trim().Split("-");start = 센날수(칸[0].ToNumber(), 칸[1].ToNumber(), 칸[2].ToNumber());n = Console.ReadLine().ToNumber();for (i = 0; i < n; i++){ k = Console.ReadLine().ToNumber(); // 문자열 그대로 +하면 이어 붙이기가 된다 → 수로 바꾼 다음에 더한다 Console.WriteLine(날짜로(start + k));}