|
|
@@ -0,0 +1,106 @@
|
|
|
+package com.sqx.common.utils;
|
|
|
+
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.Period;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+public class MenstrualCycleCalculator {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算预测的下次经期开始日期
|
|
|
+ * @param lastPeriodStart 上次经期开始日期
|
|
|
+ * @param cycleLength 月经周期长度(天)
|
|
|
+ * @return 预测的下次经期开始日期
|
|
|
+ */
|
|
|
+ public static LocalDate predictNextPeriod(LocalDate lastPeriodStart, int cycleLength) {
|
|
|
+ return lastPeriodStart.plusDays(cycleLength);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算预测的排卵日
|
|
|
+ * @param nextPeriodStart 预测的下次经期开始日期
|
|
|
+ * @return 预测的排卵日(下次经期前14天)
|
|
|
+ */
|
|
|
+ public static LocalDate predictOvulationDay(LocalDate nextPeriodStart) {
|
|
|
+ return nextPeriodStart.minusDays(14);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算预测的受孕窗口期(排卵日前5天到排卵日后1天)
|
|
|
+ * @param ovulationDay 排卵日
|
|
|
+ * @return 包含受孕窗口期开始和结束日期的数组
|
|
|
+ */
|
|
|
+ public static LocalDate[] predictFertileWindow(LocalDate ovulationDay) {
|
|
|
+ return new LocalDate[] {
|
|
|
+ ovulationDay.minusDays(5),
|
|
|
+ ovulationDay.plusDays(1)
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算月经周期长度
|
|
|
+ * @param previousStart 前次经期开始日期
|
|
|
+ * @param currentStart 本次经期开始日期
|
|
|
+ * @return 周期长度(天)
|
|
|
+ */
|
|
|
+ public static int calculateCycleLength(LocalDate previousStart, LocalDate currentStart) {
|
|
|
+ return Period.between(previousStart, currentStart).getDays();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成未来几个周期的预测
|
|
|
+ * @param lastPeriodStart 最近一次经期开始日期
|
|
|
+ * @param cycleLength 月经周期长度
|
|
|
+ * @param periodDuration 经期持续时间(天)
|
|
|
+ * @param numberOfCycles 要预测的周期数
|
|
|
+ * @return 包含预测结果的列表
|
|
|
+ */
|
|
|
+ public static List<String> generateForecast(LocalDate lastPeriodStart,
|
|
|
+ int cycleLength, int periodDuration, int numberOfCycles) {
|
|
|
+ List<String> forecast = new ArrayList<>();
|
|
|
+ LocalDate nextPeriodStart = lastPeriodStart;
|
|
|
+
|
|
|
+ for (int i = 1; i <= numberOfCycles; i++) {
|
|
|
+ nextPeriodStart = predictNextPeriod(nextPeriodStart, cycleLength);
|
|
|
+ LocalDate ovulationDay = predictOvulationDay(nextPeriodStart);
|
|
|
+ LocalDate[] fertileWindow = predictFertileWindow(ovulationDay);
|
|
|
+
|
|
|
+ forecast.add(String.format("周期 %d: 预计经期 %s 至 %s | 排卵日: %s | 受孕窗口: %s 至 %s",
|
|
|
+ i,
|
|
|
+ nextPeriodStart,
|
|
|
+ nextPeriodStart.plusDays(periodDuration - 1),
|
|
|
+ ovulationDay,
|
|
|
+ fertileWindow[0],
|
|
|
+ fertileWindow[1]
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ return forecast;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ // 示例用法
|
|
|
+ LocalDate lastPeriod = LocalDate.of(2025, 8, 1);
|
|
|
+ int cycleLength = 28; // 平均周期长度
|
|
|
+ int periodDuration = 5; // 平均经期持续时间
|
|
|
+
|
|
|
+ System.out.println("=== 经期预测 ===");
|
|
|
+ System.out.println("上次经期开始: " + lastPeriod);
|
|
|
+ System.out.println("平均周期长度: " + cycleLength + "天");
|
|
|
+ System.out.println("平均经期持续时间: " + periodDuration + "天");
|
|
|
+ System.out.println();
|
|
|
+
|
|
|
+ System.out.println("预测下次经期开始: " + predictNextPeriod(lastPeriod, cycleLength));
|
|
|
+ System.out.println("预测排卵日: " + predictOvulationDay(predictNextPeriod(lastPeriod, cycleLength)));
|
|
|
+
|
|
|
+ LocalDate[] fertileWindow = predictFertileWindow(
|
|
|
+ predictOvulationDay(predictNextPeriod(lastPeriod, cycleLength)));
|
|
|
+ System.out.println("预测受孕窗口: " + fertileWindow[0] + " 至 " + fertileWindow[1]);
|
|
|
+ System.out.println();
|
|
|
+
|
|
|
+ System.out.println("=== 未来3个周期预测 ===");
|
|
|
+ generateForecast(lastPeriod, cycleLength, periodDuration, 3)
|
|
|
+ .forEach(System.out::println);
|
|
|
+ }
|
|
|
+}
|