@@ -335,6 +335,12 @@ pub fn rules_duration(b: &mut RuleSetBuilder<Dimension>) -> RustlingResult<()> {
335335 b. reg ( r#"fr[üu]her"# ) ?,
336336 |duration, _| duration. value ( ) . ago ( )
337337 ) ;
338+ b. rule_2 ( "seit <duration>" ,
339+ b. reg ( r#"seit"# ) ?,
340+ duration_check ! ( ) ,
341+ |_, duration| duration. value ( ) . ago ( ) ?
342+ . span_to ( & helpers:: cycle_nth ( Grain :: Second , 0 ) ?, false )
343+ ) ;
338344 b. rule_3 ( "<duration> after <datetime>" ,
339345 duration_check ! ( ) ,
340346 b. reg ( r#"nach"# ) ?,
@@ -1089,26 +1095,42 @@ pub fn rules_datetime(b: &mut RuleSetBuilder<Dimension>) -> RustlingResult<()> {
10891095 b. rule_1 ( "year" ,
10901096 integer_check_by_range ! ( 1900 , 2100 ) ,
10911097 |integer| {
1092- helpers:: year ( integer. value ( ) . value as i32 )
1098+ if integer. value ( ) . suffixed {
1099+ return Err ( RuleError :: Invalid . into ( ) )
1100+ } else {
1101+ helpers:: year ( integer. value ( ) . value as i32 )
1102+ }
10931103 }
10941104 ) ;
10951105 b. rule_2 ( "year" ,
10961106 b. reg ( r#"(?:de[rnms]|das|die) jahre?s?n?"# ) ?,
10971107 integer_check_by_range ! ( -1000 , 2100 ) ,
10981108 |_, integer| {
1099- helpers:: year ( integer. value ( ) . value as i32 )
1109+ if integer. value ( ) . suffixed {
1110+ return Err ( RuleError :: Invalid . into ( ) )
1111+ } else {
1112+ helpers:: year ( integer. value ( ) . value as i32 )
1113+ }
11001114 }
11011115 ) ;
11021116 b. rule_1 ( "year (latent)" ,
11031117 integer_check_by_range ! ( -1000 , 1899 ) ,
11041118 |integer| {
1105- Ok ( helpers:: year ( integer. value ( ) . value as i32 ) ?. latent ( ) )
1119+ if integer. value ( ) . suffixed {
1120+ return Err ( RuleError :: Invalid . into ( ) )
1121+ } else {
1122+ Ok ( helpers:: year ( integer. value ( ) . value as i32 ) ?. latent ( ) )
1123+ }
11061124 }
11071125 ) ;
11081126 b. rule_1 ( "year (latent)" ,
11091127 integer_check_by_range ! ( 2101 , 2200 ) ,
11101128 |integer| {
1111- Ok ( helpers:: year ( integer. value ( ) . value as i32 ) ?. latent ( ) )
1129+ if integer. value ( ) . suffixed {
1130+ return Err ( RuleError :: Invalid . into ( ) )
1131+ } else {
1132+ Ok ( helpers:: year ( integer. value ( ) . value as i32 ) ?. latent ( ) )
1133+ }
11121134 }
11131135 ) ;
11141136 b. rule_2 ( "the <day-of-month> (ordinal)" ,
@@ -1254,50 +1276,50 @@ pub fn rules_datetime(b: &mut RuleSetBuilder<Dimension>) -> RustlingResult<()> {
12541276 ) ;
12551277 b. rule_1_terminal ( "quarter (relative minutes)" ,
12561278 b. reg ( r#"vie?rtel"# ) ?,
1257- |_| Ok ( RelativeMinuteValue ( 15 ) )
1279+ |_| helpers :: relative_minute_value ( 15 )
12581280 ) ;
12591281 b. rule_1_terminal ( "half (relative minutes)" ,
12601282 b. reg ( r#"halbe?"# ) ?,
1261- |_| Ok ( RelativeMinuteValue ( 30 ) )
1283+ |_| helpers :: relative_minute_value ( 30 )
12621284 ) ;
12631285 b. rule_1_terminal ( "number (as relative minutes for minute=1)" ,
12641286 b. reg ( r#"eins"# ) ?,
1265- |_| Ok ( RelativeMinuteValue ( 1 ) )
1287+ |_| helpers :: relative_minute_value ( 1 )
12661288 ) ;
12671289 b. rule_1 ( "number (as relative minutes for minute>1)" ,
12681290 integer_check_by_range ! ( 2 , 59 ) ,
1269- |integer| Ok ( RelativeMinuteValue ( integer. value ( ) . value as i32 ) )
1291+ |integer| helpers :: relative_minute_value ( integer. value ( ) . value as i32 )
12701292 ) ;
12711293 b. rule_2 ( "number <minutes> (as relative minutes)" ,
12721294 integer_check_by_range ! ( 1 , 59 ) ,
12731295 b. reg ( r#"minuten?"# ) ?,
1274- |a, _| Ok ( RelativeMinuteValue ( a. value ( ) . value as i32 ) )
1296+ |a, _| helpers :: relative_minute_value ( a. value ( ) . value as i32 )
12751297 ) ;
12761298 b. rule_3 ( "<hour-of-day> <integer> (as relative minutes)" ,
12771299 datetime_check ! ( |datetime: & DatetimeValue | !datetime. latent && form!( Form :: TimeOfDay ( TimeOfDayForm :: Hour { .. } ) ) ( datetime) ) ,
12781300 b. reg ( r#"\s|und"# ) ?,
12791301 relative_minute_check ! ( ) ,
1280- |datetime, _, relative_minute | helpers:: hour_relative_minute (
1302+ |datetime, _, relative_minutes | helpers:: hour_relative_minute (
12811303 datetime. value ( ) . form_time_of_day ( ) ?. full_hour ( ) ,
1282- relative_minute . value ( ) . 0 ,
1304+ relative_minutes . value ( ) . value ,
12831305 datetime. value ( ) . form_time_of_day ( ) ?. is_12_clock ( ) )
12841306 ) ;
12851307 b. rule_3 ( "relative minutes to|till|before <integer> (hour-of-day)" ,
12861308 relative_minute_check ! ( ) ,
12871309 b. reg ( r#"vor"# ) ?,
12881310 datetime_check ! ( form!( Form :: TimeOfDay ( TimeOfDayForm :: Hour { .. } ) ) ) ,
1289- |relative_minute , _, datetime| helpers:: hour_relative_minute (
1311+ |relative_minutes , _, datetime| helpers:: hour_relative_minute (
12901312 datetime. value ( ) . form_time_of_day ( ) ?. full_hour ( ) ,
1291- -1 * relative_minute . value ( ) . 0 ,
1313+ -1 * relative_minutes . value ( ) . value ,
12921314 datetime. value ( ) . form_time_of_day ( ) ?. is_12_clock ( ) )
12931315 ) ;
12941316 b. rule_3 ( "relative minutes after|past <integer> (hour-of-day)" ,
12951317 relative_minute_check ! ( ) ,
12961318 b. reg ( r#"nach"# ) ?,
12971319 datetime_check ! ( form!( Form :: TimeOfDay ( TimeOfDayForm :: Hour { .. } ) ) ) ,
1298- |relative_minute , _, datetime| helpers:: hour_relative_minute (
1320+ |relative_minutes , _, datetime| helpers:: hour_relative_minute (
12991321 datetime. value ( ) . form_time_of_day ( ) ?. full_hour ( ) ,
1300- relative_minute . value ( ) . 0 ,
1322+ relative_minutes . value ( ) . value ,
13011323 datetime. value ( ) . form_time_of_day ( ) ?. is_12_clock ( ) )
13021324 ) ;
13031325 b. rule_2 ( "viertel <integer> (german style hour-of-day)" ,
@@ -1695,37 +1717,44 @@ pub fn rules_datetime(b: &mut RuleSetBuilder<Dimension>) -> RustlingResult<()> {
16951717 friday. span_to ( & monday, false )
16961718 }
16971719 ) ;
1698- b. rule_1_terminal ( "season" ,
1720+ b. rule_1_terminal ( "season - summer " ,
16991721 b. reg ( r#"sommer(?:zeit|s)?"# ) ?,
17001722 |_| Ok ( helpers:: month_day ( 6 , 21 ) ?
17011723 . span_to ( & helpers:: month_day ( 9 , 23 ) ?, false ) ?
1702- . form ( Form :: PartOfYear ) )
1724+ . form ( Form :: Season ) )
17031725 ) ;
17041726 b. rule_1_terminal ( "Summer solstice" ,
17051727 b. reg ( r#"sommersonn(?:en)?wende"# ) ?,
17061728 |_| Ok ( helpers:: month_day ( 6 , 21 ) ?. form ( Form :: Celebration ) . too_ambiguous ( ) )
17071729 ) ;
1708- b. rule_1_terminal ( "season" ,
1730+ b. rule_1_terminal ( "season - fall " ,
17091731 b. reg ( r#"herbst(?:zeit|s|es)?|sp[äa]tjahr(?:es)?"# ) ?,
17101732 |_| Ok ( helpers:: month_day ( 9 , 23 ) ?
17111733 . span_to ( & helpers:: month_day ( 12 , 21 ) ?, false ) ?
1712- . form ( Form :: PartOfYear ) )
1734+ . form ( Form :: Season ) )
17131735 ) ;
1714- b. rule_1_terminal ( "season" ,
1736+ b. rule_1_terminal ( "season - winter " ,
17151737 b. reg ( r#"winter(?:zeit|s)?"# ) ?,
17161738 |_| Ok ( helpers:: month_day ( 12 , 21 ) ?
17171739 . span_to ( & helpers:: month_day ( 3 , 20 ) ?, false ) ?
1718- . form ( Form :: PartOfYear ) )
1740+ . form ( Form :: Season ) )
1741+ ) ;
1742+ b. rule_2 ( "season - winter <year>" ,
1743+ b. reg ( r#"winter(?:zeit|s)?"# ) ?,
1744+ datetime_check ! ( form!( Form :: Year ( _) ) ) ,
1745+ |_, year| Ok ( helpers:: year_month_day ( year. value ( ) . form_year ( ) ?, 12 , 21 ) ?
1746+ . span_to ( & helpers:: year_month_day ( year. value ( ) . form_year ( ) ? + ( 1 as i32 ) , 3 , 20 ) ?, false ) ?
1747+ . form ( Form :: Season ) )
17191748 ) ;
17201749 b. rule_1_terminal ( "Winter solstice" ,
17211750 b. reg ( r#"wintersonnwende"# ) ?,
17221751 |_| Ok ( helpers:: month_day ( 12 , 21 ) ?. form ( Form :: Celebration ) . too_ambiguous ( ) )
17231752 ) ;
1724- b. rule_1_terminal ( "season" ,
1753+ b. rule_1_terminal ( "season - spring " ,
17251754 b. reg ( r#"(?:fr[üu]hlings?|fr[üu]hjahr(?:es)?)(?:zeit)?"# ) ?,
17261755 |_| Ok ( helpers:: month_day ( 3 , 20 ) ?
17271756 . span_to ( & helpers:: month_day ( 6 , 21 ) ?, false ) ?
1728- . form ( Form :: PartOfYear ) )
1757+ . form ( Form :: Season ) )
17291758 ) ;
17301759 b. rule_2 ( "im <part-of-year>" ,
17311760 b. reg ( r#"(?:(?:in )?(?:de[nrms]|die|das)|im|ins)"# ) ?,
@@ -1849,11 +1878,23 @@ pub fn rules_datetime(b: &mut RuleSetBuilder<Dimension>) -> RustlingResult<()> {
18491878// |_, datetime| Ok(datetime.value().clone().mark_before_end_all())
18501879// );
18511880 b. rule_2 ( "before <datetime>" ,
1852- b. reg ( r#"vor(?: de[nmr]| )|bis(?:(?: zu[rm]?(?: den)?)| in d(?:en|ie|as) )?"# ) ?,
1881+ b. reg ( r#"vor(?: de[nmr])?"# ) ?,
18531882 datetime_check ! ( excluding_form!( Form :: PartOfForm ( _) ) ) ,
18541883 |_, datetime| Ok ( datetime. value ( ) . clone ( ) . mark_before_start ( ) )
18551884 ) ;
18561885
1886+ b. rule_2 ( "until <datetime>" ,
1887+ b. reg ( r#"bis(?:(?: zu[rm]?(?: de[nmr])?))?"# ) ?,
1888+ datetime_check ! ( |datetime: & DatetimeValue | excluding_form!( Form :: PartOfForm ( _) ) ( datetime) && excluding_form!( Form :: TimeOfDay ( _) ) ( datetime) ) ,
1889+ |_, datetime| Ok ( datetime. value ( ) . clone ( ) . mark_before_end_all ( ) )
1890+ ) ;
1891+
1892+ b. rule_2 ( "until <time-of-day>" ,
1893+ b. reg ( r#"bis"# ) ?,
1894+ datetime_check ! ( |datetime: & DatetimeValue | excluding_form!( Form :: PartOfForm ( _) ) ( datetime) && form!( Form :: TimeOfDay ( _) ) ( datetime) ) ,
1895+ |_, datetime| Ok ( datetime. value ( ) . clone ( ) . mark_before_end ( ) )
1896+ ) ;
1897+
18571898 b. rule_2 ( "before <part-of-form> (specific cases)" ,
18581899 b. reg ( r#"vor(?: de[nmr]| )|bis(?:(?: zu[rm]?(?: den)?)| in d(?:en|ie|as))?"# ) ?,
18591900 datetime_check ! ( form!( Form :: PartOfForm ( _) ) ) ,
@@ -2287,28 +2328,26 @@ pub fn rules_numbers(b: &mut RuleSetBuilder<Dimension>) -> RustlingResult<()> {
22872328 |text_match| FloatValue :: new ( text_match. group ( 1 ) . replace ( "," , "." ) . parse ( ) ?)
22882329 ) ;
22892330 b. rule_3 ( "number dot number" ,
2290- number_check ! ( |number : & NumberValue | !number . prefixed( ) ) ,
2331+ integer_check ! ( |integer : & IntegerValue | !integer . prefixed) ,
22912332 b. reg ( r#"komma"# ) ?,
2292- number_check ! ( |number : & NumberValue | !number . suffixed( ) ) ,
2333+ integer_check ! ( |integer : & IntegerValue | !integer . suffixed) ,
22932334 |a, _, b| {
2294- let power = b. value ( ) . value ( ) . to_string ( ) . chars ( ) . count ( ) ;
2295- let coeff = 10.0_f32 . powf ( -1.0 * power as f32 ) ;
2335+ let value: f64 = format ! ( "{}.{}" , a. value( ) . value, b. value( ) . value) . parse ( ) ?;
22962336 Ok ( FloatValue {
2297- value : b . value ( ) . value ( ) * coeff + a . value ( ) . value ( ) ,
2337+ value,
22982338 ..FloatValue :: default ( )
22992339 } )
2300- }
2301- ) ;
2340+ } ) ;
23022341 b. rule_4 ( "number dot zero ... number" ,
2303- number_check ! ( |number : & NumberValue | !number . prefixed( ) ) ,
2342+ integer_check ! ( |integer : & IntegerValue | !integer . prefixed) ,
23042343 b. reg ( r#"komma"# ) ?,
23052344 b. reg ( r#"(?:(?:null )*(?:null))"# ) ?,
2306- number_check ! ( |number : & NumberValue | !number . suffixed( ) ) ,
2345+ integer_check ! ( |integer : & IntegerValue | !integer . suffixed) ,
23072346 |a, _, zeros, b| {
2308- let power = zeros. group ( 0 ) . split_whitespace ( ) . count ( ) + b . value ( ) . value ( ) . to_string ( ) . chars ( ) . count ( ) ;
2309- let coeff = 10.0_f32 . powf ( - 1.0 * power as f32 ) ;
2347+ let zeros_string = std :: iter :: repeat ( "0" ) . take ( zeros. group ( 0 ) . split_whitespace ( ) . count ( ) ) . collect :: < String > ( ) ;
2348+ let value : f64 = format ! ( "{}.{}{}" , a . value ( ) . value , zeros_string , b . value ( ) . value ) . parse ( ) ? ;
23102349 Ok ( FloatValue {
2311- value : b . value ( ) . value ( ) * coeff + a . value ( ) . value ( ) ,
2350+ value,
23122351 ..FloatValue :: default ( )
23132352 } )
23142353 } ) ;
@@ -2383,7 +2422,7 @@ pub fn rules_numbers(b: &mut RuleSetBuilder<Dimension>) -> RustlingResult<()> {
23832422 . into ( )
23842423 }
23852424 NumberValue :: Float ( float) => {
2386- let product = float. value * ( multiplier as f32 ) ;
2425+ let product = float. value * ( multiplier as f64 ) ;
23872426 if product. floor ( ) == product {
23882427 IntegerValue {
23892428 value : product as i64 ,
0 commit comments