Skip to content

Commit fa15d84

Browse files
committed
Add more tests for parse_from_str and specifiers
Add exhaustive set of tests for `DateTime<FixedOffset>::parse_from_str` function and all strftime specifiers. Issue chronotope#1112
1 parent 088b693 commit fa15d84

File tree

3 files changed

+213
-4
lines changed

3 files changed

+213
-4
lines changed

src/datetime/tests.rs

+210-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use crate::offset::{FixedOffset, TimeZone, Utc};
66
#[cfg(feature = "clock")]
77
use crate::offset::{Local, Offset};
88
use crate::{Datelike, Days, LocalResult, Months, NaiveDateTime, TimeDelta};
9+
use crate::naive::date::{MAX_YEAR, MIN_YEAR};
10+
use crate::format::ParseResult;
911

1012
#[derive(Clone)]
1113
struct DstTester;
@@ -989,8 +991,215 @@ fn test_utc_datetime_from_str_with_spaces() {
989991
assert!(Utc.datetime_from_str("Aug 09 2013 23:54:35 !!!", "%b %d %Y %H:%M:%S ").is_err());
990992
}
991993

994+
/// Test `parse_from_str` focused on strftime `%Y`, `%y`, and `%C` specifiers.
992995
#[test]
993-
fn test_datetime_parse_from_str() {
996+
fn test_datetime_parse_from_str_year() {
997+
fn parse(data: &str, format: &str) -> ParseResult<DateTime::<FixedOffset>> {
998+
eprintln!("parse: data: {:?}, format: {:?}", data, format);
999+
DateTime::<FixedOffset>::parse_from_str(data, format)
1000+
}
1001+
fn parse_year(data: &str, format: &str) -> i32 {
1002+
eprintln!("parse_year: data: {:?}, format: {:?}", data, format);
1003+
DateTime::<FixedOffset>::parse_from_str(data, format).unwrap().year()
1004+
}
1005+
let dt = ymdhms(
1006+
&FixedOffset::east_opt(-9 * 60 * 60).unwrap(),
1007+
2013, 8, 9, 23, 54, 35
1008+
);
1009+
1010+
//
1011+
// %Y
1012+
//
1013+
// ok
1014+
assert_eq!(parse("2013-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z"), Ok(dt));
1015+
assert_eq!(parse("08-2013-09T23:54:35 -0900", "%m-%Y-%dT%H:%M:%S %z"), Ok(dt));
1016+
assert_eq!(parse_year("9999-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z"), 9999);
1017+
assert_eq!(parse_year("999-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z"), 999);
1018+
assert_eq!(parse_year("99-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z"), 99);
1019+
assert_eq!(parse_year("9-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z"), 9);
1020+
assert_eq!(parse_year("0-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z"), 0);
1021+
let d1: String = MIN_YEAR.to_string() + "-08-09T23:54:35 -0900";
1022+
assert_eq!(parse_year(d1.as_str(), "%Y-%m-%dT%H:%M:%S %z"), MIN_YEAR);
1023+
let d1: String = (MIN_YEAR + 1).to_string() + "-08-09T23:54:35 -0900";
1024+
assert_eq!(parse_year(d1.as_str(), "%Y-%m-%dT%H:%M:%S %z"), MIN_YEAR + 1);
1025+
// errors
1026+
// XXX: MAX_YEAR cannont be parsed, can only parse up to four decimal digits
1027+
let d1: String = MAX_YEAR.to_string() + "-08-09T23:54:35 -0900";
1028+
assert!(parse(d1.as_str(), "%Y-%m-%dT%H:%M:%S %z").is_err());
1029+
assert!(parse("99999-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1030+
assert!(parse("A-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1031+
assert!(parse("0x11-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1032+
assert!(parse("108-09T23:54:35 -0900", "%Y%m-%dT%H:%M:%S %z").is_err());
1033+
1034+
//
1035+
// %y
1036+
//
1037+
// ok
1038+
assert_eq!(parse("13-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z"), Ok(dt));
1039+
assert_eq!(parse("08-13-09T23:54:35 -0900", "%m-%y-%dT%H:%M:%S %z"), Ok(dt));
1040+
assert_eq!(parse_year("0-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z"), 2000);
1041+
assert_eq!(parse_year("99-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z"), 1999);
1042+
assert_eq!(parse_year("108-09T23:54:35 -0900", "%y%m-%dT%H:%M:%S %z"), 2010);
1043+
assert_eq!(parse_year("081-09T23:54:35 -0900", "%m%y-%dT%H:%M:%S %z"), 2001);
1044+
// errors
1045+
assert!(parse("999-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z").is_err());
1046+
assert!(parse("100-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z").is_err());
1047+
assert!(parse("013-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z").is_err());
1048+
assert!(parse("0x11-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z").is_err());
1049+
assert!(parse("A-08-09T23:54:35 -0900", "%y-%m-%dT%H:%M:%S %z").is_err());
1050+
1051+
//
1052+
// %C
1053+
//
1054+
// ok
1055+
assert_eq!(parse("2013-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z"), Ok(dt));
1056+
assert_eq!(parse("20_13-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z"), Ok(dt));
1057+
assert_eq!(parse_year("0_13-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z"), 13);
1058+
assert_eq!(parse_year("9_13-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z"), 913);
1059+
assert_eq!(parse_year("99_13-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z"), 9913);
1060+
assert_eq!(parse_year("013-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z"), 103);
1061+
assert_eq!(parse_year("113-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z"), 1103);
1062+
assert_eq!(parse_year("223-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z"), 2203);
1063+
assert_eq!(parse_year("553-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z"), 5503);
1064+
assert_eq!(parse_year("993-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z"), 9903);
1065+
assert_eq!(parse_year("9923-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z"), 9923);
1066+
// errors
1067+
assert!(parse("913_2-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z").is_err());
1068+
assert!(parse("9913-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z").is_err());
1069+
assert!(parse("99923-08-09T23:54:35 -0900", "%C%y-%m-%dT%H:%M:%S %z").is_err());
1070+
assert!(parse("20-13-09T23:54:35 -0900", "%m-%C-%dT%H:%M:%S %z").is_err());
1071+
assert!(parse("999_01-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z").is_err());
1072+
assert!(parse("100_01-08-09T23:54:35 -0900", "%C_%y-%m-%dT%H:%M:%S %z").is_err());
1073+
assert!(parse("0x11-08-09T23:54:35 -0900", "%C-%m-%dT%H:%M:%S %z").is_err());
1074+
assert!(parse("A-08-09T23:54:35 -0900", "%C-%m-%dT%H:%M:%S %z").is_err());
1075+
}
1076+
1077+
/// Test `parse_from_str` focused on strftime `%m`, `%b`, `%h`, and `%B` specifiers.
1078+
#[test]
1079+
fn test_datetime_parse_from_str_month() {
1080+
fn parse(data: &str, format: &str) -> ParseResult<DateTime::<FixedOffset>> {
1081+
eprintln!("parse: data: {:?}, format: {:?}", data, format);
1082+
DateTime::<FixedOffset>::parse_from_str(data, format)
1083+
}
1084+
fn parse_month(data: &str, format: &str) -> u32 {
1085+
eprintln!("parse_month: data: {:?}, format: {:?}", data, format);
1086+
DateTime::<FixedOffset>::parse_from_str(data, format).unwrap().month()
1087+
}
1088+
let dt = ymdhms(
1089+
&FixedOffset::east_opt(-9 * 60 * 60).unwrap(),
1090+
2013, 8, 9, 23, 54, 35
1091+
);
1092+
1093+
//
1094+
// %m
1095+
//
1096+
// ok
1097+
assert_eq!(parse("2013-08-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z"), Ok(dt));
1098+
assert_eq!(parse("201308-09T23:54:35 -0900", "%Y%m-%dT%H:%M:%S %z"), Ok(dt));
1099+
assert_eq!(parse("2013-0809T23:54:35 -0900", "%Y-%m%dT%H:%M:%S %z"), Ok(dt));
1100+
assert_eq!(parse("20130809T23:54:35 -0900", "%Y%m%dT%H:%M:%S %z"), Ok(dt));
1101+
assert_eq!(parse("20130809235435-0900", "%Y%m%d%H%M%S%z"), Ok(dt));
1102+
assert_eq!(parse_month("20130109235435-0900", "%Y%m%d%H%M%S%z"), 1);
1103+
assert_eq!(parse_month("20131209235435-0900", "%Y%m%d%H%M%S%z"), 12);
1104+
// errors
1105+
assert!(parse("2013-00-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1106+
assert!(parse("2013-13-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1107+
assert!(parse("2013-55-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1108+
assert!(parse("2013-99-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1109+
assert!(parse("2013-123-09T23:54:35 -0900", "%Y-%m-%dT%H:%M:%S %z").is_err());
1110+
1111+
//
1112+
// %b
1113+
//
1114+
// ok
1115+
assert_eq!(parse("2013-Aug-09T23:54:35 -0900", "%Y-%b-%dT%H:%M:%S %z"), Ok(dt));
1116+
assert_eq!(parse("2013aug-09T23:54:35 -0900", "%Y%b-%dT%H:%M:%S %z"), Ok(dt));
1117+
assert_eq!(parse("2013-AUG09T23:54:35 -0900", "%Y-%b%dT%H:%M:%S %z"), Ok(dt));
1118+
assert_eq!(parse("2013aug09T23:54:35 -0900", "%Y%b%dT%H:%M:%S %z"), Ok(dt));
1119+
assert_eq!(parse("2013aug09235435-0900", "%Y%b%d%H%M%S%z"), Ok(dt));
1120+
assert_eq!(parse_month("2013jan09235435-0900", "%Y%b%d%H%M%S%z"), 1);
1121+
assert_eq!(parse_month("2013feb09235435-0900", "%Y%b%d%H%M%S%z"), 2);
1122+
assert_eq!(parse_month("2013mar09235435-0900", "%Y%b%d%H%M%S%z"), 3);
1123+
assert_eq!(parse_month("2013apr09235435-0900", "%Y%b%d%H%M%S%z"), 4);
1124+
assert_eq!(parse_month("2013may09235435-0900", "%Y%b%d%H%M%S%z"), 5);
1125+
assert_eq!(parse_month("2013jun09235435-0900", "%Y%b%d%H%M%S%z"), 6);
1126+
assert_eq!(parse_month("2013jul09235435-0900", "%Y%b%d%H%M%S%z"), 7);
1127+
assert_eq!(parse_month("2013aug09235435-0900", "%Y%b%d%H%M%S%z"), 8);
1128+
assert_eq!(parse_month("2013sep09235435-0900", "%Y%b%d%H%M%S%z"), 9);
1129+
assert_eq!(parse_month("2013oct09235435-0900", "%Y%b%d%H%M%S%z"), 10);
1130+
assert_eq!(parse_month("2013nov09235435-0900", "%Y%b%d%H%M%S%z"), 11);
1131+
assert_eq!(parse_month("2013dec09235435-0900", "%Y%b%d%H%M%S%z"), 12);
1132+
// errors
1133+
assert!(parse("2013-AWG-09T23:54:35 -0900", "%Y-%b-%dT%H:%M:%S %z").is_err());
1134+
assert!(parse("2013-AU-09T23:54:35 -0900", "%Y-%b-%dT%H:%M:%S %z").is_err());
1135+
assert!(parse("2013-AG-09T23:54:35 -0900", "%Y-%b-%dT%H:%M:%S %z").is_err());
1136+
assert!(parse("2013-AUG.-09T23:54:35 -0900", "%Y-%b-%dT%H:%M:%S %z").is_err());
1137+
assert!(parse("2013-AUGU-09T23:54:35 -0900", "%Y-%b-%dT%H:%M:%S %z").is_err());
1138+
assert!(parse("2013-AUGUST-09T23:54:35 -0900", "%Y-%b-%dT%H:%M:%S %z").is_err());
1139+
1140+
//
1141+
// %h
1142+
//
1143+
// ok
1144+
assert_eq!(parse("2013-Aug-09T23:54:35 -0900", "%Y-%h-%dT%H:%M:%S %z"), Ok(dt));
1145+
assert_eq!(parse("2013aug-09T23:54:35 -0900", "%Y%h-%dT%H:%M:%S %z"), Ok(dt));
1146+
assert_eq!(parse("2013-AUG09T23:54:35 -0900", "%Y-%h%dT%H:%M:%S %z"), Ok(dt));
1147+
assert_eq!(parse("2013aug09T23:54:35 -0900", "%Y%h%dT%H:%M:%S %z"), Ok(dt));
1148+
assert_eq!(parse("2013aug09235435-0900", "%Y%h%d%H%M%S%z"), Ok(dt));
1149+
assert_eq!(parse_month("2013jan09235435-0900", "%Y%h%d%H%M%S%z"), 1);
1150+
assert_eq!(parse_month("2013feb09235435-0900", "%Y%h%d%H%M%S%z"), 2);
1151+
assert_eq!(parse_month("2013mar09235435-0900", "%Y%h%d%H%M%S%z"), 3);
1152+
assert_eq!(parse_month("2013apr09235435-0900", "%Y%h%d%H%M%S%z"), 4);
1153+
assert_eq!(parse_month("2013may09235435-0900", "%Y%h%d%H%M%S%z"), 5);
1154+
assert_eq!(parse_month("2013jun09235435-0900", "%Y%h%d%H%M%S%z"), 6);
1155+
assert_eq!(parse_month("2013jul09235435-0900", "%Y%h%d%H%M%S%z"), 7);
1156+
assert_eq!(parse_month("2013aug09235435-0900", "%Y%h%d%H%M%S%z"), 8);
1157+
assert_eq!(parse_month("2013sep09235435-0900", "%Y%h%d%H%M%S%z"), 9);
1158+
assert_eq!(parse_month("2013oct09235435-0900", "%Y%h%d%H%M%S%z"), 10);
1159+
assert_eq!(parse_month("2013nov09235435-0900", "%Y%h%d%H%M%S%z"), 11);
1160+
assert_eq!(parse_month("2013dec09235435-0900", "%Y%h%d%H%M%S%z"), 12);
1161+
// errors
1162+
assert!(parse("2013-AWG-09T23:54:35 -0900", "%Y-%h-%dT%H:%M:%S %z").is_err());
1163+
assert!(parse("2013-AU-09T23:54:35 -0900", "%Y-%h-%dT%H:%M:%S %z").is_err());
1164+
assert!(parse("2013-AG-09T23:54:35 -0900", "%Y-%h-%dT%H:%M:%S %z").is_err());
1165+
assert!(parse("2013-AUG.-09T23:54:35 -0900", "%Y-%h-%dT%H:%M:%S %z").is_err());
1166+
assert!(parse("2013-AUGU-09T23:54:35 -0900", "%Y-%h-%dT%H:%M:%S %z").is_err());
1167+
assert!(parse("2013-AUGUST-09T23:54:35 -0900", "%Y-%h-%dT%H:%M:%S %z").is_err());
1168+
1169+
//
1170+
// %B
1171+
//
1172+
// ok
1173+
assert_eq!(parse("2013-August-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z"), Ok(dt));
1174+
assert_eq!(parse("2013-aUgUsT-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z"), Ok(dt));
1175+
assert_eq!(parse("2013-august-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z"), Ok(dt));
1176+
assert_eq!(parse("2013august-09T23:54:35 -0900", "%Y%B-%dT%H:%M:%S %z"), Ok(dt));
1177+
assert_eq!(parse("2013-AUGust09T23:54:35 -0900", "%Y-%B%dT%H:%M:%S %z"), Ok(dt));
1178+
assert_eq!(parse("2013august09T23:54:35 -0900", "%Y%B%dT%H:%M:%S %z"), Ok(dt));
1179+
assert_eq!(parse("2013august09235435-0900", "%Y%B%d%H%M%S%z"), Ok(dt));
1180+
assert_eq!(parse_month("2013january09235435-0900", "%Y%B%d%H%M%S%z"), 1);
1181+
assert_eq!(parse_month("2013february09235435-0900", "%Y%B%d%H%M%S%z"), 2);
1182+
assert_eq!(parse_month("2013march09235435-0900", "%Y%B%d%H%M%S%z"), 3);
1183+
assert_eq!(parse_month("2013april09235435-0900", "%Y%B%d%H%M%S%z"), 4);
1184+
assert_eq!(parse_month("2013may09235435-0900", "%Y%B%d%H%M%S%z"), 5);
1185+
assert_eq!(parse_month("2013june09235435-0900", "%Y%B%d%H%M%S%z"), 6);
1186+
assert_eq!(parse_month("2013july09235435-0900", "%Y%B%d%H%M%S%z"), 7);
1187+
assert_eq!(parse_month("2013august09235435-0900", "%Y%B%d%H%M%S%z"), 8);
1188+
assert_eq!(parse_month("2013september09235435-0900", "%Y%B%d%H%M%S%z"), 9);
1189+
assert_eq!(parse_month("2013october09235435-0900", "%Y%B%d%H%M%S%z"), 10);
1190+
assert_eq!(parse_month("2013november09235435-0900", "%Y%B%d%H%M%S%z"), 11);
1191+
assert_eq!(parse_month("2013december09235435-0900", "%Y%B%d%H%M%S%z"), 12);
1192+
// errors
1193+
assert!(parse("2013-AUGUS-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z").is_err());
1194+
assert!(parse("2013-AUGU-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z").is_err());
1195+
assert!(parse("2013-AUG.-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z").is_err());
1196+
assert!(parse("2013-AG-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z").is_err());
1197+
assert!(parse("2013-A-09T23:54:35 -0900", "%Y-%B-%dT%H:%M:%S %z").is_err());
1198+
}
1199+
1200+
/// Test `parse_from_str` focused on strftime `%Z`, `%z`, `%:z`, and `%::z` specifiers.
1201+
#[test]
1202+
fn test_datetime_parse_from_str_timezone() {
9941203
let dt = ymdhms(&FixedOffset::east_opt(-9 * 60 * 60).unwrap(), 2013, 8, 9, 23, 54, 35);
9951204
let parse = DateTime::<FixedOffset>::parse_from_str;
9961205

src/naive/date.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ use crate::{Datelike, TimeDelta, Weekday};
2828
use super::internals::{self, DateImpl, Mdf, Of, YearFlags};
2929
use super::isoweek;
3030

31-
const MAX_YEAR: i32 = internals::MAX_YEAR;
32-
const MIN_YEAR: i32 = internals::MIN_YEAR;
31+
pub(crate) const MAX_YEAR: i32 = internals::MAX_YEAR;
32+
pub(crate) const MIN_YEAR: i32 = internals::MIN_YEAR;
3333

3434
// MAX_YEAR-12-31 minus 0000-01-01
3535
// = ((MAX_YEAR+1)-01-01 minus 0001-01-01) + (0001-01-01 minus 0000-01-01) - 1 day

src/naive/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! (e.g. [`TimeZone`](../offset/trait.TimeZone.html)),
55
//! but can be also used for the simpler date and time handling.
66
7-
mod date;
7+
pub(crate) mod date;
88
pub(crate) mod datetime;
99
mod internals;
1010
mod isoweek;

0 commit comments

Comments
 (0)