This commit is contained in:
2026-01-20 03:45:15 +08:00
parent 101e8b7e8e
commit 1498209b0e
147 changed files with 13055 additions and 12 deletions

View File

@@ -44,7 +44,8 @@ def truncation_correction(mu, sigma, C, p_thresh):
if p_trunc < p_thresh:
return mu, p_trunc, False
else:
mu_tilde = mu * (1 + 0.4 * p_trunc)
# 与主流程 `02_demand_correction.py` 保持一致:线性修正系数 0.1
mu_tilde = mu * (1 + 0.1 * p_trunc)
return mu_tilde, p_trunc, True

Binary file not shown.

View File

@@ -0,0 +1,121 @@
from __future__ import annotations
import math
from pathlib import Path
import pandas as pd
ROOT = Path(__file__).resolve().parent
OUT_DIR = ROOT / "paper_tables"
def _to_int_series(s: pd.Series) -> pd.Series:
return s.map(lambda x: int(round(float(x))) if pd.notna(x) else x)
def _to_float_series(s: pd.Series, ndigits: int) -> pd.Series:
return s.map(lambda x: round(float(x), ndigits) if pd.notna(x) else x)
def _format_table1_metrics_summary(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
out["E1_total_service"] = _to_int_series(out["E1_total_service"])
out["E2_quality_weighted"] = _to_int_series(out["E2_quality_weighted"])
out["F1_gini"] = _to_float_series(out["F1_gini"], 4)
out["F2_min_satisfaction"] = _to_float_series(out["F2_min_satisfaction"], 2)
out["F3_cv_satisfaction"] = _to_float_series(out["F3_cv_satisfaction"], 4)
out["E1_total_service_pct"] = _to_float_series(out["E1_total_service_pct"], 2)
out["E2_quality_weighted_pct"] = _to_float_series(out["E2_quality_weighted_pct"], 2)
return out
def _format_table2_corrected_sites(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
out["site_id"] = _to_int_series(out["site_id"])
out["mu"] = _to_float_series(out["mu"], 1)
out["sigma"] = _to_float_series(out["sigma"], 1)
out["p_trunc"] = _to_float_series(out["p_trunc"], 3)
out["mu_tilde"] = _to_float_series(out["mu_tilde"], 1)
out["mu_delta"] = _to_float_series(out["mu_delta"], 1)
out["mu_delta_pct"] = _to_float_series(out["mu_delta_pct"], 1)
return out
def _format_table3_backtest_summary(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
out["value"] = out["value"].map(lambda x: round(float(x), 6) if pd.notna(x) else x)
out["p_value"] = out["p_value"].map(lambda x: round(float(x), 6) if pd.notna(x) else x)
return out
def _format_appendix_site_details(df: pd.DataFrame) -> pd.DataFrame:
out = df.copy()
out["site_id"] = _to_int_series(out["site_id"])
out["mu"] = _to_float_series(out["mu"], 1)
out["mu_tilde"] = _to_float_series(out["mu_tilde"], 1)
out["k"] = _to_int_series(out["k"])
out["annual_service"] = _to_int_series(out["annual_service"])
out["r"] = _to_float_series(out["r"], 4)
out["quality_factor"] = _to_float_series(out["quality_factor"], 4)
out["service_quality_weighted"] = _to_int_series(out["service_quality_weighted"])
return out
def export_tables() -> list[Path]:
OUT_DIR.mkdir(parents=True, exist_ok=True)
written: list[Path] = []
# Table 1: overall performance comparison
metrics_xlsx = ROOT / "04_metrics.xlsx"
metrics = pd.read_excel(metrics_xlsx, sheet_name="metrics_summary")
metrics_paper = _format_table1_metrics_summary(metrics)
p1 = OUT_DIR / "table1_metrics_summary.csv"
metrics_paper.to_csv(p1, index=False, encoding="utf-8-sig")
written.append(p1)
# Table 2: truncation correction (corrected sites)
backtest_xlsx = ROOT / "07_backtest.xlsx"
corrected = pd.read_excel(backtest_xlsx, sheet_name="corrected_sites")
corrected = corrected.copy()
corrected["mu_delta"] = corrected["mu_tilde"] - corrected["mu"]
corrected["mu_delta_pct"] = corrected["mu_delta"] / corrected["mu"] * 100
corrected_paper = _format_table2_corrected_sites(corrected)
p2 = OUT_DIR / "table2_corrected_sites.csv"
corrected_paper.to_csv(p2, index=False, encoding="utf-8-sig")
written.append(p2)
# Table 3: backtest & fit statistics
summary = pd.read_excel(backtest_xlsx, sheet_name="summary_metrics")
summary_paper = _format_table3_backtest_summary(summary)
p3 = OUT_DIR / "table3_backtest_summary.csv"
summary_paper.to_csv(p3, index=False, encoding="utf-8-sig")
written.append(p3)
# Table 4: constraint validation results
validate_xlsx = ROOT / "06_validate.xlsx"
validation = pd.read_excel(validate_xlsx, sheet_name="validation_results")
p4 = OUT_DIR / "table4_validation_results.csv"
validation.to_csv(p4, index=False, encoding="utf-8-sig")
written.append(p4)
# Appendix: per-site allocation details (optional for paper appendix)
site_details = pd.read_excel(metrics_xlsx, sheet_name="site_details")
site_details_paper = _format_appendix_site_details(site_details)
p5 = OUT_DIR / "appendix_site_details.csv"
site_details_paper.to_csv(p5, index=False, encoding="utf-8-sig")
written.append(p5)
return written
def main() -> None:
written = export_tables()
rel = [p.relative_to(ROOT) for p in written]
print("Wrote:")
for p in rel:
print(f" - {p}")
if __name__ == "__main__":
main()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 180 KiB

View File

@@ -0,0 +1,71 @@
site_id,site_name,mu,mu_tilde,k,annual_service,r,quality_factor,service_quality_weighted
1.0,MFP American Legion - Binghamton,200,200,14.0,2803,14.0,1.0,2803
2.0,MFP Avoca,315,323,22.0,6921,21.4249,0.7947,5500
3.0,MFP Bath,279,279,19.0,5310,19.0,0.8946,4750
4.0,MFP Beaver Dams,171,171,12.0,2048,12.0,1.0,2048
5.0,MFP Birnie Transportation Services,213,213,15.0,3201,15.0,1.0,3201
6.0,MFP Boys and Girls Club,211,211,15.0,3162,15.0,1.0,3162
7.0,MFP Bradford,122,122,9.0,1100,9.0,1.0,1100
8.0,MFP Campbell,168,168,12.0,2022,12.0,1.0,2022
9.0,MFP Canisteo,177,177,13.0,2301,13.0,1.0,2301
10.0,MFP Colesville,197,197,14.0,2763,14.0,1.0,2763
11.0,MFP College Corning Community College,251,251,18.0,4518,18.0,0.996,4500
12.0,MFP College Ithaca College,138,138,10.0,1383,10.0,1.0,1383
13.0,MFP College TC3 -College,262,266,19.0,4968,18.686,0.956,4750
14.0,MFP Conklin- Maines Community Center,153,153,11.0,1685,11.0,1.0,1685
15.0,MFP Danby,160,160,12.0,1923,12.0,1.0,1923
16.0,MFP Deposit,157,157,11.0,1722,11.0,1.0,1722
17.0,MFP Endwell United Methodist Church,285,289,20.0,5705,19.7173,0.8764,5000
18.0,MFP Erin,174,174,13.0,2261,13.0,1.0,2261
19.0,MFP First Assembly Of God Church,146,146,11.0,1606,11.0,1.0,1606
20.0,MFP Lamphear Court,126,126,9.0,1134,9.0,1.0,1134
21.0,MFP Lansing,181,181,13.0,2353,13.0,1.0,2353
22.0,MFP Lindley,233,233,16.0,3726,16.0,1.0,3726
23.0,MFP Millport,166,166,12.0,1992,12.0,1.0,1992
24.0,MFP Montour Falls-Schuyler County Human Services Complex,149,149,11.0,1643,11.0,1.0,1643
25.0,MFP Nichols-The Creamery,122,122,9.0,1102,9.0,1.0,1102
26.0,MFP Owego VFW,176,176,13.0,2291,13.0,1.0,2291
27.0,MFP Prattsburgh,144,144,11.0,1590,11.0,1.0,1590
28.0,MFP Rathbone,269,269,19.0,5113,19.0,0.9291,4750
29.0,MFP Reach for Christ Church Freeville,220,220,16.0,3520,16.0,1.0,3520
30.0,MFP Redeemer Lutheran Church,231,233,16.0,3690,15.8404,1.0,3690
31.0,MFP Rehoboth Deliverance Ministry,236,236,17.0,4010,17.0,1.0,4010
32.0,MFP Richford,266,266,19.0,5052,19.0,0.9402,4750
33.0,MFP Saint Mary Recreation Center,148,148,11.0,1631,11.0,1.0,1631
34.0,MFP Salvation Army Ithaca,181,181,13.0,2355,13.0,1.0,2355
35.0,MFP Schuyler Outreach,139,139,10.0,1389,10.0,1.0,1389
36.0,MFP Senior - Addison Place Apartments,30,30,3.0,90,3.0,1.0,90
37.0,MFP Senior - Bragg,67,67,5.0,334,5.0,1.0,334
38.0,MFP Senior - Carpenter Apartments,31,31,3.0,93,3.0,1.0,93
39.0,MFP Senior - Cayuga Meadows,26,26,3.0,78,3.0,1.0,78
40.0,MFP Senior - CFS Lakeview,112,112,8.0,896,8.0,1.0,896
41.0,MFP Senior - Conifer Village,34,34,3.0,101,3.0,1.0,101
42.0,MFP Senior - Corning Senior Center,75,75,6.0,450,6.0,1.0,450
43.0,MFP Senior - Dayspring,77,77,6.0,463,6.0,1.0,463
44.0,MFP Senior - East Hill Senior Living,40,40,4.0,159,4.0,1.0,159
45.0,"MFP Senior - Elizabeth Square, Waverly",29,29,3.0,87,3.0,1.0,87
46.0,MFP Senior - Ellis Hollow,25,25,3.0,74,3.0,1.0,74
47.0,MFP Senior - Flannery,62,62,5.0,309,5.0,1.0,309
48.0,MFP Senior - Harry L Apartments,33,33,3.0,99,3.0,1.0,99
49.0,MFP Senior - Jefferson Village,25,25,3.0,74,3.0,1.0,74
50.0,MFP Senior - Lincoln Court,26,26,3.0,78,3.0,1.0,78
51.0,MFP Senior - Long Meadow Senior Housing,35,35,3.0,104,3.0,1.0,104
52.0,MFP Senior - Metro Plaza Apartments,56,56,5.0,282,5.0,1.0,282
53.0,MFP Senior - North Shore Towers,58,58,5.0,292,5.0,1.0,292
54.0,"MFP Senior - Northern Broome Senior Center, Whitney Point",51,51,4.0,204,4.0,1.0,204
55.0,MFP Senior - Park Terrace Congregate Apartments,24,24,3.0,73,3.0,1.0,73
56.0,MFP Senior - Springview Apartments,28,28,3.0,83,3.0,1.0,83
57.0,MFP Senior - Titus Towers,73,73,6.0,437,6.0,1.0,437
58.0,MFP Senior - Villa Serene,70,70,6.0,418,6.0,1.0,418
59.0,MFP Senior - Village Square/Manor,34,34,3.0,103,3.0,1.0,103
60.0,MFP Senior - Wells Apartments,24,24,3.0,70,3.0,1.0,70
61.0,MFP Senior - Woodsedge Apartments,17,17,2.0,34,2.0,1.0,34
62.0,MFP The Love Church,259,259,18.0,4668,18.0,0.964,4500
63.0,MFP Troupsburg,149,149,11.0,1636,11.0,1.0,1636
64.0,MFP Tuscarora,193,193,14.0,2697,14.0,1.0,2697
65.0,MFP Van Etten,214,214,15.0,3206,15.0,1.0,3206
66.0,MFP Waverly,397,429,29.0,11502,26.8129,0.6303,7250
67.0,MFP Wayland,180,180,13.0,2345,13.0,1.0,2345
68.0,MFP Whitney Point,203,203,14.0,2836,14.0,1.0,2836
69.0,MFP Windsor,201,201,14.0,2813,14.0,1.0,2813
70.0,MFP Woodhull,176,176,13.0,2288,13.0,1.0,2288
1 site_id site_name mu mu_tilde k annual_service r quality_factor service_quality_weighted
2 1.0 MFP American Legion - Binghamton 200 200 14.0 2803 14.0 1.0 2803
3 2.0 MFP Avoca 315 323 22.0 6921 21.4249 0.7947 5500
4 3.0 MFP Bath 279 279 19.0 5310 19.0 0.8946 4750
5 4.0 MFP Beaver Dams 171 171 12.0 2048 12.0 1.0 2048
6 5.0 MFP Birnie Transportation Services 213 213 15.0 3201 15.0 1.0 3201
7 6.0 MFP Boys and Girls Club 211 211 15.0 3162 15.0 1.0 3162
8 7.0 MFP Bradford 122 122 9.0 1100 9.0 1.0 1100
9 8.0 MFP Campbell 168 168 12.0 2022 12.0 1.0 2022
10 9.0 MFP Canisteo 177 177 13.0 2301 13.0 1.0 2301
11 10.0 MFP Colesville 197 197 14.0 2763 14.0 1.0 2763
12 11.0 MFP College Corning Community College 251 251 18.0 4518 18.0 0.996 4500
13 12.0 MFP College Ithaca College 138 138 10.0 1383 10.0 1.0 1383
14 13.0 MFP College TC3 -College 262 266 19.0 4968 18.686 0.956 4750
15 14.0 MFP Conklin- Maines Community Center 153 153 11.0 1685 11.0 1.0 1685
16 15.0 MFP Danby 160 160 12.0 1923 12.0 1.0 1923
17 16.0 MFP Deposit 157 157 11.0 1722 11.0 1.0 1722
18 17.0 MFP Endwell United Methodist Church 285 289 20.0 5705 19.7173 0.8764 5000
19 18.0 MFP Erin 174 174 13.0 2261 13.0 1.0 2261
20 19.0 MFP First Assembly Of God Church 146 146 11.0 1606 11.0 1.0 1606
21 20.0 MFP Lamphear Court 126 126 9.0 1134 9.0 1.0 1134
22 21.0 MFP Lansing 181 181 13.0 2353 13.0 1.0 2353
23 22.0 MFP Lindley 233 233 16.0 3726 16.0 1.0 3726
24 23.0 MFP Millport 166 166 12.0 1992 12.0 1.0 1992
25 24.0 MFP Montour Falls-Schuyler County Human Services Complex 149 149 11.0 1643 11.0 1.0 1643
26 25.0 MFP Nichols-The Creamery 122 122 9.0 1102 9.0 1.0 1102
27 26.0 MFP Owego VFW 176 176 13.0 2291 13.0 1.0 2291
28 27.0 MFP Prattsburgh 144 144 11.0 1590 11.0 1.0 1590
29 28.0 MFP Rathbone 269 269 19.0 5113 19.0 0.9291 4750
30 29.0 MFP Reach for Christ Church Freeville 220 220 16.0 3520 16.0 1.0 3520
31 30.0 MFP Redeemer Lutheran Church 231 233 16.0 3690 15.8404 1.0 3690
32 31.0 MFP Rehoboth Deliverance Ministry 236 236 17.0 4010 17.0 1.0 4010
33 32.0 MFP Richford 266 266 19.0 5052 19.0 0.9402 4750
34 33.0 MFP Saint Mary Recreation Center 148 148 11.0 1631 11.0 1.0 1631
35 34.0 MFP Salvation Army Ithaca 181 181 13.0 2355 13.0 1.0 2355
36 35.0 MFP Schuyler Outreach 139 139 10.0 1389 10.0 1.0 1389
37 36.0 MFP Senior - Addison Place Apartments 30 30 3.0 90 3.0 1.0 90
38 37.0 MFP Senior - Bragg 67 67 5.0 334 5.0 1.0 334
39 38.0 MFP Senior - Carpenter Apartments 31 31 3.0 93 3.0 1.0 93
40 39.0 MFP Senior - Cayuga Meadows 26 26 3.0 78 3.0 1.0 78
41 40.0 MFP Senior - CFS Lakeview 112 112 8.0 896 8.0 1.0 896
42 41.0 MFP Senior - Conifer Village 34 34 3.0 101 3.0 1.0 101
43 42.0 MFP Senior - Corning Senior Center 75 75 6.0 450 6.0 1.0 450
44 43.0 MFP Senior - Dayspring 77 77 6.0 463 6.0 1.0 463
45 44.0 MFP Senior - East Hill Senior Living 40 40 4.0 159 4.0 1.0 159
46 45.0 MFP Senior - Elizabeth Square, Waverly 29 29 3.0 87 3.0 1.0 87
47 46.0 MFP Senior - Ellis Hollow 25 25 3.0 74 3.0 1.0 74
48 47.0 MFP Senior - Flannery 62 62 5.0 309 5.0 1.0 309
49 48.0 MFP Senior - Harry L Apartments 33 33 3.0 99 3.0 1.0 99
50 49.0 MFP Senior - Jefferson Village 25 25 3.0 74 3.0 1.0 74
51 50.0 MFP Senior - Lincoln Court 26 26 3.0 78 3.0 1.0 78
52 51.0 MFP Senior - Long Meadow Senior Housing 35 35 3.0 104 3.0 1.0 104
53 52.0 MFP Senior - Metro Plaza Apartments 56 56 5.0 282 5.0 1.0 282
54 53.0 MFP Senior - North Shore Towers 58 58 5.0 292 5.0 1.0 292
55 54.0 MFP Senior - Northern Broome Senior Center, Whitney Point 51 51 4.0 204 4.0 1.0 204
56 55.0 MFP Senior - Park Terrace Congregate Apartments 24 24 3.0 73 3.0 1.0 73
57 56.0 MFP Senior - Springview Apartments 28 28 3.0 83 3.0 1.0 83
58 57.0 MFP Senior - Titus Towers 73 73 6.0 437 6.0 1.0 437
59 58.0 MFP Senior - Villa Serene 70 70 6.0 418 6.0 1.0 418
60 59.0 MFP Senior - Village Square/Manor 34 34 3.0 103 3.0 1.0 103
61 60.0 MFP Senior - Wells Apartments 24 24 3.0 70 3.0 1.0 70
62 61.0 MFP Senior - Woodsedge Apartments 17 17 2.0 34 2.0 1.0 34
63 62.0 MFP The Love Church 259 259 18.0 4668 18.0 0.964 4500
64 63.0 MFP Troupsburg 149 149 11.0 1636 11.0 1.0 1636
65 64.0 MFP Tuscarora 193 193 14.0 2697 14.0 1.0 2697
66 65.0 MFP Van Etten 214 214 15.0 3206 15.0 1.0 3206
67 66.0 MFP Waverly 397 429 29.0 11502 26.8129 0.6303 7250
68 67.0 MFP Wayland 180 180 13.0 2345 13.0 1.0 2345
69 68.0 MFP Whitney Point 203 203 14.0 2836 14.0 1.0 2836
70 69.0 MFP Windsor 201 201 14.0 2813 14.0 1.0 2813
71 70.0 MFP Woodhull 176 176 13.0 2288 13.0 1.0 2288

View File

@@ -0,0 +1,5 @@
method,E1_total_service,E2_quality_weighted,F1_gini,F2_min_satisfaction,F3_cv_satisfaction,E1_total_service_pct,E2_quality_weighted_pct
Recommended (μ̃ proportional),139469,131462,0.3137,2.0,0.5603,0,0
Baseline 1: Uniform,104797,101309,0.0244,9.2458,0.0486,-25,-23
Baseline 2: 2019 Scaled,104071,100264,0.0915,5.0,0.1759,-25,-24
Baseline 3: μ proportional (no correction),139129,131397,0.313,2.0,0.5561,0,0
1 method E1_total_service E2_quality_weighted F1_gini F2_min_satisfaction F3_cv_satisfaction E1_total_service_pct E2_quality_weighted_pct
2 Recommended (μ̃ proportional) 139469 131462 0.3137 2.0 0.5603 0 0
3 Baseline 1: Uniform 104797 101309 0.0244 9.2458 0.0486 -25 -23
4 Baseline 2: 2019 Scaled 104071 100264 0.0915 5.0 0.1759 -25 -24
5 Baseline 3: μ proportional (no correction) 139129 131397 0.313 2.0 0.5561 0 0

View File

@@ -0,0 +1,6 @@
site_id,site_name,mu,sigma,p_trunc,mu_tilde,mu_delta,mu_delta_pct
2.0,MFP Avoca,315,57.3497,0.2684,323,8,3.0
13.0,MFP College TC3 -College,262,91.9929,0.168,266,4,2.0
17.0,MFP Endwell United Methodist Church,285,60.7815,0.1434,289,4,1.0
30.0,MFP Redeemer Lutheran Church,231,93.4787,0.1007,233,2,1.0
66.0,MFP Waverly,397,51.8754,0.8157,429,32,8.0
1 site_id site_name mu sigma p_trunc mu_tilde mu_delta mu_delta_pct
2 2.0 MFP Avoca 315 57.3497 0.2684 323 8 3.0
3 13.0 MFP College TC3 -College 262 91.9929 0.168 266 4 2.0
4 17.0 MFP Endwell United Methodist Church 285 60.7815 0.1434 289 4 1.0
5 30.0 MFP Redeemer Lutheran Church 231 93.4787 0.1007 233 2 1.0
6 66.0 MFP Waverly 397 51.8754 0.8157 429 32 8.0

View File

@@ -0,0 +1,10 @@
metric,value,p_value
"corr(visits_2019, μ)",0.0349,0.774
"corr(visits_2019, μ̃)",0.0364,0.7645
sites_increased,36.0,
sites_decreased,32.0,
sites_unchanged,2.0,
CV(k/μ̃),0.1974,
service_2019_actual,102473.0,
service_model,139469.0768,
improvement_pct,34.6117,
1 metric value p_value
2 corr(visits_2019, μ) 0.0349 0.774
3 corr(visits_2019, μ̃) 0.0364 0.7645
4 sites_increased 36.0
5 sites_decreased 32.0
6 sites_unchanged 2.0
7 CV(k/μ̃) 0.1974
8 service_2019_actual 102473.0
9 service_model 139469.0768
10 improvement_pct 34.6117

View File

@@ -0,0 +1,7 @@
constraint,formula,expected,actual,passed,details
C1: 资源约束,Σk_i = 730,730,730,True,总访问次数 = 730
C2: 覆盖约束,k_i >= 1,>= 1,min = 2,True,"最小访问次数 = 2, 违反站点数 = 0"
C3: 日容量约束,每日站点数 = 2,所有天 = 2,"min=2, max=2",True,不满足的天数 = 0
C4: 无重复约束,site_1 ≠ site_2 (同一天),无重复,重复天数 = 0,True,
C5: 排程一致性,排程次数 = k_i,所有站点一致,不一致站点数 = 0,True,全部一致
C6: 总天数,日历天数 = 365,365,365,True,日历包含 365 天
1 constraint formula expected actual passed details
2 C1: 资源约束 Σk_i = 730 730 730 True 总访问次数 = 730
3 C2: 覆盖约束 k_i >= 1 >= 1 min = 2 True 最小访问次数 = 2, 违反站点数 = 0
4 C3: 日容量约束 每日站点数 = 2 所有天 = 2 min=2, max=2 True 不满足的天数 = 0
5 C4: 无重复约束 site_1 ≠ site_2 (同一天) 无重复 重复天数 = 0 True
6 C5: 排程一致性 排程次数 = k_i 所有站点一致 不一致站点数 = 0 True 全部一致
7 C6: 总天数 日历天数 = 365 365 365 True 日历包含 365 天