@@ -472,6 +472,35 @@ TEST(Date32Conversion, Errors) {
472472 AssertConversionError (date32 (), {" 2020-13-01\n " }, {0 });
473473}
474474
475+ TEST (Date32Conversion, UserDefinedParsers) {
476+ auto options = ConvertOptions::Defaults ();
477+ const auto type = date32 ();
478+
479+ // Test a single parser
480+ options.timestamp_parsers = {TimestampParser::MakeStrptime (" %d-%b-%y" )};
481+ AssertConversion<Date32Type, int32_t >(type, {" 15-OCT-15,18-JUN-90\n " },
482+ {{16723 }, {7473 }}, options);
483+
484+ // ISO-8601 values are still accepted when parsers are given
485+ AssertConversion<Date32Type, int32_t >(type, {" 2020-03-15,15-OCT-15\n " },
486+ {{18336 }, {16723 }}, options);
487+
488+ // Test multiple parsers, with a pre-epoch value
489+ options.timestamp_parsers .push_back (TimestampParser::MakeStrptime (" %d-%m-%Y" ));
490+ AssertConversion<Date32Type, int32_t >(type, {" 15-OCT-15,08-05-1945\n " },
491+ {{16723 }, {-9004 }}, options);
492+
493+ // Parsed timestamps are floored to the day boundary, also before the epoch
494+ options.timestamp_parsers = {TimestampParser::MakeStrptime (" %m/%d/%Y %H:%M" )};
495+ AssertConversion<Date32Type, int32_t >(type, {" 03/15/2020 14:30,05/08/1945 14:30\n " },
496+ {{18336 }, {-9004 }}, options);
497+
498+ // Test errors
499+ AssertConversionError (type, {" 24-12-2020\n " }, {0 }, options);
500+ options.timestamp_parsers = {TimestampParser::MakeStrptime (" %m/%d/%Y %z" )};
501+ AssertConversionError (type, {" 01/02/1970 +0000\n " }, {0 }, options);
502+ }
503+
475504TEST (Date64Conversion, Basics) {
476505 AssertConversion<Date64Type, int64_t >(date64 (), {" 1945-05-08\n " , " 2020-03-15\n " },
477506 {{-777945600000LL , 1584230400000LL }});
@@ -487,6 +516,33 @@ TEST(Date64Conversion, Errors) {
487516 AssertConversionError (date64 (), {" 2020-13-01\n " }, {0 });
488517}
489518
519+ TEST (Date64Conversion, UserDefinedParsers) {
520+ auto options = ConvertOptions::Defaults ();
521+ const auto type = date64 ();
522+
523+ // Test a single parser
524+ options.timestamp_parsers = {TimestampParser::MakeStrptime (" %d-%b-%y" )};
525+ AssertConversion<Date64Type, int64_t >(type, {" 15-OCT-15,18-JUN-90\n " },
526+ {{1444867200000LL }, {645667200000LL }}, options);
527+
528+ // ISO-8601 values are still accepted when parsers are given
529+ AssertConversion<Date64Type, int64_t >(type, {" 2020-03-15,15-OCT-15\n " },
530+ {{1584230400000LL }, {1444867200000LL }}, options);
531+
532+ // Test multiple parsers, with a pre-epoch value
533+ options.timestamp_parsers .push_back (TimestampParser::MakeStrptime (" %d-%m-%Y" ));
534+ AssertConversion<Date64Type, int64_t >(type, {" 15-OCT-15,08-05-1945\n " },
535+ {{1444867200000LL }, {-777945600000LL }}, options);
536+
537+ // Parsed timestamps are floored to the day boundary, also before the epoch
538+ options.timestamp_parsers = {TimestampParser::MakeStrptime (" %m/%d/%Y %H:%M" )};
539+ AssertConversion<Date64Type, int64_t >(type, {" 03/15/2020 14:30,05/08/1945 14:30\n " },
540+ {{1584230400000LL }, {-777945600000LL }}, options);
541+
542+ // Test errors
543+ AssertConversionError (type, {" 24-12-2020\n " }, {0 }, options);
544+ }
545+
490546TEST (Time32Conversion, Seconds) {
491547 const auto type = time32 (TimeUnit::SECOND );
492548
@@ -513,6 +569,30 @@ TEST(Time32Conversion, Millis) {
513569 AssertConversionError (type, {" 23:59:60\n " }, {0 });
514570}
515571
572+ TEST (Time32Conversion, UserDefinedParsers) {
573+ auto options = ConvertOptions::Defaults ();
574+
575+ // Test a single parser, with non-zero-padded hours
576+ options.timestamp_parsers = {TimestampParser::MakeStrptime (" %H:%M:%S" )};
577+ AssertConversion<Time32Type, int32_t >(time32 (TimeUnit::SECOND ), {" 7:55:00,12:01:02\n " },
578+ {{28500 }, {43262 }}, options);
579+ AssertConversion<Time32Type, int32_t >(time32 (TimeUnit::MILLI ), {" 7:55:00\n " },
580+ {{28500000 }}, options);
581+
582+ // ISO-8601 values are still accepted when parsers are given
583+ AssertConversion<Time32Type, int32_t >(time32 (TimeUnit::SECOND ), {" 07:55:00,7:55:00\n " },
584+ {{28500 }, {28500 }}, options);
585+
586+ // The time of day is extracted from parsed timestamps, also before the epoch
587+ options.timestamp_parsers .push_back (TimestampParser::MakeStrptime (" %Y-%m-%d %H:%M" ));
588+ AssertConversion<Time32Type, int32_t >(time32 (TimeUnit::SECOND ),
589+ {" 2020-03-15 07:55,1945-05-08 07:55\n " },
590+ {{28500 }, {28500 }}, options);
591+
592+ // Test errors
593+ AssertConversionError (time32 (TimeUnit::SECOND ), {" 24:00:00\n " }, {0 }, options);
594+ }
595+
516596TEST (Time64Conversion, Micros) {
517597 const auto type = time64 (TimeUnit::MICRO );
518598
@@ -539,6 +619,24 @@ TEST(Time64Conversion, Nanos) {
539619 AssertConversionError (type, {" 23:59:60\n " }, {0 });
540620}
541621
622+ TEST (Time64Conversion, UserDefinedParsers) {
623+ auto options = ConvertOptions::Defaults ();
624+
625+ // Test a single parser, with non-zero-padded hours
626+ options.timestamp_parsers = {TimestampParser::MakeStrptime (" %H:%M:%S" )};
627+ AssertConversion<Time64Type, int64_t >(time64 (TimeUnit::MICRO ), {" 7:55:00\n " },
628+ {{28500000000LL }}, options);
629+ AssertConversion<Time64Type, int64_t >(time64 (TimeUnit::NANO ), {" 7:55:00\n " },
630+ {{28500000000000LL }}, options);
631+
632+ // ISO-8601 values are still accepted when parsers are given
633+ AssertConversion<Time64Type, int64_t >(time64 (TimeUnit::MICRO ), {" 07:55:00.123456\n " },
634+ {{28500123456LL }}, options);
635+
636+ // Test errors
637+ AssertConversionError (time64 (TimeUnit::MICRO ), {" 24:00:00\n " }, {0 }, options);
638+ }
639+
542640TEST (TimestampConversion, Basics) {
543641 auto type = timestamp (TimeUnit::SECOND );
544642
0 commit comments