diff --git a/pandas/tseries/tests/test_timeseries.py b/pandas/tseries/tests/test_timeseries.py index a078aba2269bb..c95281d49586a 100644 --- a/pandas/tseries/tests/test_timeseries.py +++ b/pandas/tseries/tests/test_timeseries.py @@ -11,7 +11,7 @@ from pandas import (Index, Series, TimeSeries, DataFrame, isnull, date_range, Timestamp, Period, DatetimeIndex, - Int64Index, to_datetime, bdate_range, Float64Index, TimedeltaIndex) + Int64Index, to_datetime, bdate_range, Float64Index, TimedeltaIndex, NaT) import pandas.core.datetools as datetools import pandas.tseries.offsets as offsets @@ -4461,6 +4461,27 @@ def test_second(self): self.assertIsInstance(r2, Float64Index) tm.assert_index_equal(r1, r2) +class TestDaysInMonth(tm.TestCase): + # tests for issue #10154 + # Not all tests pass there are other issues, see comments on lines + def test_day_not_in_month_coerce_true_NaT(self): + self.assertTrue(isnull(to_datetime('2015-02-29', coerce=True))) + self.assertTrue(isnull(to_datetime('2015-02-29', format="%Y-%m-%d", coerce=True))) # this test fails + self.assertTrue(isnull(to_datetime('2015-02-32', format="%Y-%m-%d", coerce=True))) + self.assertTrue(isnull(to_datetime('2015-04-31', format="%Y-%m-%d", coerce=True))) # this test fails + + def test_day_not_in_month_coerce_false_raise(self): + self.assertRaises(ValueError, to_datetime, '2015-02-29', errors='raise', coerce=False) + self.assertRaises(ValueError, to_datetime, '2015-02-29', errors='raise', format="%Y-%m-%d", coerce=False) + self.assertRaises(ValueError, to_datetime, '2015-02-32', errors='raise', format="%Y-%m-%d", coerce=False) + self.assertRaises(ValueError, to_datetime, '2015-04-31', errors='raise', format="%Y-%m-%d", coerce=False) + + def test_day_not_in_month_coerce_false_ignore(self): + self.assertEqual(to_datetime('2015-02-29', errors='ignore', coerce=False), '2015-02-29') + self.assertRaises(ValueError, to_datetime, '2015-02-29', errors='ignore', format="%Y-%m-%d", coerce=False) + self.assertRaises(ValueError, to_datetime, '2015-02-32', errors='ignore', format="%Y-%m-%d", coerce=False) + self.assertRaises(ValueError, to_datetime, '2015-04-31', errors='ignore', format="%Y-%m-%d", coerce=False) + if __name__ == '__main__': nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], exit=False) diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index b3a6059db384f..27cd5e89220a9 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -2760,17 +2760,23 @@ def array_strptime(ndarray[object] values, object fmt, bint exact=True, bint coe # Cannot pre-calculate datetime_date() since can change in Julian # calculation and thus could have different value for the day of the wk # calculation. - if julian == -1: - # Need to add 1 to result since first day of the year is 1, not 0. - julian = datetime_date(year, month, day).toordinal() - \ - datetime_date(year, 1, 1).toordinal() + 1 - else: # Assume that if they bothered to include Julian day it will - # be accurate. - datetime_result = datetime_date.fromordinal( - (julian - 1) + datetime_date(year, 1, 1).toordinal()) - year = datetime_result.year - month = datetime_result.month - day = datetime_result.day + try: + if julian == -1: + # Need to add 1 to result since first day of the year is 1, not 0. + julian = datetime_date(year, month, day).toordinal() - \ + datetime_date(year, 1, 1).toordinal() + 1 + else: # Assume that if they bothered to include Julian day it will + # be accurate. + datetime_result = datetime_date.fromordinal( + (julian - 1) + datetime_date(year, 1, 1).toordinal()) + year = datetime_result.year + month = datetime_result.month + day = datetime_result.day + except ValueError: + if coerce: + iresult[i] = iNaT + continue + raise if weekday == -1: weekday = datetime_date(year, month, day).weekday()