summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Henstridge <james@jamesh.id.au>2009-02-17 15:03:33 +0900
committerJames Henstridge <james@jamesh.id.au>2009-02-17 15:03:33 +0900
commit2a94dfae47c10426be7e9b7babdf89548cfbe24d (patch)
tree5fb1a7a966b18de54400da41401dba732ac6413b
parentba8be438bb174fda02adf06d3a0691b9cdee8f11 (diff)
downloadpsycopg2-2a94dfae47c10426be7e9b7babdf89548cfbe24d.tar.gz
* tests/test_dates.py (DatetimeTests, mxDateTimeTests): full test
coverage for datetime and time strings with and without time zone information. * psycopg/typecast_datetime.c (typecast_PYDATETIME_cast): adjust to handle the changes in typecast_parse_time. (typecast_PYTIME_cast): add support for time zone aware time values. * psycopg/typecast_mxdatetime.c (typecast_MXDATE_cast): make sure that values with time zones are correctly processed (even though that means ignoring the time zone value). (typecast_MXTIME_cast): same here. * psycopg/typecast.c (typecast_parse_time): Update method to parse second resolution timezone offsets.
-rw-r--r--ChangeLog17
-rw-r--r--psycopg/typecast.c12
-rw-r--r--psycopg/typecast_datetime.c70
-rw-r--r--psycopg/typecast_mxdatetime.c4
-rw-r--r--tests/test_dates.py204
5 files changed, 224 insertions, 83 deletions
diff --git a/ChangeLog b/ChangeLog
index b8a5723..b89be49 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2009-02-17 James Henstridge <james@jamesh.id.au>
+ * tests/test_dates.py (DatetimeTests, mxDateTimeTests): full test
+ coverage for datetime and time strings with and without time zone
+ information.
+
+ * psycopg/typecast_datetime.c (typecast_PYDATETIME_cast): adjust
+ to handle the changes in typecast_parse_time.
+ (typecast_PYTIME_cast): add support for time zone aware time
+ values.
+
+ * psycopg/typecast_mxdatetime.c (typecast_MXDATE_cast): make sure
+ that values with time zones are correctly processed (even though
+ that means ignoring the time zone value).
+ (typecast_MXTIME_cast): same here.
+
+ * psycopg/typecast.c (typecast_parse_time): Update method to parse
+ second resolution timezone offsets.
+
* psycopg/typecast.c (typecast_parse_time): Fix up handling of
negative timezone offsets with a non-zero minutes field.
diff --git a/psycopg/typecast.c b/psycopg/typecast.c
index a21b30f..07bb1f5 100644
--- a/psycopg/typecast.c
+++ b/psycopg/typecast.c
@@ -96,7 +96,7 @@ typecast_parse_time(const char* s, const char** t, Py_ssize_t* len,
int* hh, int* mm, int* ss, int* us, int* tz)
{
int acc = -1, cz = 0;
- int tzs = 1, tzhh = 0, tzmm = 0;
+ int tzsign = 1, tzhh = 0, tzmm = 0, tzss = 0;
int usd = 0;
/* sets microseconds and timezone to 0 because they may be missing */
@@ -105,7 +105,7 @@ typecast_parse_time(const char* s, const char** t, Py_ssize_t* len,
Dprintf("typecast_parse_time: len = " FORMAT_CODE_PY_SSIZE_T ", s = %s",
*len, s);
- while (cz < 6 && *len > 0 && *s) {
+ while (cz < 7 && *len > 0 && *s) {
switch (*s) {
case ':':
if (cz == 0) *hh = acc;
@@ -113,6 +113,7 @@ typecast_parse_time(const char* s, const char** t, Py_ssize_t* len,
else if (cz == 2) *ss = acc;
else if (cz == 3) *us = acc;
else if (cz == 4) tzhh = acc;
+ else if (cz == 5) tzmm = acc;
acc = -1; cz++;
break;
case '.':
@@ -125,7 +126,7 @@ typecast_parse_time(const char* s, const char** t, Py_ssize_t* len,
case '-':
/* seconds or microseconds here, anything else is an error */
if (cz < 2 || cz > 3) return -1;
- if (*s == '-') tzs = -1;
+ if (*s == '-') tzsign = -1;
if (cz == 2) *ss = acc;
else if (cz == 3) *us = acc;
acc = -1; cz = 4;
@@ -151,11 +152,12 @@ typecast_parse_time(const char* s, const char** t, Py_ssize_t* len,
else if (cz == 2) { *ss = acc; cz += 1; }
else if (cz == 3) { *us = acc; cz += 1; }
else if (cz == 4) { tzhh = acc; cz += 1; }
- else if (cz == 5) tzmm = acc;
+ else if (cz == 5) { tzmm = acc; cz += 1; }
+ else if (cz == 6) tzss = acc;
}
if (t != NULL) *t = s;
- *tz = tzs * (tzhh * 60 + tzmm);
+ *tz = tzsign * (3600 * tzhh + 60 * tzmm + tzss);
if (*us != 0) {
while (usd++ < 6) *us *= 10;
diff --git a/psycopg/typecast_datetime.c b/psycopg/typecast_datetime.c
index 8144850..0256032 100644
--- a/psycopg/typecast_datetime.c
+++ b/psycopg/typecast_datetime.c
@@ -74,6 +74,8 @@ static PyObject *
typecast_PYDATETIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
{
PyObject* obj = NULL;
+ PyObject *tzinfo = NULL;
+ PyObject *tzinfo_factory;
int n, y=0, m=0, d=0;
int hh=0, mm=0, ss=0, us=0, tz=0;
const char *tp = NULL;
@@ -108,7 +110,7 @@ typecast_PYDATETIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
" len = " FORMAT_CODE_PY_SSIZE_T ","
" hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
n, len, hh, mm, ss, us, tz);
- if (n < 3 || n > 5) {
+ if (n < 3 || n > 6) {
PyErr_SetString(DataError, "unable to parse time");
return NULL;
}
@@ -121,24 +123,34 @@ typecast_PYDATETIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
if (y > 9999)
y = 9999;
- if (n == 5 && ((cursorObject*)curs)->tzinfo_factory != Py_None) {
+ tzinfo_factory = ((cursorObject *)curs)->tzinfo_factory;
+ if (n >= 5 && tzinfo_factory != Py_None) {
/* we have a time zone, calculate minutes and create
appropriate tzinfo object calling the factory */
- PyObject *tzinfo;
- Dprintf("typecast_PYDATETIME_cast: UTC offset = %dm", tz);
- tzinfo = PyObject_CallFunction(
- ((cursorObject*)curs)->tzinfo_factory, "i", tz);
+ Dprintf("typecast_PYDATETIME_cast: UTC offset = %ds", tz);
+
+ /* The datetime module requires that time zone offsets be
+ a whole number of minutes, so fail if we have a time
+ zone with a seconds offset.
+ */
+ if (tz % 60 != 0) {
+ PyErr_Format(PyExc_ValueError, "time zone offset %d is not "
+ "a whole number of minutes", tz);
+ return NULL;
+ }
+ tzinfo = PyObject_CallFunction(tzinfo_factory, "i", tz / 60);
+ } else {
+ Py_INCREF(Py_None);
+ tzinfo = Py_None;
+ }
+ if (tzinfo != NULL) {
obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
y, m, d, hh, mm, ss, us, tzinfo);
Dprintf("typecast_PYDATETIME_cast: tzinfo: %p, refcnt = "
FORMAT_CODE_PY_SSIZE_T,
tzinfo, tzinfo->ob_refcnt
);
- Py_XDECREF(tzinfo);
- }
- else {
- obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiii",
- y, m, d, hh, mm, ss, us);
+ Py_DECREF(tzinfo);
}
}
return obj;
@@ -150,6 +162,8 @@ static PyObject *
typecast_PYTIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
{
PyObject* obj = NULL;
+ PyObject *tzinfo = NULL;
+ PyObject *tzinfo_factory;
int n, hh=0, mm=0, ss=0, us=0, tz=0;
if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
@@ -159,16 +173,38 @@ typecast_PYTIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
"hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
n, len, hh, mm, ss, us, tz);
- if (n < 3 || n > 5) {
+ if (n < 3 || n > 6) {
PyErr_SetString(DataError, "unable to parse time");
return NULL;
}
- else {
- if (ss > 59) {
- mm += 1;
- ss -= 60;
+ if (ss > 59) {
+ mm += 1;
+ ss -= 60;
+ }
+ tzinfo_factory = ((cursorObject *)curs)->tzinfo_factory;
+ if (n >= 5 && tzinfo_factory != Py_None) {
+ /* we have a time zone, calculate minutes and create
+ appropriate tzinfo object calling the factory */
+ Dprintf("typecast_PYTIME_cast: UTC offset = %ds", tz);
+
+ /* The datetime module requires that time zone offsets be
+ a whole number of minutes, so fail if we have a time
+ zone with a seconds offset.
+ */
+ if (tz % 60 != 0) {
+ PyErr_Format(PyExc_ValueError, "time zone offset %d is not "
+ "a whole number of minutes", tz);
+ return NULL;
}
- obj = PyObject_CallFunction(pyTimeTypeP, "iiii", hh, mm, ss, us);
+ tzinfo = PyObject_CallFunction(tzinfo_factory, "i", tz / 60);
+ } else {
+ Py_INCREF(Py_None);
+ tzinfo = Py_None;
+ }
+ if (tzinfo != NULL) {
+ obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
+ hh, mm, ss, us, tzinfo);
+ Py_DECREF(tzinfo);
}
return obj;
}
diff --git a/psycopg/typecast_mxdatetime.c b/psycopg/typecast_mxdatetime.c
index e030091..eac220f 100644
--- a/psycopg/typecast_mxdatetime.c
+++ b/psycopg/typecast_mxdatetime.c
@@ -63,7 +63,7 @@ typecast_MXDATE_cast(const char *str, Py_ssize_t len, PyObject *curs)
" len = " FORMAT_CODE_PY_SSIZE_T ","
" hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
n, len, hh, mm, ss, us, tz);
- if (n != 0 && (n < 3 || n > 5)) {
+ if (n != 0 && (n < 3 || n > 6)) {
PyErr_SetString(DataError, "unable to parse time");
return NULL;
}
@@ -91,7 +91,7 @@ typecast_MXTIME_cast(const char *str, Py_ssize_t len, PyObject *curs)
Dprintf("typecast_MXTIME_cast: hh = %d, mm = %d, ss = %d, us = %d",
hh, mm, ss, us);
- if (n < 3 || n > 5) {
+ if (n < 3 || n > 6) {
PyErr_SetString(DataError, "unable to parse time");
return NULL;
}
diff --git a/tests/test_dates.py b/tests/test_dates.py
index eda4e89..7b9e59f 100644
--- a/tests/test_dates.py
+++ b/tests/test_dates.py
@@ -10,43 +10,41 @@ import tests
class CommonDatetimeTestsMixin:
def execute(self, *args):
- conn = psycopg2.connect(tests.dsn)
- curs = conn.cursor()
- curs.execute(*args)
- return curs.fetchone()[0]
+ self.curs.execute(*args)
+ return self.curs.fetchone()[0]
def test_parse_date(self):
- value = self.DATE('2007-01-01', None)
+ value = self.DATE('2007-01-01', self.curs)
self.assertNotEqual(value, None)
self.assertEqual(value.year, 2007)
self.assertEqual(value.month, 1)
self.assertEqual(value.day, 1)
def test_parse_null_date(self):
- value = self.DATE(None, None)
+ value = self.DATE(None, self.curs)
self.assertEqual(value, None)
def test_parse_incomplete_date(self):
- self.assertRaises(psycopg2.DataError, self.DATE, '2007', None)
- self.assertRaises(psycopg2.DataError, self.DATE, '2007-01', None)
+ self.assertRaises(psycopg2.DataError, self.DATE, '2007', self.curs)
+ self.assertRaises(psycopg2.DataError, self.DATE, '2007-01', self.curs)
def test_parse_time(self):
- value = self.TIME('13:30:29', None)
+ value = self.TIME('13:30:29', self.curs)
self.assertNotEqual(value, None)
self.assertEqual(value.hour, 13)
self.assertEqual(value.minute, 30)
self.assertEqual(value.second, 29)
def test_parse_null_time(self):
- value = self.TIME(None, None)
+ value = self.TIME(None, self.curs)
self.assertEqual(value, None)
def test_parse_incomplete_time(self):
- self.assertRaises(psycopg2.DataError, self.TIME, '13', None)
- self.assertRaises(psycopg2.DataError, self.TIME, '13:30', None)
+ self.assertRaises(psycopg2.DataError, self.TIME, '13', self.curs)
+ self.assertRaises(psycopg2.DataError, self.TIME, '13:30', self.curs)
def test_parse_datetime(self):
- value = self.DATETIME('2007-01-01 13:30:29', None)
+ value = self.DATETIME('2007-01-01 13:30:29', self.curs)
self.assertNotEqual(value, None)
self.assertEqual(value.year, 2007)
self.assertEqual(value.month, 1)
@@ -56,23 +54,21 @@ class CommonDatetimeTestsMixin:
self.assertEqual(value.second, 29)
def test_parse_null_datetime(self):
- value = self.DATETIME(None, None)
+ value = self.DATETIME(None, self.curs)
self.assertEqual(value, None)
def test_parse_incomplete_time(self):
self.assertRaises(psycopg2.DataError,
- self.DATETIME, '2007', None)
+ self.DATETIME, '2007', self.curs)
self.assertRaises(psycopg2.DataError,
- self.DATETIME, '2007-01', None)
+ self.DATETIME, '2007-01', self.curs)
self.assertRaises(psycopg2.DataError,
- self.DATETIME, '2007-01-01 13', None)
+ self.DATETIME, '2007-01-01 13', self.curs)
self.assertRaises(psycopg2.DataError,
- self.DATETIME, '2007-01-01 13:30', None)
- self.assertRaises(psycopg2.DataError,
- self.DATETIME, '2007-01-01 13:30:29+00:10:50', None)
+ self.DATETIME, '2007-01-01 13:30', self.curs)
def test_parse_null_interval(self):
- value = self.INTERVAL(None, None)
+ value = self.INTERVAL(None, self.curs)
self.assertEqual(value, None)
@@ -80,80 +76,137 @@ class DatetimeTests(unittest.TestCase, CommonDatetimeTestsMixin):
"""Tests for the datetime based date handling in psycopg2."""
def setUp(self):
+ self.conn = psycopg2.connect(tests.dsn)
+ self.curs = self.conn.cursor()
self.DATE = psycopg2._psycopg.PYDATE
self.TIME = psycopg2._psycopg.PYTIME
self.DATETIME = psycopg2._psycopg.PYDATETIME
self.INTERVAL = psycopg2._psycopg.PYINTERVAL
+ def tearDown(self):
+ self.conn.close()
+
def test_parse_bc_date(self):
# datetime does not support BC dates
- self.assertRaises(ValueError, self.DATE, '00042-01-01 BC', None)
+ self.assertRaises(ValueError, self.DATE, '00042-01-01 BC', self.curs)
def test_parse_bc_datetime(self):
# datetime does not support BC dates
self.assertRaises(ValueError, self.DATETIME,
- '00042-01-01 13:30:29 BC', None)
+ '00042-01-01 13:30:29 BC', self.curs)
def test_parse_time_microseconds(self):
- value = self.TIME('13:30:29.123456', None)
+ value = self.TIME('13:30:29.123456', self.curs)
self.assertEqual(value.second, 29)
self.assertEqual(value.microsecond, 123456)
def test_parse_datetime_microseconds(self):
- value = self.DATETIME('2007-01-01 13:30:29.123456', None)
+ value = self.DATETIME('2007-01-01 13:30:29.123456', self.curs)
self.assertEqual(value.second, 29)
self.assertEqual(value.microsecond, 123456)
- def check_timezone(self, curs, str_offset, offset):
+ def check_time_tz(self, str_offset, offset):
+ from datetime import time, timedelta
+ base = time(13, 30, 29)
+ base_str = '13:30:29'
+
+ value = self.TIME(base_str + str_offset, self.curs)
+
+ # Value has time zone info and correct UTC offset.
+ self.assertNotEqual(value.tzinfo, None),
+ self.assertEqual(value.utcoffset(), timedelta(seconds=offset))
+
+ # Time portion is correct.
+ self.assertEqual(value.replace(tzinfo=None), base)
+
+ def test_parse_time_timezone(self):
+ self.check_time_tz("+01", 3600)
+ self.check_time_tz("-01", -3600)
+ self.check_time_tz("+01:15", 4500)
+ self.check_time_tz("-01:15", -4500)
+ # The Python datetime module does not support time zone
+ # offsets that are not a whole number of minutes, so we get an
+ # error here. Check that we are generating an understandable
+ # error message.
+ try:
+ self.check_time_tz("+01:15:42", 4542)
+ except ValueError, exc:
+ self.assertEqual(exc.message, "time zone offset 4542 is not a "
+ "whole number of minutes")
+ else:
+ self.fail("Expected ValueError")
+
+ try:
+ self.check_time_tz("-01:15:42", -4542)
+ except ValueError, exc:
+ self.assertEqual(exc.message, "time zone offset -4542 is not a "
+ "whole number of minutes")
+ else:
+ self.fail("Expected ValueError")
+
+ def check_datetime_tz(self, str_offset, offset):
from datetime import datetime, timedelta
base = datetime(2007, 1, 1, 13, 30, 29)
base_str = '2007-01-01 13:30:29'
- value = self.DATETIME(base_str + str_offset, curs)
+ value = self.DATETIME(base_str + str_offset, self.curs)
- # tzinfo instance is correct.
- self.assertTrue(isinstance(value.tzinfo, FixedOffsetTimezone),
- "value's timezone is not a FixedOffsetTimezone")
- self.assertEqual(value.tzinfo._offset, timedelta(seconds=offset))
+ # Value has time zone info and correct UTC offset.
+ self.assertNotEqual(value.tzinfo, None),
+ self.assertEqual(value.utcoffset(), timedelta(seconds=offset))
# Datetime is correct.
self.assertEqual(value.replace(tzinfo=None), base)
- # Offset from UTC is correct.
+ # Conversion to UTC produces the expected offset.
UTC = FixedOffsetTimezone(0, "UTC")
value_utc = value.astimezone(UTC).replace(tzinfo=None)
self.assertEqual(base - value_utc, timedelta(seconds=offset))
- def test_parse_datetime_timezone_hours(self):
- conn = psycopg2.connect(tests.dsn)
- curs = conn.cursor()
- self.check_timezone(curs, "+01", 3600)
- self.check_timezone(curs, "-01", -3600)
-
- def test_parse_datetime_timezone_hours_minutes(self):
- conn = psycopg2.connect(tests.dsn)
- curs = conn.cursor()
- self.check_timezone(curs, "+01:15", 4500)
- self.check_timezone(curs, "-01:15", -4500)
-
- # This test is disabled because we don't support parsing second
- # resolution timezone offsets and Python wouldn't handle them even
- # if we did.
- def disabled_test_parse_datetime_timezone_hours_minutes_seconds(self):
- conn = psycopg2.connect(tests.dsn)
- curs = conn.cursor()
- self.check_timezone(curs, "+01:15:42", 4542)
- self.check_timezone(curs, "-01:15:42", -4542)
+ def test_parse_datetime_timezone(self):
+ self.check_datetime_tz("+01", 3600)
+ self.check_datetime_tz("-01", -3600)
+ self.check_datetime_tz("+01:15", 4500)
+ self.check_datetime_tz("-01:15", -4500)
+ # The Python datetime module does not support time zone
+ # offsets that are not a whole number of minutes, so we get an
+ # error here. Check that we are generating an understandable
+ # error message.
+ try:
+ self.check_datetime_tz("+01:15:42", 4542)
+ except ValueError, exc:
+ self.assertEqual(exc.message, "time zone offset 4542 is not a "
+ "whole number of minutes")
+ else:
+ self.fail("Expected ValueError")
+
+ try:
+ self.check_datetime_tz("-01:15:42", -4542)
+ except ValueError, exc:
+ self.assertEqual(exc.message, "time zone offset -4542 is not a "
+ "whole number of minutes")
+ else:
+ self.fail("Expected ValueError")
+
+ def test_parse_time_no_timezone(self):
+ self.assertEqual(self.TIME("13:30:29", self.curs).tzinfo, None)
+ self.assertEqual(self.TIME("13:30:29.123456", self.curs).tzinfo, None)
+
+ def test_parse_datetime_no_timezone(self):
+ self.assertEqual(
+ self.DATETIME("2007-01-01 13:30:29", self.curs).tzinfo, None)
+ self.assertEqual(
+ self.DATETIME("2007-01-01 13:30:29.123456", self.curs).tzinfo, None)
def test_parse_interval(self):
- value = self.INTERVAL('42 days 12:34:56.123456', None)
+ value = self.INTERVAL('42 days 12:34:56.123456', self.curs)
self.assertNotEqual(value, None)
self.assertEqual(value.days, 42)
self.assertEqual(value.seconds, 45296)
self.assertEqual(value.microseconds, 123456)
def test_parse_negative_interval(self):
- value = self.INTERVAL('-42 days -12:34:56.123456', None)
+ value = self.INTERVAL('-42 days -12:34:56.123456', self.curs)
self.assertNotEqual(value, None)
self.assertEqual(value.days, -43)
self.assertEqual(value.seconds, 41103)
@@ -205,13 +258,18 @@ class mxDateTimeTests(unittest.TestCase, CommonDatetimeTestsMixin):
"""Tests for the mx.DateTime based date handling in psycopg2."""
def setUp(self):
+ self.conn = psycopg2.connect(tests.dsn)
+ self.curs = self.conn.cursor()
self.DATE = psycopg2._psycopg.MXDATE
self.TIME = psycopg2._psycopg.MXTIME
self.DATETIME = psycopg2._psycopg.MXDATETIME
self.INTERVAL = psycopg2._psycopg.MXINTERVAL
+ def tearDown(self):
+ self.conn.close()
+
def test_parse_bc_date(self):
- value = self.DATE('00042-01-01 BC', None)
+ value = self.DATE('00042-01-01 BC', self.curs)
self.assertNotEqual(value, None)
# mx.DateTime numbers BC dates from 0 rather than 1.
self.assertEqual(value.year, -41)
@@ -219,7 +277,7 @@ class mxDateTimeTests(unittest.TestCase, CommonDatetimeTestsMixin):
self.assertEqual(value.day, 1)
def test_parse_bc_datetime(self):
- value = self.DATETIME('00042-01-01 13:30:29 BC', None)
+ value = self.DATETIME('00042-01-01 13:30:29 BC', self.curs)
self.assertNotEqual(value, None)
# mx.DateTime numbers BC dates from 0 rather than 1.
self.assertEqual(value.year, -41)
@@ -230,19 +288,47 @@ class mxDateTimeTests(unittest.TestCase, CommonDatetimeTestsMixin):
self.assertEqual(value.second, 29)
def test_parse_time_microseconds(self):
- value = self.TIME('13:30:29.123456', None)
+ value = self.TIME('13:30:29.123456', self.curs)
self.assertEqual(math.floor(value.second), 29)
self.assertEqual(
int((value.second - math.floor(value.second)) * 1000000), 123456)
def test_parse_datetime_microseconds(self):
- value = self.DATETIME('2007-01-01 13:30:29.123456', None)
+ value = self.DATETIME('2007-01-01 13:30:29.123456', self.curs)
self.assertEqual(math.floor(value.second), 29)
self.assertEqual(
int((value.second - math.floor(value.second)) * 1000000), 123456)
+ def test_parse_time_timezone(self):
+ # Time zone information is ignored.
+ from mx.DateTime import Time
+ expected = Time(13, 30, 29)
+ self.assertEqual(expected, self.TIME("13:30:29+01", self.curs))
+ self.assertEqual(expected, self.TIME("13:30:29-01", self.curs))
+ self.assertEqual(expected, self.TIME("13:30:29+01:15", self.curs))
+ self.assertEqual(expected, self.TIME("13:30:29-01:15", self.curs))
+ self.assertEqual(expected, self.TIME("13:30:29+01:15:42", self.curs))
+ self.assertEqual(expected, self.TIME("13:30:29-01:15:42", self.curs))
+
+ def test_parse_datetime_timezone(self):
+ # Time zone information is ignored.
+ from mx.DateTime import DateTime
+ expected = DateTime(2007, 1, 1, 13, 30, 29)
+ self.assertEqual(
+ expected, self.DATETIME("2007-01-01 13:30:29+01", self.curs))
+ self.assertEqual(
+ expected, self.DATETIME("2007-01-01 13:30:29-01", self.curs))
+ self.assertEqual(
+ expected, self.DATETIME("2007-01-01 13:30:29+01:15", self.curs))
+ self.assertEqual(
+ expected, self.DATETIME("2007-01-01 13:30:29-01:15", self.curs))
+ self.assertEqual(
+ expected, self.DATETIME("2007-01-01 13:30:29+01:15:42", self.curs))
+ self.assertEqual(
+ expected, self.DATETIME("2007-01-01 13:30:29-01:15:42", self.curs))
+
def test_parse_interval(self):
- value = self.INTERVAL('42 days 05:50:05', None)
+ value = self.INTERVAL('42 days 05:50:05', self.curs)
self.assertNotEqual(value, None)
self.assertEqual(value.day, 42)
self.assertEqual(value.hour, 5)