@@ -44,7 +44,8 @@ mod builder;
4444mod ordinal;
4545mod primitive;
4646
47- use builder:: DateTimeBuilder ;
47+ pub ( crate ) mod error;
48+
4849use jiff:: Zoned ;
4950use primitive:: space;
5051use winnow:: {
@@ -54,7 +55,8 @@ use winnow::{
5455 ModalResult , Parser ,
5556} ;
5657
57- use crate :: ParseDateTimeError ;
58+ use builder:: DateTimeBuilder ;
59+ use error:: Error ;
5860
5961#[ derive( PartialEq , Debug ) ]
6062enum Item {
@@ -69,40 +71,23 @@ enum Item {
6971}
7072
7173/// Parse a date and time string based on a specific date.
72- pub ( crate ) fn parse_at_date < S : AsRef < str > + Clone > (
73- base : Zoned ,
74- input : S ,
75- ) -> Result < Zoned , ParseDateTimeError > {
74+ pub ( crate ) fn parse_at_date < S : AsRef < str > + Clone > ( base : Zoned , input : S ) -> Result < Zoned , Error > {
7675 let input = input. as_ref ( ) . to_ascii_lowercase ( ) ;
7776 match parse ( & mut input. as_str ( ) ) {
78- Ok ( builder) => at_date ( builder, base) ,
79- Err ( _ ) => Err ( ParseDateTimeError :: InvalidInput ) ,
77+ Ok ( builder) => builder. set_base ( base) . build ( ) ,
78+ Err ( e ) => Err ( e . into ( ) ) ,
8079 }
8180}
8281
8382/// Parse a date and time string based on the current local time.
84- pub ( crate ) fn parse_at_local < S : AsRef < str > + Clone > ( input : S ) -> Result < Zoned , ParseDateTimeError > {
83+ pub ( crate ) fn parse_at_local < S : AsRef < str > + Clone > ( input : S ) -> Result < Zoned , Error > {
8584 let input = input. as_ref ( ) . to_ascii_lowercase ( ) ;
8685 match parse ( & mut input. as_str ( ) ) {
87- Ok ( builder) => at_local ( builder) ,
88- Err ( _ ) => Err ( ParseDateTimeError :: InvalidInput ) ,
86+ Ok ( builder) => builder. build ( ) ,
87+ Err ( e ) => Err ( e . into ( ) ) ,
8988 }
9089}
9190
92- /// Build a `Zoned` object from a `DateTimeBuilder` and a base `Zoned` object.
93- fn at_date ( builder : DateTimeBuilder , base : Zoned ) -> Result < Zoned , ParseDateTimeError > {
94- builder
95- . set_base ( base)
96- . build ( )
97- . ok_or ( ParseDateTimeError :: InvalidInput )
98- }
99-
100- /// Build a `Zoned` object from a `DateTimeBuilder` and a default `Zoned` object
101- /// (the current time in the local timezone).
102- fn at_local ( builder : DateTimeBuilder ) -> Result < Zoned , ParseDateTimeError > {
103- builder. build ( ) . ok_or ( ParseDateTimeError :: InvalidInput )
104- }
105-
10691/// Parse a date and time string.
10792///
10893/// Grammar:
@@ -310,10 +295,14 @@ fn expect_error(input: &mut &str, reason: &'static str) -> ErrMode<ContextError>
310295mod tests {
311296 use jiff:: { civil:: DateTime , tz:: TimeZone , ToSpan , Zoned } ;
312297
313- use super :: { at_date, parse, DateTimeBuilder } ;
298+ use super :: { parse, DateTimeBuilder } ;
299+
300+ fn at_date ( builder : DateTimeBuilder , base : Zoned ) -> Zoned {
301+ builder. set_base ( base) . build ( ) . unwrap ( )
302+ }
314303
315304 fn at_utc ( builder : DateTimeBuilder ) -> Zoned {
316- at_date ( builder, Zoned :: now ( ) . with_time_zone ( TimeZone :: UTC ) ) . unwrap ( )
305+ at_date ( builder, Zoned :: now ( ) . with_time_zone ( TimeZone :: UTC ) )
317306 }
318307
319308 fn test_eq_fmt ( fmt : & str , input : & str ) -> String {
@@ -479,43 +468,40 @@ mod tests {
479468 . unwrap ( ) ;
480469
481470 assert_eq ! (
482- at_date( parse( & mut "last wed" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
471+ at_date( parse( & mut "last wed" ) . unwrap( ) , now. clone( ) ) ,
483472 now. checked_sub( 7 . days( ) ) . unwrap( )
484473 ) ;
474+ assert_eq ! ( at_date( parse( & mut "this wed" ) . unwrap( ) , now. clone( ) ) , now) ;
485475 assert_eq ! (
486- at_date( parse( & mut "this wed" ) . unwrap( ) , now. clone( ) ) . unwrap( ) ,
487- now
488- ) ;
489- assert_eq ! (
490- at_date( parse( & mut "next wed" ) . unwrap( ) , now. clone( ) ) . unwrap( ) ,
476+ at_date( parse( & mut "next wed" ) . unwrap( ) , now. clone( ) ) ,
491477 now. checked_add( 7 . days( ) ) . unwrap( )
492478 ) ;
493479 assert_eq ! (
494- at_date( parse( & mut "last thu" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
480+ at_date( parse( & mut "last thu" ) . unwrap( ) , now. clone( ) ) ,
495481 now. checked_sub( 6 . days( ) ) . unwrap( )
496482 ) ;
497483 assert_eq ! (
498- at_date( parse( & mut "this thu" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
484+ at_date( parse( & mut "this thu" ) . unwrap( ) , now. clone( ) ) ,
499485 now. checked_add( 1 . days( ) ) . unwrap( )
500486 ) ;
501487 assert_eq ! (
502- at_date( parse( & mut "next thu" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
488+ at_date( parse( & mut "next thu" ) . unwrap( ) , now. clone( ) ) ,
503489 now. checked_add( 1 . days( ) ) . unwrap( )
504490 ) ;
505491 assert_eq ! (
506- at_date( parse( & mut "1 wed" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
492+ at_date( parse( & mut "1 wed" ) . unwrap( ) , now. clone( ) ) ,
507493 now. checked_add( 7 . days( ) ) . unwrap( )
508494 ) ;
509495 assert_eq ! (
510- at_date( parse( & mut "1 thu" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
496+ at_date( parse( & mut "1 thu" ) . unwrap( ) , now. clone( ) ) ,
511497 now. checked_add( 1 . days( ) ) . unwrap( )
512498 ) ;
513499 assert_eq ! (
514- at_date( parse( & mut "2 wed" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
500+ at_date( parse( & mut "2 wed" ) . unwrap( ) , now. clone( ) ) ,
515501 now. checked_add( 14 . days( ) ) . unwrap( )
516502 ) ;
517503 assert_eq ! (
518- at_date( parse( & mut "2 thu" ) . unwrap( ) , now. clone( ) ) . unwrap ( ) ,
504+ at_date( parse( & mut "2 thu" ) . unwrap( ) , now. clone( ) ) ,
519505 now. checked_add( 8 . days( ) ) . unwrap( )
520506 ) ;
521507 }
@@ -524,30 +510,30 @@ mod tests {
524510 fn relative_date_time ( ) {
525511 let now = Zoned :: now ( ) . with_time_zone ( TimeZone :: UTC ) ;
526512
527- let result = at_date ( parse ( & mut "2 days ago" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
513+ let result = at_date ( parse ( & mut "2 days ago" ) . unwrap ( ) , now. clone ( ) ) ;
528514 assert_eq ! ( result, now. checked_sub( 2 . days( ) ) . unwrap( ) ) ;
529515 assert_eq ! ( result. hour( ) , now. hour( ) ) ;
530516 assert_eq ! ( result. minute( ) , now. minute( ) ) ;
531517 assert_eq ! ( result. second( ) , now. second( ) ) ;
532518
533- let result = at_date ( parse ( & mut "2 days 3 days ago" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
519+ let result = at_date ( parse ( & mut "2 days 3 days ago" ) . unwrap ( ) , now. clone ( ) ) ;
534520 assert_eq ! ( result, now. checked_sub( 1 . days( ) ) . unwrap( ) ) ;
535521 assert_eq ! ( result. hour( ) , now. hour( ) ) ;
536522 assert_eq ! ( result. minute( ) , now. minute( ) ) ;
537523 assert_eq ! ( result. second( ) , now. second( ) ) ;
538524
539- let result = at_date ( parse ( & mut "2025-01-01 2 days ago" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
525+ let result = at_date ( parse ( & mut "2025-01-01 2 days ago" ) . unwrap ( ) , now. clone ( ) ) ;
540526 assert_eq ! ( result. hour( ) , 0 ) ;
541527 assert_eq ! ( result. minute( ) , 0 ) ;
542528 assert_eq ! ( result. second( ) , 0 ) ;
543529
544- let result = at_date ( parse ( & mut "3 weeks" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
530+ let result = at_date ( parse ( & mut "3 weeks" ) . unwrap ( ) , now. clone ( ) ) ;
545531 assert_eq ! ( result, now. checked_add( 21 . days( ) ) . unwrap( ) ) ;
546532 assert_eq ! ( result. hour( ) , now. hour( ) ) ;
547533 assert_eq ! ( result. minute( ) , now. minute( ) ) ;
548534 assert_eq ! ( result. second( ) , now. second( ) ) ;
549535
550- let result = at_date ( parse ( & mut "2025-01-01 3 weeks" ) . unwrap ( ) , now) . unwrap ( ) ;
536+ let result = at_date ( parse ( & mut "2025-01-01 3 weeks" ) . unwrap ( ) , now) ;
551537 assert_eq ! ( result. hour( ) , 0 ) ;
552538 assert_eq ! ( result. minute( ) , 0 ) ;
553539 assert_eq ! ( result. second( ) , 0 ) ;
@@ -558,23 +544,23 @@ mod tests {
558544 let now = Zoned :: now ( ) . with_time_zone ( TimeZone :: UTC ) ;
559545
560546 // Pure number as year.
561- let result = at_date ( parse ( & mut "jul 18 12:30 2025" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
547+ let result = at_date ( parse ( & mut "jul 18 12:30 2025" ) . unwrap ( ) , now. clone ( ) ) ;
562548 assert_eq ! ( result. year( ) , 2025 ) ;
563549
564550 // Pure number as time.
565- let result = at_date ( parse ( & mut "1230" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
551+ let result = at_date ( parse ( & mut "1230" ) . unwrap ( ) , now. clone ( ) ) ;
566552 assert_eq ! ( result. hour( ) , 12 ) ;
567553 assert_eq ! ( result. minute( ) , 30 ) ;
568554
569- let result = at_date ( parse ( & mut "123" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
555+ let result = at_date ( parse ( & mut "123" ) . unwrap ( ) , now. clone ( ) ) ;
570556 assert_eq ! ( result. hour( ) , 1 ) ;
571557 assert_eq ! ( result. minute( ) , 23 ) ;
572558
573- let result = at_date ( parse ( & mut "12" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
559+ let result = at_date ( parse ( & mut "12" ) . unwrap ( ) , now. clone ( ) ) ;
574560 assert_eq ! ( result. hour( ) , 12 ) ;
575561 assert_eq ! ( result. minute( ) , 0 ) ;
576562
577- let result = at_date ( parse ( & mut "1" ) . unwrap ( ) , now. clone ( ) ) . unwrap ( ) ;
563+ let result = at_date ( parse ( & mut "1" ) . unwrap ( ) , now. clone ( ) ) ;
578564 assert_eq ! ( result. hour( ) , 1 ) ;
579565 assert_eq ! ( result. minute( ) , 0 ) ;
580566 }
0 commit comments