From bb9c7efbcc393101fdbd715d3c80124ec83231b0 Mon Sep 17 00:00:00 2001
From: pengzhendong <275331498@qq.com>
Date: Tue, 9 Jun 2026 17:18:42 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20disambiguate=20"X=E7=82=B9=E9=9B=B6Y"=20?=
 =?UTF-8?q?between=20time=20and=20decimal=20in=20Chinese=20ITN=20(#310)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

"五点零三" was incorrectly parsed as time 5:03 instead of decimal 5.03.

Fix: require "分" suffix or noon prefix (上午/下午/etc.) for time patterns
with zero-prefixed minutes (零一~零九). Without either, these are now
treated as decimals.

- Split minute.tsv: move 零X entries to new minute_zero.tsv
- Time tagger: 零X minutes without "分" only match with noon prefix

Examples:
  五点零三 => 5.03 (decimal, no context)
  五点零三分 => 5:03 (time, has 分)
  下午五点零三 => 5:03p.m. (time, has noon)
  八点三十 => 8:30 (time, unambiguous)
---
 itn/chinese/data/time/minute.tsv      |  9 ---------
 itn/chinese/data/time/minute_zero.tsv |  9 +++++++++
 itn/chinese/rules/time.py             | 21 +++++++++++++--------
 itn/chinese/test/data/time.txt        |  2 +-
 4 files changed, 23 insertions(+), 18 deletions(-)
 create mode 100644 itn/chinese/data/time/minute_zero.tsv

diff --git a/itn/chinese/data/time/minute.tsv b/itn/chinese/data/time/minute.tsv
index 66f97516..eced82f5 100644
--- a/itn/chinese/data/time/minute.tsv
+++ b/itn/chinese/data/time/minute.tsv
@@ -1,13 +1,4 @@
 半	30
-零一	01
-零二	02
-零三	03
-零四	04
-零五	05
-零六	06
-零七	07
-零八	08
-零九	09
 十	10
 十一	11
 十二	12
diff --git a/itn/chinese/data/time/minute_zero.tsv b/itn/chinese/data/time/minute_zero.tsv
new file mode 100644
index 00000000..59cd78af
--- /dev/null
+++ b/itn/chinese/data/time/minute_zero.tsv
@@ -0,0 +1,9 @@
+零一	01
+零二	02
+零三	03
+零四	04
+零五	05
+零六	06
+零七	07
+零八	08
+零九	09
diff --git a/itn/chinese/rules/time.py b/itn/chinese/rules/time.py
index 31d7c5ac..2e8d067b 100644
--- a/itn/chinese/rules/time.py
+++ b/itn/chinese/rules/time.py
@@ -29,19 +29,24 @@ def __init__(self):
     def build_tagger(self):
         h = string_file(get_abs_path("../itn/chinese/data/time/hour.tsv"))
         m = string_file(get_abs_path("../itn/chinese/data/time/minute.tsv"))
+        m_zero = string_file(get_abs_path("../itn/chinese/data/time/minute_zero.tsv"))
         s = string_file(get_abs_path("../itn/chinese/data/time/second.tsv"))
         noon = string_file(get_abs_path("../itn/chinese/data/time/noon.tsv"))
 
+        hour = insert('hour: "') + h + insert('"')
+        minute = insert(' minute: "') + m + delete("分").ques + insert('"')
+        minute |= insert(' minute: "') + m_zero + delete("分") + insert('"')
+        minute_zero_no_fen = insert(' minute: "') + m_zero + insert('"')
+        second = (insert(' second: "') + s + insert('"')).ques
+
         tagger = (
             (insert('noon: "') + noon + insert('" ')).ques
-            + insert('hour: "')
-            + h
-            + insert('"')
-            + insert(' minute: "')
-            + m
-            + delete("分").ques
-            + insert('"')
-            + (insert(' second: "') + s + insert('"')).ques
+            + hour + minute + second
+        )
+        # "X点零Y" without "分" requires noon prefix to disambiguate from decimal
+        tagger |= (
+            insert('noon: "') + noon + insert('" ')
+            + hour + minute_zero_no_fen + second
         )
         self.tagger = self.add_tokens(tagger)
 
diff --git a/itn/chinese/test/data/time.txt b/itn/chinese/test/data/time.txt
index 0aae787f..3b722ede 100644
--- a/itn/chinese/test/data/time.txt
+++ b/itn/chinese/test/data/time.txt
@@ -9,4 +9,4 @@
 八点零五分 => 8:05
 八点三十 => 8:30
 八点半 => 8:30
-时间上是零点十分登机,八点五分下飞机,八点三十去吃早饭.你是说八点零五分下飞机还是八点零五下飞机?我可能下午三点四十,或者上午十点半再或者下午三点四十一分去找你 => 时间上是00:10登机,8.5分下飞机,8:30去吃早饭.你是说8:05下飞机还是8:05下飞机?我可能3:40p.m.,或者10:30a.m.再或者3:41p.m.去找你
+时间上是零点十分登机,八点五分下飞机,八点三十去吃早饭.你是说八点零五分下飞机还是八点零五分下飞机?我可能下午三点四十,或者上午十点半再或者下午三点四十一分去找你 => 时间上是00:10登机,8.5分下飞机,8:30去吃早饭.你是说8:05下飞机还是8:05下飞机?我可能3:40p.m.,或者10:30a.m.再或者3:41p.m.去找你
