diff --git a/src/format/parse.rs b/src/format/parse.rs
index 5a3a702734..2c1089004c 100644
--- a/src/format/parse.rs
+++ b/src/format/parse.rs
@@ -279,6 +279,32 @@ where
     parse_internal(parsed, s, items)
 }
 
+fn get_numeric_item_len<'a, B>(item: Option<&B>) -> Option<usize>
+where
+    B: Borrow<Item<'a>>,
+{
+    use super::Fixed::*;
+
+    item.map(|i| match *i.borrow() {
+        Item::Fixed(Internal(InternalFixed { val: InternalInternal::Nanosecond3NoDot })) => 3,
+        Item::Fixed(Internal(InternalFixed { val: InternalInternal::Nanosecond6NoDot })) => 6,
+        Item::Fixed(Internal(InternalFixed { val: InternalInternal::Nanosecond9NoDot })) => 9,
+        Item::Literal(prefix) => {
+            prefix.as_bytes().iter().take_while(|&&c| c.is_ascii_digit()).count()
+        }
+        _ => 0,
+    })
+}
+
+fn recalculate_numeric_item_width<'a, B>(s: &str, next_item: Option<&B>) -> usize
+where
+    B: Borrow<Item<'a>>,
+{
+    let next_width = get_numeric_item_len(next_item).unwrap_or(0);
+    let numeric_bytes_available = s.as_bytes().iter().take_while(|&&c| c.is_ascii_digit()).count();
+    numeric_bytes_available - next_width
+}
+
 fn parse_internal<'a, 'b, I, B>(
     parsed: &mut Parsed,
     mut s: &'b str,
@@ -300,7 +326,10 @@ where
         }};
     }
 
-    for item in items {
+    let mut items_iter = items.peekable();
+
+    while let Some(item) = items_iter.next() {
+        let next_item = items_iter.peek();
         match *item.borrow() {
             Item::Literal(prefix) => {
                 if s.len() < prefix.len() {
@@ -336,7 +365,16 @@ where
                 use super::Numeric::*;
                 type Setter = fn(&mut Parsed, i64) -> ParseResult<()>;
 
-                let (width, signed, set): (usize, bool, Setter) = match *spec {
+                s = s.trim_start();
+                let mut substr = s;
+                let negative = s.starts_with('-');
+                let positive = s.starts_with('+');
+                let starts_with_sign = negative || positive;
+                if starts_with_sign {
+                    substr = &s[1..];
+                }
+
+                let (mut width, signed, set): (usize, bool, Setter) = match *spec {
                     Year => (4, true, Parsed::set_year),
                     YearDiv100 => (2, false, Parsed::set_year_div_100),
                     YearMod100 => (2, false, Parsed::set_year_mod_100),
@@ -356,26 +394,25 @@ where
                     Minute => (2, false, Parsed::set_minute),
                     Second => (2, false, Parsed::set_second),
                     Nanosecond => (9, false, Parsed::set_nanosecond),
-                    Timestamp => (usize::MAX, false, Parsed::set_timestamp),
+                    Timestamp => (
+                        recalculate_numeric_item_width(substr, next_item),
+                        false,
+                        Parsed::set_timestamp,
+                    ),
 
                     // for the future expansion
                     Internal(ref int) => match int._dummy {},
                 };
 
-                s = s.trim_start();
-                let v = if signed {
-                    if s.starts_with('-') {
-                        let v = try_consume!(scan::number(&s[1..], 1, usize::MAX));
-                        0i64.checked_sub(v).ok_or(OUT_OF_RANGE)?
-                    } else if s.starts_with('+') {
-                        try_consume!(scan::number(&s[1..], 1, usize::MAX))
-                    } else {
-                        // if there is no explicit sign, we respect the original `width`
-                        try_consume!(scan::number(s, 1, width))
-                    }
-                } else {
-                    try_consume!(scan::number(s, 1, width))
-                };
+                if starts_with_sign && signed {
+                    width = recalculate_numeric_item_width(substr, next_item);
+                } else if starts_with_sign {
+                    return Err(INVALID);
+                }
+
+                let v = try_consume!(scan::number(substr, 1, width));
+                let v = if negative { 0i64.checked_sub(v).ok_or(OUT_OF_RANGE)? } else { v };
+
                 set(parsed, v)?;
             }
 
@@ -765,6 +802,7 @@ mod tests {
             &[num(Year), Space(" "), Literal("x"), Space(" "), Literal("1235")],
             parsed!(year: 1234),
         );
+        check("12341235", &[num(Year), Literal("1235")], parsed!(year: 1234));
 
         // signed numeric
         check("-42", &[num(Year)], parsed!(year: -42));
@@ -777,9 +815,12 @@ mod tests {
         check("  -42195", &[num(Year)], parsed!(year: -42195));
         check(" +42195", &[num(Year)], parsed!(year: 42195));
         check("  -42195", &[num(Year)], parsed!(year: -42195));
+        check("  -42195123", &[num(Year), Literal("123")], parsed!(year: -42195));
         check("  +42195", &[num(Year)], parsed!(year: 42195));
+        check("  +42195123", &[num(Year), Literal("123")], parsed!(year: 42195));
         check("-42195 ", &[num(Year)], Err(TOO_LONG));
         check("+42195 ", &[num(Year)], Err(TOO_LONG));
+        check("+42195123 ", &[num(Year), Literal("123")], Err(TOO_LONG));
         check("  -   42", &[num(Year)], Err(INVALID));
         check("  +   42", &[num(Year)], Err(INVALID));
         check("  -42195", &[Space("  "), num(Year)], parsed!(year: -42195));
@@ -1482,6 +1523,15 @@ mod tests {
                 second: 5, nanosecond: 567000000
             ),
         );
+        check(
+            "20151230204",
+            &[
+                num(Year), Literal("123"), num(Month), num(Day)
+            ],
+            parsed!(
+                year: 2015, month: 2, day: 4
+            ),
+        );
         check(
             "Mon, 10 Jun 2013 09:32:37 GMT",
             &[
@@ -1537,6 +1587,31 @@ mod tests {
             &[num(Timestamp), Literal("."), num(Nanosecond)],
             parsed!(nanosecond: 56_789, timestamp: 12_345_678_901_234),
         );
+        check(
+            "12345678901234111",
+            &[num(Timestamp), Literal("111")],
+            parsed!(timestamp: 12_345_678_901_234),
+        );
+        check(
+            "12345678901234567",
+            &[num(Timestamp), internal_fixed(Nanosecond3NoDot)],
+            parsed!(nanosecond: 567_000_000, timestamp: 12_345_678_901_234),
+        );
+        check(
+            "12345678901234567",
+            &[num(Timestamp), internal_fixed(Nanosecond3NoDot)],
+            parsed!(nanosecond: 567_000_000, timestamp: 12_345_678_901_234),
+        );
+        check(
+            "12345678901234567890",
+            &[num(Timestamp), internal_fixed(Nanosecond6NoDot)],
+            parsed!(nanosecond: 567_890_000, timestamp: 12_345_678_901_234),
+        );
+        check(
+            "12345678901234567890123",
+            &[num(Timestamp), internal_fixed(Nanosecond9NoDot)],
+            parsed!(nanosecond: 567_890_123, timestamp: 12_345_678_901_234),
+        );
         check(
             "12345678901234.56789",
             &[num(Timestamp), fixed(Fixed::Nanosecond)],
diff --git a/src/format/scan.rs b/src/format/scan.rs
index 1ab87b9dd5..3e67808479 100644
--- a/src/format/scan.rs
+++ b/src/format/scan.rs
@@ -15,8 +15,6 @@ use crate::Weekday;
 /// Any number that does not fit in `i64` is an error.
 #[inline]
 pub(super) fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)> {
-    assert!(min <= max);
-
     // We are only interested in ascii numbers, so we can work with the `str` as bytes. We stop on
     // the first non-numeric byte, which may be another ascii character or beginning of multi-byte
     // UTF-8 character.
@@ -25,6 +23,10 @@ pub(super) fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)
         return Err(TOO_SHORT);
     }
 
+    if min > max {
+        return Err(INVALID);
+    }
+
     let mut n = 0i64;
     for (i, c) in bytes.iter().take(max).cloned().enumerate() {
         // cloned() = copied()
diff --git a/src/naive/datetime/tests.rs b/src/naive/datetime/tests.rs
index 161245813d..d48bb22158 100644
--- a/src/naive/datetime/tests.rs
+++ b/src/naive/datetime/tests.rs
@@ -191,6 +191,10 @@ fn test_datetime_parse_from_str() {
         NaiveDateTime::parse_from_str("2014-5-7T12:34:56+09:30", "%Y-%m-%dT%H:%M:%S%z"),
         Ok(ymdhms(2014, 5, 7, 12, 34, 56))
     ); // ignore offset
+    assert_eq!(
+        NaiveDateTime::parse_from_str("2014123-5-7T12:34:56+09:30", "%Y123-%m-%dT%H:%M:%S%z"),
+        Ok(ymdhms(2014, 5, 7, 12, 34, 56))
+    ); // ignore offset
     assert_eq!(
         NaiveDateTime::parse_from_str("2015-W06-1 000000", "%G-W%V-%u%H%M%S"),
         Ok(ymdhms(2015, 2, 2, 0, 0, 0))
@@ -218,14 +222,26 @@ fn test_datetime_parse_from_str() {
         NaiveDateTime::parse_from_str("1441497364.649", "%s%.3f"),
         Ok(ymdhmsn(2015, 9, 5, 23, 56, 4, 649000000))
     );
+    assert_eq!(
+        NaiveDateTime::parse_from_str("1441497364649", "%s%3f"),
+        Ok(ymdhmsn(2015, 9, 5, 23, 56, 4, 649000000))
+    );
     assert_eq!(
         NaiveDateTime::parse_from_str("1497854303.087654", "%s%.6f"),
         Ok(ymdhmsn(2017, 6, 19, 6, 38, 23, 87654000))
     );
+    assert_eq!(
+        NaiveDateTime::parse_from_str("1497854303087654", "%s%6f"),
+        Ok(ymdhmsn(2017, 6, 19, 6, 38, 23, 87654000))
+    );
     assert_eq!(
         NaiveDateTime::parse_from_str("1437742189.918273645", "%s%.9f"),
         Ok(ymdhmsn(2015, 7, 24, 12, 49, 49, 918273645))
     );
+    assert_eq!(
+        NaiveDateTime::parse_from_str("1437742189918273645", "%s%9f"),
+        Ok(ymdhmsn(2015, 7, 24, 12, 49, 49, 918273645))
+    );
 }
 
 #[test]