Skip to content

About

Parse short Chinese & English schedule sentences (每周一三五早上7点跑步) into dates, times and repeat rules. Zero deps.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zh-schedule-parser

A small, dependency-free JavaScript library (ESM, with TypeScript types) that reads short Chinese and English schedule sentences and returns structured dates, times and repeat rules.

每周一三五早上7点跑步     → 跑步 · 07:00 · weekly on Mon/Wed/Fri
明天下午三点开会          → 开会 · tomorrow 15:00
每隔两天提醒我浇花        → 浇花 · every 2 days (flagged: could mean every 3)
8点吃药                  → 吃药 · 08:00 or 20:00? (it asks rather than guesses)
Gym every Monday and Thursday at 6:30am → Gym · weekly on Mon/Thu · 06:30

It is rule-based: no model, no network, and it gives the same answer every time. It works in Node 18+ and modern browsers.

Design rules

  1. Never guess an unclear time. "8点" or "at 8" could mean 08:00 or 20:00, so you get timeOptions: ["08:00", "20:00"] and time: null. The parser only picks one when the words settle it: 早上/下午/晚上, am/pm, a 24-hour time, or a task word such as 早饭 or dinner.
  2. Never turn an unsupported rhythm into a different one. "每小时喝水" keeps the task, drops the rhythm and adds the note unsupportedRepeat.
  3. Everything that is not a "when" is the title. Filler such as 提醒我, 帮我记一下 and "remind me to" is removed.

Install

It is not published to npm. Clone it, or copy src/ into your project:

git clone https://github.com/jackships/zh-schedule-parser.git
cd zh-schedule-parser
npm test
node examples/cli.js "每周一三五早上7点跑步" "明天下午3点开会,5点半取快递"

Usage

import { parse, parseMany, nextOccurrences } from "./src/index.js";

const now = new Date(2026, 9, 7, 10, 0); // Wed 2026-10-07 10:00, local time

parse("每周一三五早上7点跑步", { now });
// {
//   input: "每周一三五早上7点跑步",
//   title: "跑步",
//   date: "2026-10-09",            // first day it happens (Wednesday's 07:00 has already passed)
//   time: "07:00",
//   timeOptions: [],
//   repeat: { freq: "weekly", weekdays: [1, 3, 5] },   // 0 = Sunday … 6 = Saturday
//   endAfterDays: null, lead: null, duration: null, relativeMinutes: null,
//   alarm: false, dateExplicit: false, notes: []
// }

parseMany("明天下午3点开会,提前10分钟提醒我;下午5点半取快递", { now });
// [ { title: "开会",   date: "2026-10-08", time: "15:00", lead: 10, ... },
//   { title: "取快递", date: "2026-10-08", time: "17:30", ... } ]

nextOccurrences(parse("每个月第二个周二晚上7点读书会", { now }), { now, count: 3 });
// [ { date: "2026-10-13", time: "19:00" },
//   { date: "2026-11-10", time: "19:00" },
//   { date: "2026-12-08", time: "19:00" } ]

now defaults to the current time. Dates and times are wall-clock values in the runtime's local time zone. The tests pass in UTC, New York, Shanghai and Auckland.

What it understands

Chinese English
Days 今天 明天 后天 大后天 · 周五 / 这周五 / 下周五 / 下下周二 · 10月20号 · 15号 · 下个月5号 · 三天后 · 两周后 today, tomorrow, the day after tomorrow · Friday / next Friday · Oct 20 · 20 Oct · 12/3 (US order) · the 25th · in 3 days
Times 早上7点 · 下午三点 · 晚上十点半 · 九点一刻 · 三点三刻 · 3点45分 · 9:25 · 中午 · 凌晨两点 7pm · 6:30am · 18:30 · at 8 · noon · midnight · tonight at 9
Windows 三点到五点之间 (reminds at the start) 3 to 5pm · between 2 and 4pm
Weekly 每天 · 天天 · 每晚 · 每周一三五 · 每周二四 · 周一到周五 · 每周末 every day / night / morning · weekdays · every Monday and Thursday · Mondays
Other repeats 工作日 · 隔天 · 每三天 · 每隔两天 · 隔周六 · 每两周的周日 · 每月1号 · 每月月底 · 每月最后一个周五 · 每年3月8号 every other day · every 3 days · every other Saturday · every 2 weeks · the 1st of every month · the last Friday of every month · every year on June 12
Several times 早上8点、中午12点、晚上6点吃药 → three plans · 早中晚 / 早晚各一次 (suggested times, flagged) at 8am and 8pm · twice a day · three times a day
Relative 半小时后 · 20分钟后 · 一个小时后 in 20 minutes · in half an hour
Extras 提前10分钟提醒 (lead) · 读书20分钟 (duration) · 接下来7天 / 连续3周 (ends) · 从下周一开始 (start) · 闹钟 (alarm) 15 minutes early · for 30 minutes · for the next 5 days · starting Monday · set an alarm
Fixed holidays 元旦 · 情人节 · 劳动节 · 儿童节 · 教师节 · 国庆节 · 平安夜 · 圣诞节 (+ 前一天 / 后一天) Christmas (Eve) · New Year's (Eve) · Halloween · Valentine's (+ the day before / after)

Several plans in one message are split at ;, 。, "然后" or "then", and at a comma only when both sides say when and what. This keeps "早上8点、中午12点吃药" as one plan. A later clause without its own day shares the earlier clause's day, and an unclear hour after an earlier time on the same day takes the later reading ("3点开会,5点半取快递" gives 17:30, with the note timeFromContext).

Notes

Each plan has a notes array that tells a UI what to ask or show:

Note Meaning
vagueTime No concrete time (晚上, 周末, later, 吃完饭后). Check timeOptions when it is set.
rolledToTomorrow A bare time that has already passed today was moved to tomorrow.
weekdayIsToday "周三…" said on a Wednesday, so it means today.
unsupportedRepeat The rhythm was dropped (hourly, "until …", 每月 without a day).
suggestedTimes The times were proposed from 早中晚 / twice a day.
ambiguousInterval 每隔N天 was read as every N days. Some people mean every N+1.
endsAfterDays The repeat stops by itself (endAfterDays, counted from date).
timeFromContext An unclear hour was settled by the clause before it.
multipleTasks parse() only: the message held more than one plan. Use parseMany().

Not covered

  • Lunar dates (农历八月十五), lunar holidays (春节, 中秋) and the official Chinese holiday and 调休 calendar. workdays means Monday to Friday here.
  • Place or person triggers ("到公司时", "next time I see Sam").
  • Other time zones ("纽约时间9点").
  • Editing existing plans ("把跑步改到周二"). This library only reads new plans.

Test corpus

corpus/sentences.json holds 117 sentences (76 Chinese, 41 English) with the expected result for a fixed reference time. You can reuse it to test another parser in any language. npm test runs it together with the API tests (135 tests, built-in node:test, no dependencies).

中文说明

一个零依赖的 JavaScript 小库,把「每周一三五早上7点跑步」「明天下午三点开会」「每隔两天提醒我浇花」这类短句解析成结构化的日期、时间和重复规则,也支持英文。

  • 时间不清楚就不猜:"8点吃药"会返回 timeOptions: ["08:00", "20:00"],交给界面让用户选。
  • 不支持的节奏不硬套:"每小时喝水"会保留任务,去掉节奏,并加上 unsupportedRepeat 提示。
  • 能识别每天、每周几、工作日、隔天、每 N 天、隔周、每月几号、每月最后一个周五、每年几月几号,以及"提前10分钟"、"读书20分钟"、"接下来7天"、"从下周一开始"、"闹钟"等说法。
  • nextOccurrences() 可以算出接下来几次的具体日期。
  • 不支持农历、法定节假日和调休表、地点或人物触发。

测试语料在 corpus/sentences.json(117 句,其中中文 76 句),可以直接拿去测别的解析器。


The same approach powers the one-sentence reminders in Lili, an iOS planner (not on the App Store yet): https://y1y2u3u4.github.io/lili-site/

License

MIT © 2026 Jack Ships

About

Parse short Chinese & English schedule sentences (每周一三五早上7点跑步) into dates, times and repeat rules. Zero deps.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages