Merge pull request #248 from pganssle/tzlocal-improvements
Add ambiguous time support to tzlocal()
diff --git a/dateutil/parser.py b/dateutil/parser.py
index 6738791..147b3f2 100644
--- a/dateutil/parser.py
+++ b/dateutil/parser.py
@@ -56,6 +56,10 @@
if isinstance(instream, text_type):
instream = StringIO(instream)
+ if getattr(instream, 'read', None) is None:
+ raise TypeError('Parser must be a string or character stream, not '
+ '{itype}'.format(itype=instream.__class__.__name__))
+
self.instream = instream
self.charstack = []
self.tokenstack = []
diff --git a/dateutil/test/test_parser.py b/dateutil/test/test_parser.py
index 20a4e78..1115bbf 100644
--- a/dateutil/test/test_parser.py
+++ b/dateutil/test/test_parser.py
@@ -7,7 +7,9 @@
from dateutil.tz import tzoffset
from dateutil.parser import *
+import six
from six import assertRaisesRegex, PY3
+from six.moves import StringIO
class ParserTest(unittest.TestCase):
@@ -30,6 +32,74 @@
with self.assertRaises(ValueError):
parse('')
+ def testNone(self):
+ with self.assertRaises(TypeError):
+ parse(None)
+
+ def testInvalidType(self):
+ with self.assertRaises(TypeError):
+ parse(13)
+
+ def testDuckTyping(self):
+ # We want to support arbitrary classes that implement the stream
+ # interface.
+
+ class StringPassThrough(object):
+ def __init__(self, stream):
+ self.stream = stream
+
+ def read(self, *args, **kwargs):
+ return self.stream.read(*args, **kwargs)
+
+
+ dstr = StringPassThrough(StringIO('2014 January 19'))
+
+ self.assertEqual(parse(dstr), datetime(2014, 1, 19))
+
+ def testParseStream(self):
+ dstr = StringIO('2014 January 19')
+
+ self.assertEqual(parse(dstr), datetime(2014, 1, 19))
+
+ def testParseStr(self):
+ self.assertEqual(parse(self.str_str),
+ parse(self.uni_str))
+
+ def testParserParseStr(self):
+ from dateutil.parser import parser
+
+ self.assertEqual(parser().parse(self.str_str),
+ parser().parse(self.uni_str))
+
+ def testParseUnicodeWords(self):
+
+ class rus_parserinfo(parserinfo):
+ MONTHS = [("янв", "Январь"),
+ ("фев", "Февраль"),
+ ("мар", "Март"),
+ ("апр", "Апрель"),
+ ("май", "Май"),
+ ("июн", "Июнь"),
+ ("июл", "Июль"),
+ ("авг", "Август"),
+ ("сен", "Сентябрь"),
+ ("окт", "Октябрь"),
+ ("ноя", "Ноябрь"),
+ ("дек", "Декабрь")]
+
+ self.assertEqual(parse('10 Сентябрь 2015 10:20',
+ parserinfo=rus_parserinfo()),
+ datetime(2015, 9, 10, 10, 20))
+
+ def testParseWithNulls(self):
+ # This relies on the from __future__ import unicode_literals, because
+ # explicitly specifying a unicode literal is a syntax error in Py 3.2
+ # May want to switch to u'...' if we ever drop Python 3.2 support.
+ pstring = '\x00\x00August 29, 1924'
+
+ self.assertEqual(parse(pstring),
+ datetime(1924, 8, 29))
+
def testDateCommandFormat(self):
self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
tzinfos=self.tzinfos),
@@ -738,45 +808,6 @@
dt = myparser.parse("01/Foo/2007")
self.assertEqual(dt, datetime(2007, 1, 1))
- def testParseStr(self):
- self.assertEqual(parse(self.str_str),
- parse(self.uni_str))
-
- def testParserParseStr(self):
- from dateutil.parser import parser
-
- self.assertEqual(parser().parse(self.str_str),
- parser().parse(self.uni_str))
-
- def testParseUnicodeWords(self):
-
- class rus_parserinfo(parserinfo):
- MONTHS = [("янв", "Январь"),
- ("фев", "Февраль"),
- ("мар", "Март"),
- ("апр", "Апрель"),
- ("май", "Май"),
- ("июн", "Июнь"),
- ("июл", "Июль"),
- ("авг", "Август"),
- ("сен", "Сентябрь"),
- ("окт", "Октябрь"),
- ("ноя", "Ноябрь"),
- ("дек", "Декабрь")]
-
- self.assertEqual(parse('10 Сентябрь 2015 10:20',
- parserinfo=rus_parserinfo()),
- datetime(2015, 9, 10, 10, 20))
-
- def testParseWithNulls(self):
- # This relies on the from __future__ import unicode_literals, because
- # explicitly specifying a unicode literal is a syntax error in Py 3.2
- # May want to switch to u'...' if we ever drop Python 3.2 support.
- pstring = '\x00\x00August 29, 1924'
-
- self.assertEqual(parse(pstring),
- datetime(1924, 8, 29))
-
def testNoYearFirstNoDayFirst(self):
dtstr = '090107'