<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"> 
        <base href="https://hibernate.atlassian.net"> 
        <title>Message Title</title> 
    </head> 
    <body class="jira" style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 1.429"> 
        <table id="background-table" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0; background-color: #f5f5f5; border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0" bgcolor="#f5f5f5"> 
            <!-- header here --> 
            <tbody>
                <tr> 
                    <td id="header-pattern-container" style="padding: 0; border-collapse: collapse; padding: 10px 20px"> 
                        <table id="header-pattern" cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0"> 
                            <tbody>
                                <tr> 
                                    <td id="header-avatar-image-container" valign="top" style="padding: 0; border-collapse: collapse; vertical-align: top; width: 32px; padding-right: 8px" width="32"> <img id="header-avatar-image" class="image_fix" src="cid:jira-generated-image-avatar-91dcce1f-b4ca-4931-92e0-29bd9d1bb287" height="32" width="32" border="0" style="border-radius: 3px; vertical-align: top"> </td> 
                                    <td id="header-text-container" valign="middle" style="padding: 0; border-collapse: collapse; vertical-align: middle; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> <a class="user-hover" rel="mih_vlad" id="email_mih_vlad" href="https://hibernate.atlassian.net/secure/ViewProfile.jspa?name=mih_vlad" style="color:#6c797f;; color: #3b73af; text-decoration: none">Vlad Mihalcea</a> <strong>commented</strong> on <a href="https://hibernate.atlassian.net/browse/HHH-10399" style="color: #3b73af; text-decoration: none"><img src="cid:jira-generated-image-avatar-375e339d-1276-4598-bb91-41be1d4771a2" height="16" width="16" border="0" align="absmiddle" alt="New Feature"> HHH-10399</a> </td> 
                                </tr> 
                            </tbody>
                        </table> </td> 
                </tr> 
                <tr> 
                    <td id="email-content-container" style="padding: 0; border-collapse: collapse; padding: 0 20px"> 
                        <table id="email-content-table" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0; border-spacing: 0; border-collapse: separate"> 
                            <tbody>
                                <tr> 
                                    <!-- there needs to be content in the cell for it to render in some clients --> 
                                    <td class="email-content-rounded-top mobile-expand" style="padding: 0; border-collapse: collapse; color: #ffffff; padding: 0 15px 0 16px; height: 15px; background-color: #ffffff; border-left: 1px solid #cccccc; border-top: 1px solid #cccccc; border-right: 1px solid #cccccc; border-bottom: 0; border-top-right-radius: 5px; border-top-left-radius: 5px; height: 10px; line-height: 10px; padding: 0 15px 0 16px; mso-line-height-rule: exactly" height="10" bgcolor="#ffffff">&nbsp;</td> 
                                </tr> 
                                <tr> 
                                    <td class="email-content-main mobile-expand " style="padding: 0; border-collapse: collapse; border-left: 1px solid #cccccc; border-right: 1px solid #cccccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #ffffff" bgcolor="#ffffff"> 
                                        <table class="page-title-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0"> 
                                            <tbody>
                                                <tr> 
                                                    <td style="vertical-align: top;; padding: 0; border-collapse: collapse; padding-right: 5px; font-size: 20px; line-height: 30px; mso-line-height-rule: exactly" class="page-title-pattern-header-container"> <span class="page-title-pattern-header" style="font-family: Arial, sans-serif; padding: 0; font-size: 20px; line-height: 30px; mso-text-raise: 2px; mso-line-height-rule: exactly; vertical-align: middle"> <a href="https://hibernate.atlassian.net/browse/HHH-10399" style="color: #3b73af; text-decoration: none">Re: Add support for specifying TimeZone for ZonedDateTime type</a> </span> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                                <tr> 
                                    <td id="text-paragraph-pattern-top" class="email-content-main mobile-expand  comment-top-pattern" style="padding: 0; border-collapse: collapse; border-left: 1px solid #cccccc; border-right: 1px solid #cccccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #ffffff; border-bottom: none; padding-bottom: 0" bgcolor="#ffffff"> 
                                        <table class="text-paragraph-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 2px"> 
                                            <tbody>
                                                <tr> 
                                                    <td class="text-paragraph-pattern-container mobile-resize-text " style="padding: 0; border-collapse: collapse; padding: 0 0 10px"> <p style="margin: 10px 0 0; margin-top: 0">We had a discussion on HipChat, and this is a summary that <a href="https://hibernate.atlassian.net/secure/ViewProfile.jspa?name=steve" class="user-hover" rel="steve" style="color: #3b73af; text-decoration: none">Steve Ebersole</a> had come up with:</p> 
                                                        <div class="preformatted panel" style="border-width: 1px;; border: 1px solid #cccccc; background: #f5f5f5; font-size: 12px; line-height: 1.333; font-family: monospace; border: 1px solid #cccccc; -moz-border-radius: 3px; border-radius: 3px; margin: 9px 0">
                                                            <div class="preformattedContent panelContent" style="padding: 9px 12px"> 
                                                                <pre style="margin: 10px 0 0; margin-top: 0; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal; white-space: pre; word-break: normal; word-wrap: break-word; word-break: break-all; white-space: pre-wrap">We discussed this on HipChat, but for the benefit of all on this discussion...

Part of this (the original report) speaks to a difference in how we map (org.hibernate.type.Type) java.time temporal versus a java.util temporal - specifically java.util.Calendar.  When we are passed a Calendar (the model defines its attribute as Calendar) we pass along that Calendar reference to the JDBC driver which forces the driver to use that Calendar's TZ.  For java.time temporal types, we always resolve them to UTC values mainly because of how we get to the java.sql.Timestamp value from the java.time value.  For example, for ZonedDateTime we call:

    return (X) Timestamp.from( zonedDateTime.toInstant() );
 
The call to #toInstant there essentially forces the value to UTC because it converted directly to epoch-based numeric.

Thinking about this some more and "stepping back", the real problem is that there are a few different timezones in play here that need to be balanced and handled:

1.        The database default TZ
2.        The stored TZ
3.        The JVM/JDBC TZ
4.        The application TZ
The whole idea of "stored TZ" really depends on how the database/driver treats TIMESTAMP and whether it supports a "TIMESTAMP_WITH_TIMEZONE" type.  I personally think it is a huge mistake to save the specific TZ differences to the DB, so I would personally continue to not support TIMESTAMP_WITH_TIMEZONE types.  This would mean we never have to bind the Calendar because we could simply convert the value to to the JVM/JDBC TZ ourselves.  Specifically I would suggest that we (continue to) assume that the driver has been set up such that the same TZ is used when 

1.        when binding a Timestamp (without passing a Calendar) 
2.        reading a Timestamp (without passing a Calendar).
Specifically this would mean setting the JVM TZ, or for JDBC drivers that support it setting the "default TZ" on the driver.  If we start storing values in the TZ specific to the Calendar we really have no idea how to properly read those values back because we'd lose context to that TZ.  For that reason I suggest we drop passing along the Calender and instead perform all these conversions in memory and pass the converted Timestamp to JDBC.  When reading back, that should mean the driver would return us Timestamps relative to that same TZ.

The last piece is "application TZ" which would be an optional setting indicating the TZ zone-based values should be returned in.  

E.g., let's say a user maps a ZonedDataTime using @Temporal(TIMESTAMP).  If following my suggestions, when saving these values we would:
1.        convert the ZonedDateTime to a ZonedDateTime in the "JVM/JDBC TZ" (if different from the incoming ZonedDateTime's TZ)
2.        use that to construct a Timestamp to bind to JDBC
When reading back these values, we would:
1.        get back the Timestamp from JDBC
2.        assume the value is relative to the "JVM/JDBC TZ" and build the ZonedDateTime via `ZonedDateTime.ofInstant( timestamp.toInstant(), jvmJdbcZoneId )`
3.        convert that built ZonedDateTime to the application TZ: `builtZonedDateTime.withZoneSameInstant( applicationZoneId )` - it might be possible to combine this step with the previous, not sure...

Some if this is type-specific.  Assuming the suggestions above:
•        Instant - inherently epoch-based.  
    o        to convert this to a Timestamp for binding we would use `Timestamp#from(Instant).  Because of the above assumptions, the driver would interpret this relative to JVM/JDBC TZ
    o        Reading back we simply use `Timestamp#toInstant()`
•        LocalDateTime - is the relative idea of a date+time outside the context of any specific TZ.  
    o        When binding we would resolve this into the JVM/JDBC TZ (using LocalDateTime#atZone(jvmJdbcZoneId), convert to an Instant and create a Timestamp and bind that Timestamp to JDBC.
    o        When reading back we'd get the Instant from Timestamp and use that in `LocalDateTime#ofInstant` using the application TZ
•        LocalDate - relative idea of a date outside of any specific TZ.  Of course this could also be mapped to a JDBC DATE which circumvents some of this, but mapped to a TIMESTAMP...
    o        When binding we'd convert to a LocalDateTime using `LocalDate#atStartOfDay` and treat that LocalDateTime as above.
    o        When reading back we would create a LocalDateTime using `LocalDateTime.ofInstant(timestamp.toInstant(), applicationZoneId )`
•        LocalTime - relative idea of a time outside any specific TZ.  Could also be mapped to a JDBC TIME...
    o        When binding we'd create a LocalDateTime using `LocalTime.atDate( LocalDate.of( 1970, 1, 1 ) )`, converting that to a ZonedDateTime using `LocalDateTime#atZone( jvmJdbcZoneId )` and finally converting that to a Timestamp
    o        When reading we would call `LocalDateTime.ofInstant( timestamp.toInstant(), applicationZoneId ).toLocalTime()`
•        ZonedDateTime - like a Calendar bundles a date+time with a TZ, and so is directly convertible to an epoch-based value (Instant, Timestamp, etc).  
    o        When binding we would convert this to an Instant and then to a Timestamp
    o        When reading we would convert the Timestamp to an Instant and then convert the Instant to a ZonedDateTime using `ZonedDateTime.ofInstant( timestamp.toInstant(), applicationZoneId )`
•        OffsetDateTime - handled similar to ZonedDateTime.  
    o        When binding we would convert the value to a ZonedDateTime using `OffsetDateTime#atZoneSameInstant( jvmJdbcZoneId )` and then follows ZonedDateTime
    o        When reading we would use `OffsetDateTime.ofInstant( timestamp.toInstant(), applicationZoneId )`
•        OffsetTime - atm we just drop the ZoneOffset
•        for java.util.Date and java.sql.Timstamp mapping we have to decide what those concepts model in regards to their value relative to a TZ.  Are they a LocalDateTime relative to the system TimeZone?  Are they a LocalDateTime relative to UTC?  At the moment how we handled these "legacy Java temporal types" ends up answering this question as them being "a LocalDateTime relative to the system TimeZone".
•        what about java.sql.Time?  Is this a LocalTime?  An OffsetTime relative to UTC (+0)?
•        and java.sql.Date?

Lot of moving parts when you actually start looking deep at "supporting timezones".


[1] http://stackoverflow.com/questions/18447995/postgresql-9-2-jdbc-driver-uses-client-time-zone, etc

</pre> 
                                                            </div>
                                                        </div> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                                <tr> 
                                    <td class="email-content-main mobile-expand " style="padding: 0; border-collapse: collapse; border-left: 1px solid #cccccc; border-right: 1px solid #cccccc; border-top: 0; border-bottom: 0; padding: 0 15px 0 16px; background-color: #ffffff" bgcolor="#ffffff"> 
                                        <table id="actions-pattern" cellspacing="0" cellpadding="0" border="0" width="100%" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 1px"> 
                                            <tbody>
                                                <tr> 
                                                    <td id="actions-pattern-container" valign="middle" style="padding: 0; border-collapse: collapse; padding: 10px 0 10px 24px; vertical-align: middle; padding-left: 0"> 
                                                        <table align="left" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0"> 
                                                            <tbody>
                                                                <tr> 
                                                                    <td class="actions-pattern-action-icon-container" style="padding: 0; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 0; vertical-align: middle"> <a href="https://hibernate.atlassian.net/browse/HHH-10399#add-comment" target="_blank" title="Add Comment" style="color: #3b73af; text-decoration: none"> <img class="actions-pattern-action-icon-image" src="cid:jira-generated-image-static-comment-icon-f662868d-9577-405f-972b-54ff10adfc31" alt="Add Comment" title="Add Comment" height="16" width="16" border="0" style="vertical-align: middle"> </a> </td> 
                                                                    <td class="actions-pattern-action-text-container" style="padding: 0; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; mso-line-height-rule: exactly; mso-text-raise: 4px; padding-left: 5px"> <a href="https://hibernate.atlassian.net/browse/HHH-10399#add-comment" target="_blank" title="Add Comment" style="color: #3b73af; text-decoration: none">Add Comment</a> </td> 
                                                                </tr> 
                                                            </tbody>
                                                        </table> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                                <!-- there needs to be content in the cell for it to render in some clients --> 
                                <tr> 
                                    <td class="email-content-rounded-bottom mobile-expand" style="padding: 0; border-collapse: collapse; color: #ffffff; padding: 0 15px 0 16px; height: 5px; line-height: 5px; background-color: #ffffff; border-top: 0; border-left: 1px solid #cccccc; border-bottom: 1px solid #cccccc; border-right: 1px solid #cccccc; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; mso-line-height-rule: exactly" height="5" bgcolor="#ffffff">&nbsp;</td> 
                                </tr> 
                            </tbody>
                        </table> </td> 
                </tr> 
                <tr> 
                    <td id="footer-pattern" style="padding: 0; border-collapse: collapse; padding: 12px 20px"> 
                        <table id="footer-pattern-container" cellspacing="0" cellpadding="0" border="0" style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0"> 
                            <tbody>
                                <tr> 
                                    <td id="footer-pattern-text" class="mobile-resize-text" width="100%" style="padding: 0; border-collapse: collapse; color: #999999; font-size: 12px; line-height: 18px; font-family: Arial, sans-serif; mso-line-height-rule: exactly; mso-text-raise: 2px"> This message was sent by Atlassian JIRA <span id="footer-build-information">(v1000.305.0#100011-<span title="1dc2d9a6e2d16c04d725bc9ee96a9cbeb846cc63" data-commit-id="1dc2d9a6e2d16c04d725bc9ee96a9cbeb846cc63}">sha1:1dc2d9a</span>)</span> </td> 
                                    <td id="footer-pattern-logo-desktop-container" valign="top" style="padding: 0; border-collapse: collapse; padding-left: 20px; vertical-align: top"> 
                                        <table style="border-collapse: collapse; mso-table-lspace: 0; mso-table-rspace: 0"> 
                                            <tbody>
                                                <tr> 
                                                    <td id="footer-pattern-logo-desktop-padding" style="padding: 0; border-collapse: collapse; padding-top: 3px"> <img id="footer-pattern-logo-desktop" src="cid:jira-generated-image-static-footer-desktop-logo-784a79de-9539-4be8-b63f-c9f98b75d55f" alt="Atlassian logo" title="Atlassian logo" width="169" height="36" class="image_fix"> </td> 
                                                </tr> 
                                            </tbody>
                                        </table> </td> 
                                </tr> 
                            </tbody>
                        </table> </td> 
                </tr> 
            </tbody>
        </table>   
    </body>
</html>