From 1b39b80bd75fa19381f447c88f40b427649eedae Mon Sep 17 00:00:00 2001 From: hanyixuanten <105723997+hanyixuanten@users.noreply.github.com> Date: Mon, 20 Jul 2026 20:38:43 +0800 Subject: [PATCH] add last_update varible --- AGENTS.md | 8 +- README.md | 23 +- README_zh.md | 23 +- contests.json | 215 ++--- contests_all.json | 2239 +++++++++++++++++++++++---------------------- fetch_contests.py | 11 +- server/index.php | 72 +- 7 files changed, 1341 insertions(+), 1250 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3194114..ed60e42 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,8 +32,8 @@ When removing a provider, remove or adjust the same surfaces so stale platform l ## Output Contracts -- `contests.json` contains contests that have not ended yet: `upcoming` and `running`. -- `contests_all.json` contains contests that finished within the last 30 days. +- `contests.json` is an object with `generated_at` and `contests`; `contests` contains contests that have not ended yet: `upcoming` and `running`. +- `contests_all.json` is an object with `generated_at` and `contests`; `contests` contains contests that finished within the last 30 days. - JSON timestamps are Unix timestamps in seconds. - Keep record keys stable unless the README files and server rendering are updated in the same change. @@ -50,8 +50,8 @@ python fetch_contests.py Then inspect the generated files with `jq` when available, for example: ```bash -jq 'group_by(.platform) | map({platform: .[0].platform, count: length})' contests.json -jq 'group_by(.status) | map({status: .[0].status, count: length})' contests_all.json +jq '.contests | group_by(.platform) | map({platform: .[0].platform, count: length})' contests.json +jq '.contests | group_by(.status) | map({status: .[0].status, count: length})' contests_all.json ``` For PHP-only presentation changes, also check that `server/index.php` still reads `contests.json` and handles unknown platforms with the default styling. diff --git a/README.md b/README.md index 4bd9bfd..6b96d47 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,25 @@ Running the fetch script writes JSON files to the repository root: - `contests.json`: contests that have not ended yet, including upcoming and currently running contests. - `contests_all.json`: contests that finished within the last 30 days. -Each contest item has this shape: +Each JSON file has this top-level shape. `generated_at` is the Unix timestamp in seconds when the file was written. ```json { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 468", - "start_time": 1784980800, - "end_time": 1784986800, - "status": "upcoming", - "url": "https://atcoder.jp/contests/abc468" + "generated_at": 1784550894, + "contests": [ + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 468", + "start_time": 1784980800, + "end_time": 1784986800, + "status": "upcoming", + "url": "https://atcoder.jp/contests/abc468" + } + ] } ``` -`start_time` and `end_time` are Unix timestamps in seconds. `status` can be one of: +Each contest item is stored under `contests`. `start_time` and `end_time` are Unix timestamps in seconds. `status` can be one of: - `finished` - `running` @@ -65,7 +70,7 @@ Total contests finished in last 30 days: 139 ## Web Page -`server/index.php` reads the public raw GitHub URLs for `contests.json` and `contests_all.json`, caches them locally for 5 minutes, and renders upcoming contests with a client-side countdown plus recently finished contests. The page detects the browser/system language and time zone, syncs them to cookies, and uses them for localized text and contest times on later page loads. Unsupported languages fall back to English. +`server/index.php` reads the public raw GitHub URLs for `contests.json` and `contests_all.json`, caches them locally for 5 minutes, and renders upcoming contests with a client-side countdown plus recently finished contests. It also shows the JSON `generated_at` value as the last update time in the detected time zone. The page detects the browser/system language and time zone, syncs them to cookies, and uses them for localized text and contest times on later page loads. Unsupported languages fall back to English. If you deploy it yourself, update this constant in `server/index.php` if your repository path or branch changes: diff --git a/README_zh.md b/README_zh.md index f988039..a1ceb76 100644 --- a/README_zh.md +++ b/README_zh.md @@ -18,20 +18,25 @@ - `contests.json`:尚未结束的比赛,包括尚未开始和正在进行中的比赛。 - `contests_all.json`:最近 30 天内已经结束的比赛。 -每条比赛记录的结构如下: +每个 JSON 文件的顶层结构如下。`generated_at` 是文件写入时的秒级 Unix 时间戳。 ```json { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 468", - "start_time": 1784980800, - "end_time": 1784986800, - "status": "upcoming", - "url": "https://atcoder.jp/contests/abc468" + "generated_at": 1784550894, + "contests": [ + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 468", + "start_time": 1784980800, + "end_time": 1784986800, + "status": "upcoming", + "url": "https://atcoder.jp/contests/abc468" + } + ] } ``` -`start_time` 和 `end_time` 是秒级 Unix 时间戳。`status` 可能是以下值之一: +比赛记录存放在 `contests` 数组中。`start_time` 和 `end_time` 是秒级 Unix 时间戳。`status` 可能是以下值之一: - `finished`:已结束 - `running`:进行中 @@ -65,7 +70,7 @@ Total contests finished in last 30 days: 139 ## 网页展示 -`server/index.php` 会读取公开的 GitHub Raw 地址中的 `contests.json` 和 `contests_all.json`,在本地缓存 5 分钟,并渲染带客户端倒计时的即将开始比赛,以及最近已结束的比赛。页面会识别浏览器/系统语言和时区,将其同步到 cookie,并在后续加载时用于本地化文案和比赛时间显示。不支持的语言会回退到英语。 +`server/index.php` 会读取公开的 GitHub Raw 地址中的 `contests.json` 和 `contests_all.json`,在本地缓存 5 分钟,并渲染带客户端倒计时的即将开始比赛,以及最近已结束的比赛。页面还会读取 JSON 中的 `generated_at`,按检测到的时区显示最后更新时间。页面会识别浏览器/系统语言和时区,将其同步到 cookie,并在后续加载时用于本地化文案和比赛时间显示。不支持的语言会回退到英语。 如果你自行部署,并且仓库路径或分支发生变化,需要修改 `server/index.php` 中的这个常量: diff --git a/contests.json b/contests.json index 1516121..38192de 100644 --- a/contests.json +++ b/contests.json @@ -1,106 +1,109 @@ -[ - { - "platform": "Nowcoder", - "title": "2026牛客暑期多校训练营2", - "start_time": 1784692800, - "end_time": 1784710800, - "status": "upcoming", - "url": "https://ac.nowcoder.com/acm/contest/133877" - }, - { - "platform": "Nowcoder", - "title": "2026牛客暑期多校训练营3", - "start_time": 1784865600, - "end_time": 1784883600, - "status": "upcoming", - "url": "https://ac.nowcoder.com/acm/contest/133878" - }, - { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 468", - "start_time": 1784980800, - "end_time": 1784986800, - "status": "upcoming", - "url": "https://atcoder.jp/contests/abc468" - }, - { - "platform": "Nowcoder", - "title": "牛客周赛 Round 154", - "start_time": 1785063600, - "end_time": 1785070800, - "status": "upcoming", - "url": "https://ac.nowcoder.com/acm/contest/137840" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round (Div. 1)", - "start_time": 1785076500, - "end_time": 1785085500, - "status": "upcoming", - "url": "https://codeforces.com/contests/2249" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round (Div. 2)", - "start_time": 1785076500, - "end_time": 1785085500, - "status": "upcoming", - "url": "https://codeforces.com/contests/2250" - }, - { - "platform": "Nowcoder", - "title": "2026牛客暑期多校训练营4", - "start_time": 1785297600, - "end_time": 1785315600, - "status": "upcoming", - "url": "https://ac.nowcoder.com/acm/contest/133879" - }, - { - "platform": "Nowcoder", - "title": "2026牛客暑期多校训练营5", - "start_time": 1785470400, - "end_time": 1785488400, - "status": "upcoming", - "url": "https://ac.nowcoder.com/acm/contest/133880" - }, - { - "platform": "AtCoder", - "title": "RECRUIT Nihonbashi Half Marathon 2026 Summer (AtCoder Heuristic Contest 069)", - "start_time": 1785492000, - "end_time": 1786356000, - "status": "upcoming", - "url": "https://atcoder.jp/contests/ahc069" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round (Div. 2)", - "start_time": 1785584100, - "end_time": 1785591300, - "status": "upcoming", - "url": "https://codeforces.com/contests/2248" - }, - { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 469", - "start_time": 1785585600, - "end_time": 1785591600, - "status": "upcoming", - "url": "https://atcoder.jp/contests/abc469" - }, - { - "platform": "Nowcoder", - "title": "牛客周赛 Round 155", - "start_time": 1785668400, - "end_time": 1785675600, - "status": "upcoming", - "url": "https://ac.nowcoder.com/acm/contest/138240" - }, - { - "platform": "AtCoder", - "title": "UNIQUE VISION Programming Contest 2026 Summer (AtCoder Regular Contest 226)", - "start_time": 1786276800, - "end_time": 1786284000, - "status": "upcoming", - "url": "https://atcoder.jp/contests/arc226" - } -] \ No newline at end of file +{ + "generated_at": 1784551054, + "contests": [ + { + "platform": "Nowcoder", + "title": "2026牛客暑期多校训练营2", + "start_time": 1784692800, + "end_time": 1784710800, + "status": "upcoming", + "url": "https://ac.nowcoder.com/acm/contest/133877" + }, + { + "platform": "Nowcoder", + "title": "2026牛客暑期多校训练营3", + "start_time": 1784865600, + "end_time": 1784883600, + "status": "upcoming", + "url": "https://ac.nowcoder.com/acm/contest/133878" + }, + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 468", + "start_time": 1784980800, + "end_time": 1784986800, + "status": "upcoming", + "url": "https://atcoder.jp/contests/abc468" + }, + { + "platform": "Nowcoder", + "title": "牛客周赛 Round 154", + "start_time": 1785063600, + "end_time": 1785070800, + "status": "upcoming", + "url": "https://ac.nowcoder.com/acm/contest/137840" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round (Div. 1)", + "start_time": 1785076500, + "end_time": 1785085500, + "status": "upcoming", + "url": "https://codeforces.com/contests/2249" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round (Div. 2)", + "start_time": 1785076500, + "end_time": 1785085500, + "status": "upcoming", + "url": "https://codeforces.com/contests/2250" + }, + { + "platform": "Nowcoder", + "title": "2026牛客暑期多校训练营4", + "start_time": 1785297600, + "end_time": 1785315600, + "status": "upcoming", + "url": "https://ac.nowcoder.com/acm/contest/133879" + }, + { + "platform": "Nowcoder", + "title": "2026牛客暑期多校训练营5", + "start_time": 1785470400, + "end_time": 1785488400, + "status": "upcoming", + "url": "https://ac.nowcoder.com/acm/contest/133880" + }, + { + "platform": "AtCoder", + "title": "RECRUIT Nihonbashi Half Marathon 2026 Summer (AtCoder Heuristic Contest 069)", + "start_time": 1785492000, + "end_time": 1786356000, + "status": "upcoming", + "url": "https://atcoder.jp/contests/ahc069" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round (Div. 2)", + "start_time": 1785584100, + "end_time": 1785591300, + "status": "upcoming", + "url": "https://codeforces.com/contests/2248" + }, + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 469", + "start_time": 1785585600, + "end_time": 1785591600, + "status": "upcoming", + "url": "https://atcoder.jp/contests/abc469" + }, + { + "platform": "Nowcoder", + "title": "牛客周赛 Round 155", + "start_time": 1785668400, + "end_time": 1785675600, + "status": "upcoming", + "url": "https://ac.nowcoder.com/acm/contest/138240" + }, + { + "platform": "AtCoder", + "title": "UNIQUE VISION Programming Contest 2026 Summer (AtCoder Regular Contest 226)", + "start_time": 1786276800, + "end_time": 1786284000, + "status": "upcoming", + "url": "https://atcoder.jp/contests/arc226" + } + ] +} \ No newline at end of file diff --git a/contests_all.json b/contests_all.json index 2b4c1ae..057f84b 100644 --- a/contests_all.json +++ b/contests_all.json @@ -1,1114 +1,1125 @@ -[ - { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 463", - "start_time": 1781956800, - "end_time": 1781962800, - "status": "finished", - "url": "https://atcoder.jp/contests/abc463" - }, - { - "platform": "Nowcoder", - "title": "牛客周赛 Round 149", - "start_time": 1782039600, - "end_time": 1782046800, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/136720" - }, - { - "platform": "AtCoder", - "title": "AtCoder Heuristic Contest 067", - "start_time": 1782036000, - "end_time": 1782050400, - "status": "finished", - "url": "https://atcoder.jp/contests/ahc067" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/22 16:00start", - "start_time": 1782111600, - "end_time": 1782115200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260622_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/22 16:00start", - "start_time": 1782111600, - "end_time": 1782115200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260622_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/22 18:00start", - "start_time": 1782118800, - "end_time": 1782122400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260622_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/22 18:00start", - "start_time": 1782118800, - "end_time": 1782122400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260622_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0096 Beta", - "start_time": 1782126000, - "end_time": 1782129600, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0096" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/23 16:00start", - "start_time": 1782198000, - "end_time": 1782201600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260623_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/23 16:00start", - "start_time": 1782198000, - "end_time": 1782201600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260623_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/23 18:00start", - "start_time": 1782205200, - "end_time": 1782208800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260623_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/23 18:00start", - "start_time": 1782205200, - "end_time": 1782208800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260623_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0097 Beta", - "start_time": 1782212400, - "end_time": 1782216000, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0097" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/24 16:00start", - "start_time": 1782284400, - "end_time": 1782288000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260624_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/24 16:00start", - "start_time": 1782284400, - "end_time": 1782288000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260624_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/24 18:00start", - "start_time": 1782291600, - "end_time": 1782295200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260624_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/24 18:00start", - "start_time": 1782291600, - "end_time": 1782295200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260624_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0098 Beta", - "start_time": 1782298800, - "end_time": 1782302400, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0098" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/25 16:00start", - "start_time": 1782370800, - "end_time": 1782374400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260625_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/25 16:00start", - "start_time": 1782370800, - "end_time": 1782374400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260625_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/25 18:00start", - "start_time": 1782378000, - "end_time": 1782381600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260625_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/25 18:00start", - "start_time": 1782378000, - "end_time": 1782381600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260625_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0099 Beta", - "start_time": 1782385200, - "end_time": 1782388800, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0099" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/26 16:00start", - "start_time": 1782457200, - "end_time": 1782460800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260626_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/26 16:00start", - "start_time": 1782457200, - "end_time": 1782460800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260626_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/26 18:00start", - "start_time": 1782464400, - "end_time": 1782468000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260626_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/26 18:00start", - "start_time": 1782464400, - "end_time": 1782468000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260626_2" - }, - { - "platform": "Nowcoder", - "title": "牛客小白月赛134", - "start_time": 1782471600, - "end_time": 1782478800, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/137072" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0100 Beta", - "start_time": 1782471600, - "end_time": 1782480600, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0100" - }, - { - "platform": "AtCoder", - "title": "第七回日本最強プログラマー学生選手権~Advance~ -予選- (AtCoder Beginner Contest 464)", - "start_time": 1782561600, - "end_time": 1782567600, - "status": "finished", - "url": "https://atcoder.jp/contests/abc464" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round 1105 (Div. 1)", - "start_time": 1782570900, - "end_time": 1782579900, - "status": "finished", - "url": "https://codeforces.com/contests/2239" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round 1105 (Div. 2)", - "start_time": 1782570900, - "end_time": 1782579900, - "status": "finished", - "url": "https://codeforces.com/contests/2240" - }, - { - "platform": "Nowcoder", - "title": "牛客周赛 Round 150", - "start_time": 1782644400, - "end_time": 1782651600, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/137073" - }, - { - "platform": "AtCoder", - "title": "AtCoder Regular Contest 223", - "start_time": 1782648000, - "end_time": 1782655200, - "status": "finished", - "url": "https://atcoder.jp/contests/arc223" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round 1106 (Div. 2)", - "start_time": 1782657300, - "end_time": 1782664500, - "status": "finished", - "url": "https://codeforces.com/contests/2238" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/29 16:00start", - "start_time": 1782716400, - "end_time": 1782720000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260629_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/29 16:00start", - "start_time": 1782716400, - "end_time": 1782720000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260629_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/29 18:00start", - "start_time": 1782723600, - "end_time": 1782727200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260629_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/29 18:00start", - "start_time": 1782723600, - "end_time": 1782727200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260629_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0101 Beta", - "start_time": 1782730800, - "end_time": 1782734400, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0101" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/30 16:00start", - "start_time": 1782802800, - "end_time": 1782806400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260630_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/30 16:00start", - "start_time": 1782802800, - "end_time": 1782806400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260630_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/06/30 18:00start", - "start_time": 1782810000, - "end_time": 1782813600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260630_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/06/30 18:00start", - "start_time": 1782810000, - "end_time": 1782813600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260630_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0102 Beta", - "start_time": 1782817200, - "end_time": 1782820800, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0102" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round 1107 (Div. 3)", - "start_time": 1782830100, - "end_time": 1782838200, - "status": "finished", - "url": "https://codeforces.com/contests/2241" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/01 16:00start", - "start_time": 1782889200, - "end_time": 1782892800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260701_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/01 16:00start", - "start_time": 1782889200, - "end_time": 1782892800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260701_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/01 18:00start", - "start_time": 1782896400, - "end_time": 1782900000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260701_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/01 18:00start", - "start_time": 1782896400, - "end_time": 1782900000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260701_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0103 Beta", - "start_time": 1782903600, - "end_time": 1782907200, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0103" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/02 16:00start", - "start_time": 1782975600, - "end_time": 1782979200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260702_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/02 16:00start", - "start_time": 1782975600, - "end_time": 1782979200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260702_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/02 18:00start", - "start_time": 1782982800, - "end_time": 1782986400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260702_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/02 18:00start", - "start_time": 1782982800, - "end_time": 1782986400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260702_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0104 Beta", - "start_time": 1782990000, - "end_time": 1782993600, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0104" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/03 16:00start", - "start_time": 1783062000, - "end_time": 1783065600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260703_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/03 16:00start", - "start_time": 1783062000, - "end_time": 1783065600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260703_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/03 18:00start", - "start_time": 1783069200, - "end_time": 1783072800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260703_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/03 18:00start", - "start_time": 1783069200, - "end_time": 1783072800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260703_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0105 Beta", - "start_time": 1783076400, - "end_time": 1783080000, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0105" - }, - { - "platform": "Nowcoder", - "title": "牛客小白月赛135", - "start_time": 1783076400, - "end_time": 1783083600, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/137264" - }, - { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 465", - "start_time": 1783166400, - "end_time": 1783172400, - "status": "finished", - "url": "https://atcoder.jp/contests/abc465" - }, - { - "platform": "Nowcoder", - "title": "牛客周赛 Round 151", - "start_time": 1783249200, - "end_time": 1783256400, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/137267" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/06 16:00start", - "start_time": 1783321200, - "end_time": 1783324800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260706_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/06 16:00start", - "start_time": 1783321200, - "end_time": 1783324800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260706_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/06 18:00start", - "start_time": 1783328400, - "end_time": 1783332000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260706_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/06 18:00start", - "start_time": 1783328400, - "end_time": 1783332000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260706_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0106 Beta", - "start_time": 1783335600, - "end_time": 1783339200, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0106" - }, - { - "platform": "Codeforces", - "title": "Educational Codeforces Round 192 (Rated for Div. 2)", - "start_time": 1783348500, - "end_time": 1783355700, - "status": "finished", - "url": "https://codeforces.com/contests/2242" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/07 16:00start", - "start_time": 1783407600, - "end_time": 1783411200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260707_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/07 16:00start", - "start_time": 1783407600, - "end_time": 1783411200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260707_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/07 18:00start", - "start_time": 1783414800, - "end_time": 1783418400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260707_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/07 18:00start", - "start_time": 1783414800, - "end_time": 1783418400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260707_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0107 Beta", - "start_time": 1783422000, - "end_time": 1783425600, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0107" - }, - { - "platform": "UOJ", - "title": "UOJ Long Round #4", - "start_time": 1783216800, - "end_time": 1783432800, - "status": "finished", - "url": "https://uoj.ac/contest/108" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/08 16:00start", - "start_time": 1783494000, - "end_time": 1783497600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260708_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/08 16:00start", - "start_time": 1783494000, - "end_time": 1783497600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260708_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/08 18:00start", - "start_time": 1783501200, - "end_time": 1783504800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260708_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/08 18:00start", - "start_time": 1783501200, - "end_time": 1783504800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260708_2" - }, - { - "platform": "AtCoder", - "title": "World Tour Finals 2026 Heuristic", - "start_time": 1783382400, - "end_time": 1783504800, - "status": "finished", - "url": "https://atcoder.jp/contests/awtf2026heuristic" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0108 Beta", - "start_time": 1783508400, - "end_time": 1783512000, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0108" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/09 16:00start", - "start_time": 1783580400, - "end_time": 1783584000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260709_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/09 16:00start", - "start_time": 1783580400, - "end_time": 1783584000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260709_1" - }, - { - "platform": "AtCoder", - "title": "World Tour Finals 2026 Algorithm", - "start_time": 1783562400, - "end_time": 1783587600, - "status": "finished", - "url": "https://atcoder.jp/contests/awtf2026algo" - }, - { - "platform": "AtCoder", - "title": "World Tour Finals 2026 Algorithm(Open Contest)", - "start_time": 1783562400, - "end_time": 1783587600, - "status": "finished", - "url": "https://atcoder.jp/contests/awtf2026algo-open" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/09 18:00start", - "start_time": 1783587600, - "end_time": 1783591200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260709_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/09 18:00start", - "start_time": 1783587600, - "end_time": 1783591200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260709_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0109 Beta", - "start_time": 1783594800, - "end_time": 1783598400, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0109" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/10 16:00start", - "start_time": 1783666800, - "end_time": 1783670400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260710_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/10 16:00start", - "start_time": 1783666800, - "end_time": 1783670400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260710_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/10 18:00start", - "start_time": 1783674000, - "end_time": 1783677600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260710_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/10 18:00start", - "start_time": 1783674000, - "end_time": 1783677600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260710_2" - }, - { - "platform": "UOJ", - "title": "UOJ NOI Round #10 笔试", - "start_time": 1783681200, - "end_time": 1783683000, - "status": "finished", - "url": "https://uoj.ac/contest/109" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0110 Beta", - "start_time": 1783681200, - "end_time": 1783684800, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0110" - }, - { - "platform": "Nowcoder", - "title": "牛客挑战赛90", - "start_time": 1783681200, - "end_time": 1783692000, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/137418" - }, - { - "platform": "UOJ", - "title": "UOJ NOI Round #10 Day1", - "start_time": 1783729800, - "end_time": 1783748400, - "status": "finished", - "url": "https://uoj.ac/contest/110" - }, - { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 466", - "start_time": 1783771200, - "end_time": 1783777200, - "status": "finished", - "url": "https://atcoder.jp/contests/abc466" - }, - { - "platform": "UOJ", - "title": "UOJ NOI Round #10 Day2", - "start_time": 1783816200, - "end_time": 1783834200, - "status": "finished", - "url": "https://uoj.ac/contest/111" - }, - { - "platform": "Nowcoder", - "title": "牛客周赛 Round 152", - "start_time": 1783854000, - "end_time": 1783861200, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/137448" - }, - { - "platform": "AtCoder", - "title": "AtCoder Regular Contest-- 224", - "start_time": 1783857600, - "end_time": 1783864800, - "status": "finished", - "url": "https://atcoder.jp/contests/arc224" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round 1108 (Div. 2)", - "start_time": 1783866900, - "end_time": 1783875000, - "status": "finished", - "url": "https://codeforces.com/contests/2246" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/13 16:00start", - "start_time": 1783926000, - "end_time": 1783929600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260713_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/13 16:00start", - "start_time": 1783926000, - "end_time": 1783929600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260713_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/13 18:00start", - "start_time": 1783933200, - "end_time": 1783936800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260713_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/13 18:00start", - "start_time": 1783933200, - "end_time": 1783936800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260713_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0111 Beta", - "start_time": 1783940400, - "end_time": 1783944000, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0111" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/14 16:00start", - "start_time": 1784012400, - "end_time": 1784016000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260714_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/14 16:00start", - "start_time": 1784012400, - "end_time": 1784016000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260714_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/14 18:00start", - "start_time": 1784019600, - "end_time": 1784023200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260714_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/14 18:00start", - "start_time": 1784019600, - "end_time": 1784023200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260714_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0112 Beta", - "start_time": 1784026800, - "end_time": 1784030400, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0112" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round 1109 (Div. 3)", - "start_time": 1784039700, - "end_time": 1784047800, - "status": "finished", - "url": "https://codeforces.com/contests/2244" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/15 16:00start", - "start_time": 1784098800, - "end_time": 1784102400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260715_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/15 16:00start", - "start_time": 1784098800, - "end_time": 1784102400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260715_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/15 18:00start", - "start_time": 1784106000, - "end_time": 1784109600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260715_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/15 18:00start", - "start_time": 1784106000, - "end_time": 1784109600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260715_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0113 Beta", - "start_time": 1784113200, - "end_time": 1784116800, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0113" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/16 16:00start", - "start_time": 1784185200, - "end_time": 1784188800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260716_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/16 16:00start", - "start_time": 1784185200, - "end_time": 1784188800, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260716_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/16 18:00start", - "start_time": 1784192400, - "end_time": 1784196000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260716_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/16 18:00start", - "start_time": 1784192400, - "end_time": 1784196000, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260716_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0114 Beta", - "start_time": 1784199600, - "end_time": 1784203200, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0114" - }, - { - "platform": "Codeforces", - "title": "Spectral::Cup 2026 Round 3 (Codeforces Round 1110, Div. 1 + Div. 2)", - "start_time": 1784213100, - "end_time": 1784222100, - "status": "finished", - "url": "https://codeforces.com/contests/2245" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/17 16:00start", - "start_time": 1784271600, - "end_time": 1784275200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260717_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/17 16:00start", - "start_time": 1784271600, - "end_time": 1784275200, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260717_1" - }, - { - "platform": "Nowcoder", - "title": "2026牛客暑期多校训练营1", - "start_time": 1784260800, - "end_time": 1784278800, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/133876" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/17 18:00start", - "start_time": 1784278800, - "end_time": 1784282400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260717_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/17 18:00start", - "start_time": 1784278800, - "end_time": 1784282400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260717_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Weekday Contest 0115 Beta", - "start_time": 1784286000, - "end_time": 1784289600, - "status": "finished", - "url": "https://atcoder.jp/contests/awc0115" - }, - { - "platform": "AtCoder", - "title": "estie プログラミングコンテスト2026 (AtCoder Heuristic Contest 068)", - "start_time": 1784354400, - "end_time": 1784368800, - "status": "finished", - "url": "https://atcoder.jp/contests/ahc068" - }, - { - "platform": "AtCoder", - "title": "AtCoder Beginner Contest 467", - "start_time": 1784376000, - "end_time": 1784382000, - "status": "finished", - "url": "https://atcoder.jp/contests/abc467" - }, - { - "platform": "Codeforces", - "title": "Codeforces Round 1111 (Div. 2)", - "start_time": 1784385300, - "end_time": 1784392500, - "status": "finished", - "url": "https://codeforces.com/contests/2247" - }, - { - "platform": "Nowcoder", - "title": "牛客周赛 Round 153", - "start_time": 1784458800, - "end_time": 1784466000, - "status": "finished", - "url": "https://ac.nowcoder.com/acm/contest/137561" - }, - { - "platform": "AtCoder", - "title": "AtCoder Regular Contest 225", - "start_time": 1784462400, - "end_time": 1784469600, - "status": "finished", - "url": "https://atcoder.jp/contests/arc225" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/20 16:00start", - "start_time": 1784530800, - "end_time": 1784534400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260720_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/20 16:00start", - "start_time": 1784530800, - "end_time": 1784534400, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260720_1" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training ALL 2026/07/20 18:00start", - "start_time": 1784538000, - "end_time": 1784541600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_all_20260720_2" - }, - { - "platform": "AtCoder", - "title": "AtCoder Daily Training EASY 2026/07/20 18:00start", - "start_time": 1784538000, - "end_time": 1784541600, - "status": "finished", - "url": "https://atcoder.jp/contests/adt_easy_20260720_2" - } -] \ No newline at end of file +{ + "generated_at": 1784551054, + "contests": [ + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 463", + "start_time": 1781956800, + "end_time": 1781962800, + "status": "finished", + "url": "https://atcoder.jp/contests/abc463" + }, + { + "platform": "Nowcoder", + "title": "牛客周赛 Round 149", + "start_time": 1782039600, + "end_time": 1782046800, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/136720" + }, + { + "platform": "AtCoder", + "title": "AtCoder Heuristic Contest 067", + "start_time": 1782036000, + "end_time": 1782050400, + "status": "finished", + "url": "https://atcoder.jp/contests/ahc067" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/22 16:00start", + "start_time": 1782111600, + "end_time": 1782115200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260622_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/22 16:00start", + "start_time": 1782111600, + "end_time": 1782115200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260622_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/22 18:00start", + "start_time": 1782118800, + "end_time": 1782122400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260622_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/22 18:00start", + "start_time": 1782118800, + "end_time": 1782122400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260622_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0096 Beta", + "start_time": 1782126000, + "end_time": 1782129600, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0096" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/23 16:00start", + "start_time": 1782198000, + "end_time": 1782201600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260623_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/23 16:00start", + "start_time": 1782198000, + "end_time": 1782201600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260623_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/23 18:00start", + "start_time": 1782205200, + "end_time": 1782208800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260623_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/23 18:00start", + "start_time": 1782205200, + "end_time": 1782208800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260623_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0097 Beta", + "start_time": 1782212400, + "end_time": 1782216000, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0097" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/24 16:00start", + "start_time": 1782284400, + "end_time": 1782288000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260624_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/24 16:00start", + "start_time": 1782284400, + "end_time": 1782288000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260624_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/24 18:00start", + "start_time": 1782291600, + "end_time": 1782295200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260624_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/24 18:00start", + "start_time": 1782291600, + "end_time": 1782295200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260624_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0098 Beta", + "start_time": 1782298800, + "end_time": 1782302400, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0098" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/25 16:00start", + "start_time": 1782370800, + "end_time": 1782374400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260625_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/25 16:00start", + "start_time": 1782370800, + "end_time": 1782374400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260625_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/25 18:00start", + "start_time": 1782378000, + "end_time": 1782381600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260625_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/25 18:00start", + "start_time": 1782378000, + "end_time": 1782381600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260625_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0099 Beta", + "start_time": 1782385200, + "end_time": 1782388800, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0099" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/26 16:00start", + "start_time": 1782457200, + "end_time": 1782460800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260626_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/26 16:00start", + "start_time": 1782457200, + "end_time": 1782460800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260626_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/26 18:00start", + "start_time": 1782464400, + "end_time": 1782468000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260626_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/26 18:00start", + "start_time": 1782464400, + "end_time": 1782468000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260626_2" + }, + { + "platform": "Nowcoder", + "title": "牛客小白月赛134", + "start_time": 1782471600, + "end_time": 1782478800, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/137072" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0100 Beta", + "start_time": 1782471600, + "end_time": 1782480600, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0100" + }, + { + "platform": "AtCoder", + "title": "第七回日本最強プログラマー学生選手権~Advance~ -予選- (AtCoder Beginner Contest 464)", + "start_time": 1782561600, + "end_time": 1782567600, + "status": "finished", + "url": "https://atcoder.jp/contests/abc464" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round 1105 (Div. 1)", + "start_time": 1782570900, + "end_time": 1782579900, + "status": "finished", + "url": "https://codeforces.com/contests/2239" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round 1105 (Div. 2)", + "start_time": 1782570900, + "end_time": 1782579900, + "status": "finished", + "url": "https://codeforces.com/contests/2240" + }, + { + "platform": "Nowcoder", + "title": "牛客周赛 Round 150", + "start_time": 1782644400, + "end_time": 1782651600, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/137073" + }, + { + "platform": "AtCoder", + "title": "AtCoder Regular Contest 223", + "start_time": 1782648000, + "end_time": 1782655200, + "status": "finished", + "url": "https://atcoder.jp/contests/arc223" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round 1106 (Div. 2)", + "start_time": 1782657300, + "end_time": 1782664500, + "status": "finished", + "url": "https://codeforces.com/contests/2238" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/29 16:00start", + "start_time": 1782716400, + "end_time": 1782720000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260629_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/29 16:00start", + "start_time": 1782716400, + "end_time": 1782720000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260629_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/29 18:00start", + "start_time": 1782723600, + "end_time": 1782727200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260629_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/29 18:00start", + "start_time": 1782723600, + "end_time": 1782727200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260629_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0101 Beta", + "start_time": 1782730800, + "end_time": 1782734400, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0101" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/30 16:00start", + "start_time": 1782802800, + "end_time": 1782806400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260630_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/30 16:00start", + "start_time": 1782802800, + "end_time": 1782806400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260630_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/06/30 18:00start", + "start_time": 1782810000, + "end_time": 1782813600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260630_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/06/30 18:00start", + "start_time": 1782810000, + "end_time": 1782813600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260630_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0102 Beta", + "start_time": 1782817200, + "end_time": 1782820800, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0102" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round 1107 (Div. 3)", + "start_time": 1782830100, + "end_time": 1782838200, + "status": "finished", + "url": "https://codeforces.com/contests/2241" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/01 16:00start", + "start_time": 1782889200, + "end_time": 1782892800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260701_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/01 16:00start", + "start_time": 1782889200, + "end_time": 1782892800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260701_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/01 18:00start", + "start_time": 1782896400, + "end_time": 1782900000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260701_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/01 18:00start", + "start_time": 1782896400, + "end_time": 1782900000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260701_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0103 Beta", + "start_time": 1782903600, + "end_time": 1782907200, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0103" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/02 16:00start", + "start_time": 1782975600, + "end_time": 1782979200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260702_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/02 16:00start", + "start_time": 1782975600, + "end_time": 1782979200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260702_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/02 18:00start", + "start_time": 1782982800, + "end_time": 1782986400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260702_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/02 18:00start", + "start_time": 1782982800, + "end_time": 1782986400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260702_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0104 Beta", + "start_time": 1782990000, + "end_time": 1782993600, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0104" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/03 16:00start", + "start_time": 1783062000, + "end_time": 1783065600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260703_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/03 16:00start", + "start_time": 1783062000, + "end_time": 1783065600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260703_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/03 18:00start", + "start_time": 1783069200, + "end_time": 1783072800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260703_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/03 18:00start", + "start_time": 1783069200, + "end_time": 1783072800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260703_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0105 Beta", + "start_time": 1783076400, + "end_time": 1783080000, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0105" + }, + { + "platform": "Nowcoder", + "title": "牛客小白月赛135", + "start_time": 1783076400, + "end_time": 1783083600, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/137264" + }, + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 465", + "start_time": 1783166400, + "end_time": 1783172400, + "status": "finished", + "url": "https://atcoder.jp/contests/abc465" + }, + { + "platform": "Nowcoder", + "title": "牛客周赛 Round 151", + "start_time": 1783249200, + "end_time": 1783256400, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/137267" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/06 16:00start", + "start_time": 1783321200, + "end_time": 1783324800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260706_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/06 16:00start", + "start_time": 1783321200, + "end_time": 1783324800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260706_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/06 18:00start", + "start_time": 1783328400, + "end_time": 1783332000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260706_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/06 18:00start", + "start_time": 1783328400, + "end_time": 1783332000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260706_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0106 Beta", + "start_time": 1783335600, + "end_time": 1783339200, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0106" + }, + { + "platform": "Codeforces", + "title": "Educational Codeforces Round 192 (Rated for Div. 2)", + "start_time": 1783348500, + "end_time": 1783355700, + "status": "finished", + "url": "https://codeforces.com/contests/2242" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/07 16:00start", + "start_time": 1783407600, + "end_time": 1783411200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260707_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/07 16:00start", + "start_time": 1783407600, + "end_time": 1783411200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260707_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/07 18:00start", + "start_time": 1783414800, + "end_time": 1783418400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260707_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/07 18:00start", + "start_time": 1783414800, + "end_time": 1783418400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260707_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0107 Beta", + "start_time": 1783422000, + "end_time": 1783425600, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0107" + }, + { + "platform": "UOJ", + "title": "UOJ Long Round #4", + "start_time": 1783216800, + "end_time": 1783432800, + "status": "finished", + "url": "https://uoj.ac/contest/108" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/08 16:00start", + "start_time": 1783494000, + "end_time": 1783497600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260708_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/08 16:00start", + "start_time": 1783494000, + "end_time": 1783497600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260708_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/08 18:00start", + "start_time": 1783501200, + "end_time": 1783504800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260708_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/08 18:00start", + "start_time": 1783501200, + "end_time": 1783504800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260708_2" + }, + { + "platform": "AtCoder", + "title": "World Tour Finals 2026 Heuristic", + "start_time": 1783382400, + "end_time": 1783504800, + "status": "finished", + "url": "https://atcoder.jp/contests/awtf2026heuristic" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0108 Beta", + "start_time": 1783508400, + "end_time": 1783512000, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0108" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/09 16:00start", + "start_time": 1783580400, + "end_time": 1783584000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260709_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/09 16:00start", + "start_time": 1783580400, + "end_time": 1783584000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260709_1" + }, + { + "platform": "AtCoder", + "title": "World Tour Finals 2026 Algorithm", + "start_time": 1783562400, + "end_time": 1783587600, + "status": "finished", + "url": "https://atcoder.jp/contests/awtf2026algo" + }, + { + "platform": "AtCoder", + "title": "World Tour Finals 2026 Algorithm(Open Contest)", + "start_time": 1783562400, + "end_time": 1783587600, + "status": "finished", + "url": "https://atcoder.jp/contests/awtf2026algo-open" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/09 18:00start", + "start_time": 1783587600, + "end_time": 1783591200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260709_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/09 18:00start", + "start_time": 1783587600, + "end_time": 1783591200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260709_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0109 Beta", + "start_time": 1783594800, + "end_time": 1783598400, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0109" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/10 16:00start", + "start_time": 1783666800, + "end_time": 1783670400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260710_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/10 16:00start", + "start_time": 1783666800, + "end_time": 1783670400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260710_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/10 18:00start", + "start_time": 1783674000, + "end_time": 1783677600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260710_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/10 18:00start", + "start_time": 1783674000, + "end_time": 1783677600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260710_2" + }, + { + "platform": "UOJ", + "title": "UOJ NOI Round #10 笔试", + "start_time": 1783681200, + "end_time": 1783683000, + "status": "finished", + "url": "https://uoj.ac/contest/109" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0110 Beta", + "start_time": 1783681200, + "end_time": 1783684800, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0110" + }, + { + "platform": "Nowcoder", + "title": "牛客挑战赛90", + "start_time": 1783681200, + "end_time": 1783692000, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/137418" + }, + { + "platform": "UOJ", + "title": "UOJ NOI Round #10 Day1", + "start_time": 1783729800, + "end_time": 1783748400, + "status": "finished", + "url": "https://uoj.ac/contest/110" + }, + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 466", + "start_time": 1783771200, + "end_time": 1783777200, + "status": "finished", + "url": "https://atcoder.jp/contests/abc466" + }, + { + "platform": "UOJ", + "title": "UOJ NOI Round #10 Day2", + "start_time": 1783816200, + "end_time": 1783834200, + "status": "finished", + "url": "https://uoj.ac/contest/111" + }, + { + "platform": "Nowcoder", + "title": "牛客周赛 Round 152", + "start_time": 1783854000, + "end_time": 1783861200, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/137448" + }, + { + "platform": "AtCoder", + "title": "AtCoder Regular Contest-- 224", + "start_time": 1783857600, + "end_time": 1783864800, + "status": "finished", + "url": "https://atcoder.jp/contests/arc224" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round 1108 (Div. 2)", + "start_time": 1783866900, + "end_time": 1783875000, + "status": "finished", + "url": "https://codeforces.com/contests/2246" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/13 16:00start", + "start_time": 1783926000, + "end_time": 1783929600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260713_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/13 16:00start", + "start_time": 1783926000, + "end_time": 1783929600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260713_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/13 18:00start", + "start_time": 1783933200, + "end_time": 1783936800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260713_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/13 18:00start", + "start_time": 1783933200, + "end_time": 1783936800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260713_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0111 Beta", + "start_time": 1783940400, + "end_time": 1783944000, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0111" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/14 16:00start", + "start_time": 1784012400, + "end_time": 1784016000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260714_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/14 16:00start", + "start_time": 1784012400, + "end_time": 1784016000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260714_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/14 18:00start", + "start_time": 1784019600, + "end_time": 1784023200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260714_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/14 18:00start", + "start_time": 1784019600, + "end_time": 1784023200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260714_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0112 Beta", + "start_time": 1784026800, + "end_time": 1784030400, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0112" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round 1109 (Div. 3)", + "start_time": 1784039700, + "end_time": 1784047800, + "status": "finished", + "url": "https://codeforces.com/contests/2244" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/15 16:00start", + "start_time": 1784098800, + "end_time": 1784102400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260715_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/15 16:00start", + "start_time": 1784098800, + "end_time": 1784102400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260715_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/15 18:00start", + "start_time": 1784106000, + "end_time": 1784109600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260715_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/15 18:00start", + "start_time": 1784106000, + "end_time": 1784109600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260715_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0113 Beta", + "start_time": 1784113200, + "end_time": 1784116800, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0113" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/16 16:00start", + "start_time": 1784185200, + "end_time": 1784188800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260716_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/16 16:00start", + "start_time": 1784185200, + "end_time": 1784188800, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260716_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/16 18:00start", + "start_time": 1784192400, + "end_time": 1784196000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260716_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/16 18:00start", + "start_time": 1784192400, + "end_time": 1784196000, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260716_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0114 Beta", + "start_time": 1784199600, + "end_time": 1784203200, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0114" + }, + { + "platform": "Codeforces", + "title": "Spectral::Cup 2026 Round 3 (Codeforces Round 1110, Div. 1 + Div. 2)", + "start_time": 1784213100, + "end_time": 1784222100, + "status": "finished", + "url": "https://codeforces.com/contests/2245" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/17 16:00start", + "start_time": 1784271600, + "end_time": 1784275200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260717_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/17 16:00start", + "start_time": 1784271600, + "end_time": 1784275200, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260717_1" + }, + { + "platform": "Nowcoder", + "title": "2026牛客暑期多校训练营1", + "start_time": 1784260800, + "end_time": 1784278800, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/133876" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/17 18:00start", + "start_time": 1784278800, + "end_time": 1784282400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260717_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/17 18:00start", + "start_time": 1784278800, + "end_time": 1784282400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260717_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0115 Beta", + "start_time": 1784286000, + "end_time": 1784289600, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0115" + }, + { + "platform": "AtCoder", + "title": "estie プログラミングコンテスト2026 (AtCoder Heuristic Contest 068)", + "start_time": 1784354400, + "end_time": 1784368800, + "status": "finished", + "url": "https://atcoder.jp/contests/ahc068" + }, + { + "platform": "AtCoder", + "title": "AtCoder Beginner Contest 467", + "start_time": 1784376000, + "end_time": 1784382000, + "status": "finished", + "url": "https://atcoder.jp/contests/abc467" + }, + { + "platform": "Codeforces", + "title": "Codeforces Round 1111 (Div. 2)", + "start_time": 1784385300, + "end_time": 1784392500, + "status": "finished", + "url": "https://codeforces.com/contests/2247" + }, + { + "platform": "Nowcoder", + "title": "牛客周赛 Round 153", + "start_time": 1784458800, + "end_time": 1784466000, + "status": "finished", + "url": "https://ac.nowcoder.com/acm/contest/137561" + }, + { + "platform": "AtCoder", + "title": "AtCoder Regular Contest 225", + "start_time": 1784462400, + "end_time": 1784469600, + "status": "finished", + "url": "https://atcoder.jp/contests/arc225" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/20 16:00start", + "start_time": 1784530800, + "end_time": 1784534400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260720_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/20 16:00start", + "start_time": 1784530800, + "end_time": 1784534400, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260720_1" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training ALL 2026/07/20 18:00start", + "start_time": 1784538000, + "end_time": 1784541600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_all_20260720_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Daily Training EASY 2026/07/20 18:00start", + "start_time": 1784538000, + "end_time": 1784541600, + "status": "finished", + "url": "https://atcoder.jp/contests/adt_easy_20260720_2" + }, + { + "platform": "AtCoder", + "title": "AtCoder Weekday Contest 0116 Beta", + "start_time": 1784545200, + "end_time": 1784548800, + "status": "finished", + "url": "https://atcoder.jp/contests/awc0116" + } + ] +} \ No newline at end of file diff --git a/fetch_contests.py b/fetch_contests.py index 5e0899e..ed1563e 100644 --- a/fetch_contests.py +++ b/fetch_contests.py @@ -54,6 +54,12 @@ def filter_recent_finished(contests, days=30): if contest["status"] == "finished" and contest["end_time"] >= earliest_end_ts ] +def contest_payload(contests, generated_at): + return { + "generated_at": generated_at, + "contests": contests + } + HEADERS = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/126.0 Safari/537.36" @@ -224,6 +230,7 @@ def fetch_nowcoder(include_all=False, min_end_time=None): return [] def main(): + generated_at = now_ts() all_contests = [] all_contests.extend(fetch_codeforces()) all_contests.extend(fetch_atcoder()) @@ -234,7 +241,7 @@ def main(): # 直接写入仓库根目录 with open("contests.json", "w", encoding="utf-8") as f: - json.dump(all_contests, f, ensure_ascii=False, indent=2) + json.dump(contest_payload(all_contests, generated_at), f, ensure_ascii=False, indent=2) recent_finished_contests = [] recent_finished_min_end_time = recent_finished_cutoff() @@ -247,7 +254,7 @@ def main(): recent_finished_contests.sort(key=lambda x: x["end_time"]) with open("contests_all.json", "w", encoding="utf-8") as f: - json.dump(recent_finished_contests, f, ensure_ascii=False, indent=2) + json.dump(contest_payload(recent_finished_contests, generated_at), f, ensure_ascii=False, indent=2) print(f"Total upcoming contests: {len(all_contests)}") print(f"Total contests finished in last 30 days: {len(recent_finished_contests)}") diff --git a/server/index.php b/server/index.php index 70bcb26..4f7b7b0 100644 --- a/server/index.php +++ b/server/index.php @@ -24,6 +24,7 @@ $translations = [ 'ended' => '已结束', 'running' => '进行中', 'timezone_label' => '时区', + 'last_updated_label' => '最后更新时间', 'day' => '天', 'hour' => '时', 'minute' => '分', @@ -42,6 +43,7 @@ $translations = [ 'ended' => 'Ended', 'running' => 'Running', 'timezone_label' => 'Time zone', + 'last_updated_label' => 'Last updated', 'day' => 'd', 'hour' => 'h', 'minute' => 'm', @@ -131,17 +133,40 @@ function fetch_and_cache($url, $cache_file, $ttl) { return $json; } +function parse_contest_payload($json) { + $data = json_decode($json, true); + if (!is_array($data)) { + return false; + } + + if (isset($data['contests']) && is_array($data['contests'])) { + return [ + 'generated_at' => isset($data['generated_at']) ? (int)$data['generated_at'] : 0, + 'contests' => $data['contests'] + ]; + } + + return [ + 'generated_at' => 0, + 'contests' => $data + ]; +} + // 获取赛事 JSON $contests_json = fetch_and_cache(JSON_URL, CACHE_FILE, CACHE_TTL); if ($contests_json === false) { $contests = []; + $contests_generated_at = 0; $error_msg = $t['load_error']; } else { - $contests = json_decode($contests_json, true); - if (!is_array($contests)) { + $contests_payload = parse_contest_payload($contests_json); + if ($contests_payload === false) { $contests = []; + $contests_generated_at = 0; $error_msg = $t['load_error']; } else { + $contests = $contests_payload['contests']; + $contests_generated_at = $contests_payload['generated_at']; $error_msg = ''; } } @@ -149,17 +174,23 @@ if ($contests_json === false) { $finished_contests_json = fetch_and_cache(FINISHED_JSON_URL, FINISHED_CACHE_FILE, CACHE_TTL); if ($finished_contests_json === false) { $finished_contests = []; + $finished_contests_generated_at = 0; $finished_error_msg = $t['finished_load_error']; } else { - $finished_contests = json_decode($finished_contests_json, true); - if (!is_array($finished_contests)) { + $finished_contests_payload = parse_contest_payload($finished_contests_json); + if ($finished_contests_payload === false) { $finished_contests = []; + $finished_contests_generated_at = 0; $finished_error_msg = $t['finished_load_error']; } else { + $finished_contests = $finished_contests_payload['contests']; + $finished_contests_generated_at = $finished_contests_payload['generated_at']; $finished_error_msg = ''; } } +$last_generated_at = max($contests_generated_at, $finished_contests_generated_at); + // ========== 平台样式映射 ========== $platform_class = [ 'Codeforces' => 'cf', @@ -173,10 +204,10 @@ function h($value) { } // 辅助函数:Unix 时间戳按当前时区格式化 -function format_time($ts, $timezone) { +function format_time($ts, $timezone, $include_seconds=false) { $date = new DateTime('@' . $ts); $date->setTimezone($timezone); - return $date->format('Y-m-d H:i'); + return $date->format($include_seconds ? 'Y-m-d H:i:s' : 'Y-m-d H:i'); } function platform_class_name($platform, $platform_class) { @@ -225,6 +256,9 @@ function contest_value($contest, $key, $default) {

📅

:
+ 0): ?> +
:
+

@@ -286,6 +320,7 @@ function contest_value($contest, $key, $default) { var translations = ; var serverLanguage = ; var serverTimezone = ; +var generatedAt = ; function cookieValue(name) { var parts = document.cookie ? document.cookie.split('; ') : []; @@ -353,10 +388,35 @@ function formatDateTime(ts) { return ''; } +function formatDateTimeWithSeconds(ts) { + if (window.Intl && Intl.DateTimeFormat) { + return new Intl.DateTimeFormat(serverLanguage === 'en' ? 'en-US' : 'zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false, + timeZone: serverTimezone + }).format(new Date(ts * 1000)); + } + return ''; +} + function updateTimes() { var timezoneLabel = document.getElementById('timezone-label'); if (timezoneLabel) timezoneLabel.textContent = serverTimezone; + var lastUpdated = document.getElementById('last-updated'); + if (lastUpdated) { + var generatedAtTs = parseInt(lastUpdated.getAttribute('data-generated-at') || generatedAt, 10); + var generatedAtText = formatDateTimeWithSeconds(generatedAtTs); + if (generatedAtText) { + lastUpdated.textContent = generatedAtText; + } + } + var els = document.querySelectorAll('.time'); els.forEach(function(el) { var start = parseInt(el.getAttribute('data-start'), 10);