[Jython-checkins] jython: Restores __tojava__ to datetime.{date, datetime, time} classes
jim.baker
jython-checkins at python.org
Tue Mar 3 06:24:52 CET 2015
https://hg.python.org/jython/rev/67210f355576
changeset: 7602:67210f355576
user: Jim Baker <jim.baker at rackspace.com>
date: Mon Mar 02 22:24:31 2015 -0700
summary:
Restores __tojava__ to datetime.{date, datetime, time} classes
Also adds timezone support compared to original implementation. Tests
conversions in test_datetime_jy, and this test now runs in regrtest.
Fixes http://bugs.jython.org/issue2271
files:
Lib/datetime.py | 88 ++++++++++++++++++
Lib/test/test_datetime_jy.py | 111 +++++++++++++++++++++-
2 files changed, 192 insertions(+), 7 deletions(-)
diff --git a/Lib/datetime.py b/Lib/datetime.py
--- a/Lib/datetime.py
+++ b/Lib/datetime.py
@@ -20,6 +20,49 @@
import time as _time
import math as _math
import struct as _struct
+import sys as _sys
+
+if _sys.platform.startswith('java'):
+ from java.lang import Object
+ from java.sql import Date, Time, Timestamp
+ from java.util import Calendar, GregorianCalendar, TimeZone
+ from org.python.core import Py
+
+ # Java does have the distinction between naive and aware times and
+ # datetimes provided by Python. To avoid using the local timezone,
+ # we assume it is UTC as this is most conventional (and least
+ # surprising). See for example - or in this library itself! -
+ # https://docs.python.org/2.7/library/datetime.html#datetime.datetime.utcnow
+ # - tzinfo is None
+
+ _utc_timezone = TimeZone.getTimeZone("UTC")
+ _is_jython = True
+
+ def _make_java_utc_calendar():
+ cal = GregorianCalendar(_utc_timezone)
+ cal.clear()
+ return cal
+
+ def _make_java_calendar(d):
+ tzinfo = d.tzinfo
+ if tzinfo == None:
+ cal = GregorianCalendar(_utc_timezone)
+ else:
+ tzname = tzinfo.tzname(d)
+ if tzname != None:
+ # Only applicable if Python code is using the Olson
+ # timezone database, which is what Java uses
+ tz = TimeZone.getTimeZone(tzname)
+ if tz.getID() != tzname and tz.getID() == "GMT":
+ cal = GregorianCalendar(_utc_timezone)
+ cal.set(Calendar.DST_OFFSET, int(tzinfo.dst(d).total_seconds() * 1000))
+ cal.set(Calendar.ZONE_OFFSET, int(tzinfo.utcoffset(d).total_seconds() * 1000))
+ else:
+ cal = GregorianCalendar(tz)
+ return cal
+else:
+ _is_jython = False
+
def _cmp(x, y):
return 0 if x == y else 1 if x > y else -1
@@ -1026,6 +1069,18 @@
def __reduce__(self):
return (self.__class__, self._getstate())
+ if _is_jython:
+ def __tojava__(self, java_class):
+ if java_class not in (Calendar, Date, Object):
+ return Py.NoConversion
+ calendar = _make_java_utc_calendar()
+ calendar.set(self.year, self.month - 1, self.day)
+ if java_class == Calendar:
+ return calendar
+ else:
+ return Date(calendar.getTimeInMillis())
+
+
_date_class = date # so functions w/ args named "date" can get at the class
date.min = date(1, 1, 1)
@@ -1431,6 +1486,21 @@
def __reduce__(self):
return (time, self._getstate())
+ if _is_jython:
+ def __tojava__(self, java_class):
+ if java_class not in (Calendar, Time, Object):
+ return Py.NoConversion
+ calendar = _make_java_calendar(self)
+ if calendar == Py.NoConversion:
+ return Py.NoConversion
+ epoch_ms = (self.hour * 3600 + self.minute * 60 + self.second) * 1000 + self.microsecond // 1000
+ calendar.setTimeInMillis(epoch_ms)
+ if java_class == Calendar:
+ return calendar
+ else:
+ return Time(calendar.getTimeInMillis())
+
+
_time_class = time # so functions w/ args named "time" can get at the class
time.min = time(0, 0, 0)
@@ -1928,6 +1998,24 @@
def __reduce__(self):
return (self.__class__, self._getstate())
+ if _is_jython:
+ def __tojava__(self, java_class):
+ if java_class not in (Calendar, Timestamp, Object):
+ return Py.NoConversion
+ calendar = _make_java_calendar(self)
+ if calendar == Py.NoConversion:
+ return Py.NoConversion
+ calendar.set(self.year, self.month - 1, self.day,
+ self.hour, self.minute, self.second)
+
+ if java_class == Calendar:
+ calendar.set(Calendar.MILLISECOND, self.microsecond // 1000)
+ return calendar
+ else:
+ timestamp = Timestamp(calendar.getTimeInMillis())
+ timestamp.setNanos(self.microsecond * 1000)
+ return timestamp
+
datetime.min = datetime(1, 1, 1)
datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
diff --git a/Lib/test/test_datetime_jy.py b/Lib/test/test_datetime_jy.py
--- a/Lib/test/test_datetime_jy.py
+++ b/Lib/test/test_datetime_jy.py
@@ -6,30 +6,127 @@
from datetime import time
from datetime import date, datetime
-from java.util import Calendar
-from java.sql import Date
+from java.util import Calendar, GregorianCalendar
+from java.sql import Date, Time, Timestamp
-class TestJavaDatetime(unittest.TestCase):
+class TestCalendar(unittest.TestCase):
def test_datetime(self):
self.assertTrue(hasattr(datetime, "__tojava__"))
x = datetime(2007, 1, 3)
y = x.__tojava__(Calendar)
- self.assertTrue(isinstance(y, Calendar))
+ self.assertIsInstance(y, GregorianCalendar)
+ self.assertEqual(y.get(Calendar.YEAR), 2007)
+ self.assertEqual(y.get(Calendar.MONTH), 0)
+ self.assertEqual(y.get(Calendar.DAY_OF_MONTH), 3)
+ self.assertEqual(y.get(Calendar.HOUR), 0)
+ self.assertEqual(y.get(Calendar.MINUTE), 0)
+ self.assertEqual(y.get(Calendar.SECOND), 0)
def test_date(self):
self.assertTrue(hasattr(date, "__tojava__"))
x = date(2007, 1, 3)
y = x.__tojava__(Calendar)
- self.assertTrue(isinstance(y, Calendar))
+ self.assertIsInstance(y, GregorianCalendar)
+ self.assertEqual(y.get(Calendar.YEAR), 2007)
+ self.assertEqual(y.get(Calendar.MONTH), 0)
+ self.assertEqual(y.get(Calendar.DAY_OF_MONTH), 3)
def test_time(self):
self.assertTrue(hasattr(time, "__tojava__"))
x = time(1, 3)
y = x.__tojava__(Calendar)
- self.assertTrue(isinstance(y, Calendar))
+ self.assertIsInstance(y, GregorianCalendar)
+ # Note obvious implementation details from GregorianCalendar
+ # and its definition in terms of the epoch
+ self.assertEqual(y.get(Calendar.YEAR), 1970)
+ self.assertEqual(y.get(Calendar.MONTH), 0)
+ self.assertEqual(y.get(Calendar.DAY_OF_MONTH), 1)
+ self.assertEqual(y.get(Calendar.HOUR), 1)
+ self.assertEqual(y.get(Calendar.MINUTE), 3)
+ self.assertEqual(y.get(Calendar.SECOND), 0)
+
+
+class TestTimezone(unittest.TestCase):
+
+ def test_olson(self):
+ class GMT1(tzinfo):
+ def utcoffset(self, dt):
+ return timedelta(hours=1)
+ def dst(self, dt):
+ return timedelta(0)
+ def tzname(self,dt):
+ return "Europe/Prague"
+
+ self.assertTrue(hasattr(datetime, "__tojava__"))
+ x = datetime(2007, 1, 3, tzinfo=GMT1())
+ y = x.__tojava__(Calendar)
+ self.assertIsInstance(y, GregorianCalendar)
+ self.assertEqual(y.get(Calendar.YEAR), 2007)
+ self.assertEqual(y.get(Calendar.MONTH), 0)
+ self.assertEqual(y.get(Calendar.DAY_OF_MONTH), 3)
+ self.assertEqual(y.get(Calendar.HOUR), 0)
+ self.assertEqual(y.get(Calendar.MINUTE), 0)
+ self.assertEqual(y.get(Calendar.SECOND), 0)
+ self.assertEqual(y.getTimeZone().getID(), "Europe/Prague")
+
+ def test_offset(self):
+ class Offset(tzinfo):
+ def utcoffset(self, dt):
+ return timedelta(hours=1, minutes=15)
+ def dst(self, dt):
+ return timedelta(seconds=-900)
+ def tzname(self,dt):
+ return "Foo/Bar"
+
+ self.assertTrue(hasattr(datetime, "__tojava__"))
+ x = datetime(2007, 1, 3, tzinfo=Offset())
+ y = x.__tojava__(Calendar)
+ self.assertIsInstance(y, GregorianCalendar)
+ self.assertEqual(y.get(Calendar.YEAR), 2007)
+ self.assertEqual(y.get(Calendar.MONTH), 0)
+ self.assertEqual(y.get(Calendar.DAY_OF_MONTH), 3)
+ self.assertEqual(y.get(Calendar.HOUR), 0)
+ self.assertEqual(y.get(Calendar.MINUTE), 0)
+ self.assertEqual(y.get(Calendar.SECOND), 0)
+ self.assertEqual(y.getTimeZone().getID(), "UTC")
+ self.assertEqual(y.get(Calendar.DST_OFFSET), -900 * 1000)
+ self.assertEqual(y.get(Calendar.ZONE_OFFSET), 4500 * 1000)
+
+
+class TestSQL(unittest.TestCase):
+
+ def test_datetime(self):
+ self.assertTrue(hasattr(datetime, "__tojava__"))
+ x = datetime(2007, 1, 3)
+ y = x.__tojava__(Timestamp)
+ self.assertIsInstance(y, Timestamp)
+ self.assertEqual(y.getTime(), (x - datetime(1970, 1, 1)).total_seconds() * 1000)
+
+ def test_date(self):
+ self.assertTrue(hasattr(date, "__tojava__"))
+ x = date(2007, 1, 3)
+ y = x.__tojava__(Date)
+ self.assertIsInstance(y, Date)
+ self.assertEqual(y.getTime(), (x - date(1970, 1, 1)).total_seconds() * 1000)
+
+ def test_time(self):
+ self.assertTrue(hasattr(time, "__tojava__"))
+ x = time(1, 3)
+ y = x.__tojava__(Time)
+ self.assertIsInstance(y, Time)
+ epoch = y.getTime()/1000.
+ self.assertEqual(epoch // 3600, 1) # 1 hour
+ self.assertEqual(epoch % 3600, 180) # 3 minutes
+
+
+def test_main():
+ test_support.run_unittest(
+ TestCalendar,
+ TestSQL,
+ TestTimezone)
if __name__ == '__main__':
- unittest.main()
+ test_main()
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list