Skip to main content

whichtime_sys/dictionaries/
ja.rs

1//! Japanese (日本語) locale dictionaries
2
3use super::{CasualDateType, CasualTimeType, RelativeModifier, TimeUnit, Weekday};
4use phf::phf_map;
5
6/// Weekday dictionary
7pub static WEEKDAY_MAP: phf::Map<&'static str, Weekday> = phf_map! {
8    "日曜日" => Weekday::Sunday,
9    "日曜" => Weekday::Sunday,
10    "日" => Weekday::Sunday,
11    "月曜日" => Weekday::Monday,
12    "月曜" => Weekday::Monday,
13    "月" => Weekday::Monday,
14    "火曜日" => Weekday::Tuesday,
15    "火曜" => Weekday::Tuesday,
16    "火" => Weekday::Tuesday,
17    "水曜日" => Weekday::Wednesday,
18    "水曜" => Weekday::Wednesday,
19    "水" => Weekday::Wednesday,
20    "木曜日" => Weekday::Thursday,
21    "木曜" => Weekday::Thursday,
22    "木" => Weekday::Thursday,
23    "金曜日" => Weekday::Friday,
24    "金曜" => Weekday::Friday,
25    "金" => Weekday::Friday,
26    "土曜日" => Weekday::Saturday,
27    "土曜" => Weekday::Saturday,
28    "土" => Weekday::Saturday,
29};
30
31/// Month dictionary (Japanese uses numeric months but with kanji suffix)
32pub static MONTH_MAP: phf::Map<&'static str, u32> = phf_map! {
33    "1月" => 1,
34    "一月" => 1,
35    "2月" => 2,
36    "二月" => 2,
37    "3月" => 3,
38    "三月" => 3,
39    "4月" => 4,
40    "四月" => 4,
41    "5月" => 5,
42    "五月" => 5,
43    "6月" => 6,
44    "六月" => 6,
45    "7月" => 7,
46    "七月" => 7,
47    "8月" => 8,
48    "八月" => 8,
49    "9月" => 9,
50    "九月" => 9,
51    "10月" => 10,
52    "十月" => 10,
53    "11月" => 11,
54    "十一月" => 11,
55    "12月" => 12,
56    "十二月" => 12,
57};
58
59/// Japanese number characters
60pub static NUMBER_MAP: phf::Map<&'static str, u32> = phf_map! {
61    "零" => 0,
62    "〇" => 0,
63    "一" => 1,
64    "二" => 2,
65    "三" => 3,
66    "四" => 4,
67    "五" => 5,
68    "六" => 6,
69    "七" => 7,
70    "八" => 8,
71    "九" => 9,
72    "十" => 10,
73};
74
75/// Time unit dictionary
76pub static TIME_UNIT_MAP: phf::Map<&'static str, TimeUnit> = phf_map! {
77    "秒" => TimeUnit::Second,
78    "秒間" => TimeUnit::Second,
79    "分" => TimeUnit::Minute,
80    "分間" => TimeUnit::Minute,
81    "時間" => TimeUnit::Hour,
82    "時" => TimeUnit::Hour,
83    "日" => TimeUnit::Day,
84    "日間" => TimeUnit::Day,
85    "週" => TimeUnit::Week,
86    "週間" => TimeUnit::Week,
87    "ヶ月" => TimeUnit::Month,
88    "カ月" => TimeUnit::Month,
89    "か月" => TimeUnit::Month,
90    "月" => TimeUnit::Month,
91    "月間" => TimeUnit::Month,
92    "四半期" => TimeUnit::Quarter,
93    "年" => TimeUnit::Year,
94    "年間" => TimeUnit::Year,
95};
96
97/// Casual date keywords
98pub static CASUAL_DATE_MAP: phf::Map<&'static str, CasualDateType> = phf_map! {
99    "今" => CasualDateType::Now,
100    "今日" => CasualDateType::Today,
101    "きょう" => CasualDateType::Today,
102    "本日" => CasualDateType::Today,
103    "ほんじつ" => CasualDateType::Today,
104    "今夜" => CasualDateType::Tonight,
105    "こんや" => CasualDateType::Tonight,
106    "今晩" => CasualDateType::Tonight,
107    "こんばん" => CasualDateType::Tonight,
108    "今夕" => CasualDateType::Tonight,
109    "こんゆう" => CasualDateType::Tonight,
110    "今朝" => CasualDateType::Today,
111    "けさ" => CasualDateType::Today,
112    "明日" => CasualDateType::Tomorrow,
113    "あした" => CasualDateType::Tomorrow,
114    "あす" => CasualDateType::Tomorrow,
115    "昨日" => CasualDateType::Yesterday,
116    "きのう" => CasualDateType::Yesterday,
117    "さくじつ" => CasualDateType::Yesterday,
118    "明後日" => CasualDateType::Overmorrow,
119    "あさって" => CasualDateType::Overmorrow,
120    "一昨日" => CasualDateType::DayBeforeYesterday,
121    "おととい" => CasualDateType::DayBeforeYesterday,
122};
123
124/// Casual time keywords
125pub static CASUAL_TIME_MAP: phf::Map<&'static str, CasualTimeType> = phf_map! {
126    "正午" => CasualTimeType::Noon,
127    "昼" => CasualTimeType::Noon,
128    "真夜中" => CasualTimeType::Midnight,
129    "夜中" => CasualTimeType::Midnight,
130    "朝" => CasualTimeType::Morning,
131    "午前" => CasualTimeType::Morning,
132    "午後" => CasualTimeType::Afternoon,
133    "夕方" => CasualTimeType::Evening,
134    "夜" => CasualTimeType::Night,
135};
136
137/// Relative modifiers
138pub static RELATIVE_MODIFIER_MAP: phf::Map<&'static str, RelativeModifier> = phf_map! {
139    "今" => RelativeModifier::This,
140    "この" => RelativeModifier::This,
141    "今週" => RelativeModifier::This,
142    "次" => RelativeModifier::Next,
143    "来" => RelativeModifier::Next,
144    "次の" => RelativeModifier::Next,
145    "来週" => RelativeModifier::Next,
146    "前" => RelativeModifier::Last,
147    "先" => RelativeModifier::Last,
148    "先週" => RelativeModifier::Last,
149    "去" => RelativeModifier::Last,
150    "昨" => RelativeModifier::Last,
151};
152
153// ============================================================================
154// Lookup functions
155// ============================================================================
156
157#[inline]
158pub fn get_weekday(s: &str) -> Option<Weekday> {
159    WEEKDAY_MAP.get(s).copied()
160}
161
162#[inline]
163pub fn get_month(s: &str) -> Option<u32> {
164    MONTH_MAP.get(s).copied()
165}
166
167#[inline]
168pub fn get_number(s: &str) -> Option<u32> {
169    NUMBER_MAP.get(s).copied()
170}
171
172#[inline]
173pub fn get_time_unit(s: &str) -> Option<TimeUnit> {
174    TIME_UNIT_MAP.get(s).copied()
175}
176
177#[inline]
178pub fn get_casual_date(s: &str) -> Option<CasualDateType> {
179    CASUAL_DATE_MAP.get(s).copied()
180}
181
182#[inline]
183pub fn get_casual_time(s: &str) -> Option<CasualTimeType> {
184    CASUAL_TIME_MAP.get(s).copied()
185}
186
187#[inline]
188pub fn get_relative_modifier(s: &str) -> Option<RelativeModifier> {
189    RELATIVE_MODIFIER_MAP.get(s).copied()
190}
191
192/// Convert full-width characters to half-width (hankaku)
193pub fn to_hankaku(text: &str) -> String {
194    text.chars()
195        .map(|c| {
196            match c {
197                '\u{2019}' => '\u{0027}', // Right single quotation mark -> apostrophe
198                '\u{201D}' => '\u{0022}', // Right double quotation mark -> quote
199                '\u{3000}' => '\u{0020}', // Ideographic space -> space
200                '\u{FFE5}' => '\u{00A5}', // Full-width yen sign -> yen sign
201                // Full-width alphanumeric and punctuation (FF01-FF5E)
202                c if ('\u{FF01}'..='\u{FF5E}').contains(&c) => {
203                    char::from_u32(c as u32 - 0xFEE0).unwrap_or(c)
204                }
205                _ => c,
206            }
207        })
208        .collect()
209}
210
211/// Convert Japanese string to number
212/// Handles Japanese number characters like 一, 二, 三, 十, etc.
213pub fn ja_string_to_number(text: &str) -> u32 {
214    let mut number = 0u32;
215
216    for char in text.chars() {
217        let char_str = char.to_string();
218        if let Some(val) = get_number(&char_str) {
219            if char_str == "十" {
220                number = if number == 0 { val } else { number * val };
221            } else {
222                number += val;
223            }
224        }
225    }
226
227    number
228}
229
230/// Parse a number pattern (handles kanji numbers, digits)
231pub fn parse_number_pattern(text: &str) -> f64 {
232    // Try parsing as regular digit first
233    if let Ok(n) = text.parse::<f64>() {
234        return n;
235    }
236
237    // Try Japanese number conversion
238    let ja_num = ja_string_to_number(text);
239    if ja_num > 0 {
240        return ja_num as f64;
241    }
242
243    // Try single character kanji
244    if let Some(n) = get_number(text) {
245        return n as f64;
246    }
247
248    0.0
249}