{"record":{"id":"fa144f2a12c0f5b5","repo":"chinabugotech/hutool","slug":"birthday-is-after-datetocompare","errorCode":null,"errorMessage":"Birthday is after dateToCompare!","messagePattern":"Birthday is after dateToCompare!","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java","lineNumber":708,"sourceCode":"\n\t\treturn result.toString();\n\t}\n\n\t/**\n\t * 计算相对于dateToCompare的年龄，常用于计算指定生日在某年的年龄<br>\n\t * 按照《最高人民法院关于审理未成年人刑事案件具体应用法律若干问题的解释》第二条规定刑法第十七条规定的“周岁”，按照公历的年、月、日计算，从周岁生日的第二天起算。\n\t * <ul>\n\t *     <li>2022-03-01出生，则相对2023-03-01，周岁为0，相对于2023-03-02才是1岁。</li>\n\t *     <li>1999-02-28出生，则相对2000-02-29，周岁为1</li>\n\t * </ul>\n\t *\n\t * @param birthday      生日\n\t * @param dateToCompare 需要对比的日期\n\t * @return 年龄\n\t */\n\tprotected static int age(long birthday, long dateToCompare) {\n\t\tif (birthday > dateToCompare) {\n\t\t\tthrow new IllegalArgumentException(\"Birthday is after dateToCompare!\");\n\t\t}\n\n\t\tfinal Calendar cal = Calendar.getInstance();\n\t\tcal.setTimeInMillis(dateToCompare);\n\n\t\tfinal int year = cal.get(Calendar.YEAR);\n\t\tfinal int month = cal.get(Calendar.MONTH);\n\t\tfinal int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);\n\n\t\t// 复用cal\n\t\tcal.setTimeInMillis(birthday);\n\t\tint age = year - cal.get(Calendar.YEAR);\n\n\t\t//当前日期，则为0岁\n\t\tif (age == 0) {\n\t\t\treturn 0;\n\t\t}\n","sourceCodeStart":690,"sourceCodeEnd":726,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/date/CalendarUtil.java#L690-L726","documentation":"Thrown by CalendarUtil.age(long birthday, long dateToCompare) when the birthday timestamp is greater than the comparison date timestamp — i.e., the birthday is in the future relative to the date being compared. This is a logic error: you cannot compute age when the birth date is after the reference date. The method implements Chinese legal age reckoning (周岁).","triggerScenarios":"Calling DateUtil.age(futureBirthdayMillis, nowMillis) where the birthday epoch millis are after dateToCompare. Swapping argument order: passing the comparison date as 'birthday' and the birthday as 'dateToCompare'. System clock rollback or data entry putting a future birth date.","commonSituations":"User form where birth date is accidentally set to a future date. Data import with swapped date columns (e.g., 'created_date' passed as birthday). Test data with incorrect epoch values. System clock issues in environments causing dateToCompare to be earlier than expected.","solutions":["Validate that birthday <= dateToCompare before calling age(): if (birthday <= dateToCompare) { age(birthday, dateToCompare); }.","Check argument order: the first parameter is birthday (earlier), the second is dateToCompare (later).","Validate user-supplied birth dates to ensure they are not in the future: if (birthDate.after(new Date())) reject.","Use DateUtil.age(Date, Date) overload which delegates here, and pre-validate both Date arguments."],"exampleFix":"// before\nint age = DateUtil.age(birthdayDate, compareDate); // throws if birthday is future\n\n// after\nif (!birthdayDate.after(compareDate)) {\n    int age = DateUtil.age(birthdayDate, compareDate);\n} else {\n    // handle invalid birth date\n}","handlingStrategy":"validation","validationCode":"if (birthday > dateToCompare) {\n    throw new IllegalArgumentException(\"Birthday cannot be after the comparison date\");\n}\n// or skip:\nif (birthday <= dateToCompare) {\n    int age = DateUtil.age(birthday, dateToCompare);\n}","typeGuard":"static boolean isValidAgeInput(long birthday, long dateToCompare) {\n    return birthday <= dateToCompare;\n}","tryCatchPattern":"try {\n    return DateUtil.age(birthdayDate, compareDate);\n} catch (IllegalArgumentException e) {\n    // birthday is in the future relative to compare date\n    return 0; // or handle per business rule\n}","preventionTips":["Validate birthday <= dateToCompare before calling age().","Verify argument order: first is birthday (earlier), second is dateToCompare (later).","Reject future birth dates at the input/validation layer."],"tags":["date","calendar","age","argument-order","validation"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}