Title: Py.newDateTime, Py.newTime should initialize timezone python datetime/time objects
Type: Severity: normal
Components: Core Versions: Jython 2.7
Status: open Resolution: accepted
Dependencies: Superseder:
Assigned To: Nosy List: r_walter, stefan.richthofer, tmeagher
Priority: normal Keywords:

Created on 2017-11-26.11:32:44 by tmeagher, last changed 2020-09-30.16:44:19 by r_walter.

msg11682 (view) Author: Tim Meagher (tmeagher) Date: 2017-11-26.11:32:43
The Py.newDateTime and Py.newTime methods construct new datetime.datetime and datetime.time objects. The date/time information is calculated based on the time in millis on the java.sql.Timestamp/Time object provided to those methods.
However, the timezone is not set on the python objects. This means that while these types are "naive" in python, when converting back to Java via the __tojava__ method, the returned time will be incorrect if the system is not in the UTC timezone.


long timeMillis = System.currentTimeMillis();
SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
Timestamp inputTimestamp = new Timestamp(timeMillis);
PyObject pyDateTime = Py.newDatetime(inputTimestamp);
Timestamp resultTimestamp = (Timestamp)pyDateTime.__tojava__(java.sql.Timestamp.class);
System.out.println("Input DateTime:");
System.out.println("formatted:" + dateFormat.format(inputTimestamp));

System.out.println("Output DateTime:");
//These should both match the input datetime formatted string & time in millis, but won't if the system is not in UTC.
SimpleDateFormat timeFormat = new SimpleDateFormat( "HH:mm:ss");		
java.sql.Time inputTime = new java.sql.Time(timeMillis);		
PyObject pyTime = Py.newTime(inputTime);
java.sql.Time resultTime = (java.sql.Time)pyTime.__tojava__(java.sql.Time.class);

System.out.println("Input Time:");
System.out.println("formatted:" + timeFormat.format(inputTime));

//The millis on Time doesn't need to match the input (since the date component may exist in the original Java object, but is
//ignored when converting back to Java (which is ok), but the actual hh:mm:ss the time represents should be the same as the original
//On a non-UTC system, this is not the case.
System.out.println("Output Time:");
msg11684 (view) Author: Tim Meagher (tmeagher) Date: 2017-11-27.10:54:56
I believe I have a fix for this issue. Just have to figure out the best way to make sure tests are in the correct location & create a pull request. I guess there are numerous ways to solve this and what I am thinking may not be the ideal way, but will update this issue with my suggestion when it is all ready.
msg11689 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2017-12-07.16:34:46
Okay, shortly speaking Py.newDatetime and __tojava__ on the result should be conversion-compatible. That sounds reasonable to me.

However, we must consider that there might be code out there that is "bug-compatible" to the current behavior and changing Py.newDatetime would not be backwards compatible.

I would suggest the following:
- implement your fix as Py.newDatetimeUTC
- overload Py.newDatetime with a version that explicitly takes a time zone as second argument
- deprecate the original Py.newDatetime because it is incompatible with __tojava__ of datetime objects
- clarify and warn about this in javadoc of Py.newDatetime

@Tim Thanks for finding and working on this issue! Feel free to ask questions if you're stuck or add a PR at github to discuss your approach...
msg13126 (view) Author: Roland Walter (r_walter) Date: 2020-09-30.16:44:19
It seems this hits applications really badly using zxJDBC when inserting timestamp values into a database.
Date User Action Args
2020-09-30 16:44:19r_waltersetnosy: + r_walter
messages: + msg13126
2017-12-07 16:34:47stefan.richthofersetpriority: normal
resolution: accepted
messages: + msg11689
nosy: + stefan.richthofer
2017-11-27 10:54:57tmeaghersetmessages: + msg11684
2017-11-26 11:32:45tmeaghercreate