ICEfaces
  1. ICEfaces
  2. ICE-10918

ace:dateTimeEntry "Now" button should honor timeZone attribute

    Details

    • Assignee Priority:
      P2
    • Support Case References:
      Support Case 13652:-https://icesoft.my.salesforce.com/5007000001XOeY6

      Description

      Currently when using the popup version of the ace:dateTimeEntry widget, the "Now" button does not honor the timeZone entry.
      change Showcase "popup" example of this component to:-
            <h:panelGrid style="margin-left: auto; margin-right: auto; text-align: center;" width="100">
                          <ace:dateTimeEntry id="cal"
                                                         value="#{datePopup.selectedDate}"
                                                         timeZone="#{datePopup.selectedTimeZone} "
                                                         pattern="MMM/dd/yyyy hh:mm z"
                                                         renderAsPopup="#{datePopup.popup}">
                           </ace:dateTimeEntry>
                          <h:commandButton id="submit" value="Submit Date"/>

      and allow the user to select a timeZone:-
                          <h:panelGroup>
                              <h:outputLabel for="tzinput" value="Select TimeZone:-"/>
                              <h:selectOneMenu id="tzinput" value="#{datePopup.selectedTimeZone}">
                                  <f:selectItems value="#{datePopup.timeZones}"/>
                              </h:selectOneMenu>
                          </h:panelGroup>

      ....
      with DatePopupBean:-

      (in constructor)...

              String[] ids = TimeZone.getAvailableIDs();
              for (String id : ids){
                  timeZones.add(new SelectItem(id, displayTimeOffset(id) ));
              }

         public String displayTimeOffset(String id){
              TimeZone zone = TimeZone.getTimeZone(id);
              long hours = TimeUnit.MILLISECONDS.toHours(zone.getRawOffset());
      long minutes = TimeUnit.MILLISECONDS.toMinutes(zone.getRawOffset())
                                        - TimeUnit.HOURS.toMinutes(hours);
      minutes = Math.abs(minutes);
      String result = "";
              String hrs = String.valueOf(hours) ;
           // System.out.println(" hours="+hours+" hrs="+hrs);
      if (hours > 0) {
      result = "(GMT+"+hrs+":"+hrs+") "+ String.valueOf(minutes);
      } else {
      result = "(GMT"+hrs+":"+hrs+")"+ String.valueOf(minutes);
      }

      return result;
          }
      ...
      when you use the "now" button on the popup of the widget, you can change the timeZone and then select a time, but the "Now" button will always reflect the "Now" for the browser locale.
      Should this not reflect the "Now" in the timeZone that is currently selected? OTherwise, do we improve it to have another attribute that forces this?
      1. datepopup.xhtml
        3 kB
        Carmen Cristurean
      2. DatePopupBean.java
        3 kB
        Carmen Cristurean
      1. 1.PNG
        266 kB
      2. 2.PNG
        169 kB

        Activity

        Hide
        Arturo Zambrano added a comment - - edited

        This enhancement is not as simple as it seemed at first. The main issue is accounting for Daylight Savings Time (DST) in a reliable and accurate approach. While failing to account for the DST accurately would only result in a difference of one hour, in production environments this could have negative consequences that could be critical, depending on the nature of the application.

        There's no native support for multiple time zones in Javascript. The browser is only aware of the local time zone. The naive approach to converting a Date to a time zone that is different to the local one would look like this.

        	var now = new Date(); // right now, according to the local machine
        	var localTime_msec = now.getTime(); // milliseconds since Jan 1 1970
        	var offsetUTC_min = now.getTimezoneOffset(); // UTC offset in minutes (accounts for DST)
        	var offsetUTC_msec = offsetUTC_min * 60000; // UTC offset in milliseconds
        	var UTC_msec = localTime_msec + offsetUTC_msec; // UTC time in milliseconds
        
        	var offsetTarget = -7; // set target location's offset in hours
        	var offsetTarget_msec = offsetTarget * 3600000; // target location's offset in milliseconds
        	var targetTime_msec = UTC_msec + offsetTarget_msec; // target location's time in milliseconds
        

        Basically, the approach consists in calculating the UTC time (which we know that does not observe DST), and then we add (or subtract) the time zone offset of the target location. The Date.getTimezoneOffset() method accounts for DST (relying on the host OS), which leads us to an accurate UTC time. However, the browser doesn't have any DST information on the target location's time zone. Because the dates and times at which the various time zones enter and leave the DST can greatly vary, it's not possible to reliably calculate a date or time in a time zone (different that the one used by the browser) without external help.

        There are two possible approaches to know the target location's time zone offset while accounting for DST; one of them involves the server and the other one requires an additional Javascript library.

        The server approach consists in using the java.util.TimeZone class. We would call TimeZone.getOffset() to obtain the time zone offset in milliseconds (this value would replace the 'offsetTarget_msec' variable above), and we would always send this value to the Calendar constructor in the client. This class and method account for DST, as can be seen in the API documentation:
        https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html#getOffset(int,%20int,%20int,%20int,%20int,%20int)

        The server approach is simple enough, but there's an edge case in which the offset wouldn't be accurate: If the page is loaded minutes before the hour where the DST comes into effect in a given time zone, and then the user presses the 'Now' button a minute after the DST comes into effect, then the offset won't be accurate, and it will be off by one hour.

        The other approach doesn't require the server help and doesn't have the edge case problem described in the last paragraph, but it requires an additional Javascript library called moment.js. This library was specifically created to parse, validate, manipulate and display dates in any time zone. It uses the MIT license and seems to be getting widely adopted in the industry. This library contains all the information for all the time zones in the world and accounts for DST accurately to the minute, as can be seen in this reference page:
        http://momentjs.com/timezone/docs/#/zone-object/parse/

        These two approaches are solid enough, however they still rely on the user's machine to calculate the UTC time. If the user's machine's clock is not accurate, then the time set by the 'Now' button won't be accurate either. This situation could be improved by having a servlet that serves the server time or that references some centralized time authority. However, that might be too much for the scope of this component. Applications where time is critical may prefer to implement their own methods to ensure that the selected time is accurate, anyway. It's also easy to add a separate button to a page to set the value of the ace:dateTimeEntry component to another time zone's time, based on the server time at that moment.

        Show
        Arturo Zambrano added a comment - - edited This enhancement is not as simple as it seemed at first. The main issue is accounting for Daylight Savings Time (DST) in a reliable and accurate approach. While failing to account for the DST accurately would only result in a difference of one hour, in production environments this could have negative consequences that could be critical, depending on the nature of the application. There's no native support for multiple time zones in Javascript. The browser is only aware of the local time zone. The naive approach to converting a Date to a time zone that is different to the local one would look like this. var now = new Date(); // right now, according to the local machine var localTime_msec = now.getTime(); // milliseconds since Jan 1 1970 var offsetUTC_min = now.getTimezoneOffset(); // UTC offset in minutes (accounts for DST) var offsetUTC_msec = offsetUTC_min * 60000; // UTC offset in milliseconds var UTC_msec = localTime_msec + offsetUTC_msec; // UTC time in milliseconds var offsetTarget = -7; // set target location's offset in hours var offsetTarget_msec = offsetTarget * 3600000; // target location's offset in milliseconds var targetTime_msec = UTC_msec + offsetTarget_msec; // target location's time in milliseconds Basically, the approach consists in calculating the UTC time (which we know that does not observe DST), and then we add (or subtract) the time zone offset of the target location. The Date.getTimezoneOffset() method accounts for DST (relying on the host OS), which leads us to an accurate UTC time. However, the browser doesn't have any DST information on the target location's time zone. Because the dates and times at which the various time zones enter and leave the DST can greatly vary, it's not possible to reliably calculate a date or time in a time zone (different that the one used by the browser) without external help. There are two possible approaches to know the target location's time zone offset while accounting for DST; one of them involves the server and the other one requires an additional Javascript library. The server approach consists in using the java.util.TimeZone class. We would call TimeZone.getOffset() to obtain the time zone offset in milliseconds (this value would replace the 'offsetTarget_msec' variable above), and we would always send this value to the Calendar constructor in the client. This class and method account for DST, as can be seen in the API documentation: https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html#getOffset(int,%20int,%20int,%20int,%20int,%20int ) The server approach is simple enough, but there's an edge case in which the offset wouldn't be accurate: If the page is loaded minutes before the hour where the DST comes into effect in a given time zone, and then the user presses the 'Now' button a minute after the DST comes into effect, then the offset won't be accurate, and it will be off by one hour. The other approach doesn't require the server help and doesn't have the edge case problem described in the last paragraph, but it requires an additional Javascript library called moment.js. This library was specifically created to parse, validate, manipulate and display dates in any time zone. It uses the MIT license and seems to be getting widely adopted in the industry. This library contains all the information for all the time zones in the world and accounts for DST accurately to the minute, as can be seen in this reference page: http://momentjs.com/timezone/docs/#/zone-object/parse/ These two approaches are solid enough, however they still rely on the user's machine to calculate the UTC time. If the user's machine's clock is not accurate, then the time set by the 'Now' button won't be accurate either. This situation could be improved by having a servlet that serves the server time or that references some centralized time authority. However, that might be too much for the scope of this component. Applications where time is critical may prefer to implement their own methods to ensure that the selected time is accurate, anyway. It's also easy to add a separate button to a page to set the value of the ace:dateTimeEntry component to another time zone's time, based on the server time at that moment.
        Hide
        Arturo Zambrano added a comment - - edited

        r47010: fix for honouring the selected time zone when pressing the Today/Now button

        The fix is the server approach described above.

        Testing Notes: Testing this feature thoroughly will be somewhat complex. First, modify the showcase application, as described in the description, in order to be able to select different time zones dynamically. Also add the showButtonPanel="true" attribute as well to show the Now/Today button. Please also test with and without a timepicker; to show the timepicker change the pattern to something like "MMM/dd/yyyy h:mm:ss a" to include time. Also test with todayNowButtonsAlsoSelect="true" and also with the same attribute set to false.

        The basic test consists in selecting different time zones and making sure that upon pressing the Now/Today button, the time/day are changed to the current time in the selected time zone. You might want to modify the time zone selection menu on the page to also display the time zone id, so it's easier to identify and then check on Google the current time for that city/timezone and compare. Make sure to test that time zones with a high positive offset, where it's the next day already, cause the calendar to change to the next day as well, not just the time.

        In order to test the correctness of Daylight Saving Time, it might be necessary to become familiar with a couple of time zones in America, Europe and Asia and test them all by changing the date of the computer where this is being tested to somewhere in the summer, where the DST is in effect.

        Show
        Arturo Zambrano added a comment - - edited r47010: fix for honouring the selected time zone when pressing the Today/Now button The fix is the server approach described above. Testing Notes: Testing this feature thoroughly will be somewhat complex. First, modify the showcase application, as described in the description, in order to be able to select different time zones dynamically. Also add the showButtonPanel="true" attribute as well to show the Now/Today button. Please also test with and without a timepicker; to show the timepicker change the pattern to something like "MMM/dd/yyyy h:mm:ss a" to include time. Also test with todayNowButtonsAlsoSelect="true" and also with the same attribute set to false. The basic test consists in selecting different time zones and making sure that upon pressing the Now/Today button, the time/day are changed to the current time in the selected time zone. You might want to modify the time zone selection menu on the page to also display the time zone id, so it's easier to identify and then check on Google the current time for that city/timezone and compare. Make sure to test that time zones with a high positive offset, where it's the next day already, cause the calendar to change to the next day as well, not just the time. In order to test the correctness of Daylight Saving Time, it might be necessary to become familiar with a couple of time zones in America, Europe and Asia and test them all by changing the date of the computer where this is being tested to somewhere in the summer, where the DST is in effect.
        Hide
        Ken Fyten added a comment -

        Re-opened due to issue reported by Carmen above.

        Perhaps the issue is related to the era of JDK being used at runtime. Suggest retesting using JDK 1.7 or 1.8. If either of those work we could consider this fixed.

        Show
        Ken Fyten added a comment - Re-opened due to issue reported by Carmen above. Perhaps the issue is related to the era of JDK being used at runtime. Suggest retesting using JDK 1.7 or 1.8. If either of those work we could consider this fixed.
        Hide
        Arturo Zambrano added a comment -

        r48648: committed fix to the 3.3 EE maintenance branch.

        Show
        Arturo Zambrano added a comment - r48648: committed fix to the 3.3 EE maintenance branch.
        Hide
        Arturo Zambrano added a comment -

        Resolving issue.

        Please also test to see if you can still reproduce the issue described in this comment: http://jira.icesoft.org/browse/ICE-10918?focusedCommentId=62225&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-62225

        Show
        Arturo Zambrano added a comment - Resolving issue. Please also test to see if you can still reproduce the issue described in this comment: http://jira.icesoft.org/browse/ICE-10918?focusedCommentId=62225&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-62225

          People

          • Assignee:
            Arturo Zambrano
            Reporter:
            Judy Guglielmin
          • Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: