You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2009/01/28 08:23:02 UTC
svn commit: r738384 [1/6] - in /myfaces/trinidad/trunk/trinidad-impl/src:
main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/
main/javascript/META-INF/adf/jsLibs/
test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/
Author: matzew
Date: Wed Jan 28 07:23:01 2009
New Revision: 738384
URL: http://svn.apache.org/viewvc?rev=738384&view=rev
Log:
TRINIDAD-1349 - InputDate: wrong date-time selected when browser in summer time and server in winter time
Thanks to Yee-Wah Lee for her patch
Modified:
myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ChooseDateRenderer.java
myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/DateField.js
myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/chooseDate-minimal-golden.xml
myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/chooseDate-minimalIE-golden.xml
myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/chooseDate-minimalIERtl-golden.xml
myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/chooseDate-minimalInacc-golden.xml
myfaces/trinidad/trunk/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/chooseDate-minimalSaf-golden.xml
Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ChooseDateRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ChooseDateRenderer.java?rev=738384&r1=738383&r2=738384&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ChooseDateRenderer.java (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ChooseDateRenderer.java Wed Jan 28 07:23:01 2009
@@ -24,6 +24,8 @@
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
@@ -113,6 +115,15 @@
if (isInline && !isInlineSupported(arc))
return;
+ // TRINIDAD-1349: The client converter assumes a fixed timezone offset
+ // between the server and itself. It calculates that by passing the
+ // server's timezone offset at the current date-time, as _uixLocaleTZ.
+ // However, if we are rendering a month in which daylight savings occurs in
+ // the application timezone, the offset value may be different. In that case
+ // pass the new offset value for the client to use.
+ TimeZone tz = arc.getLocaleContext().getTimeZone();
+ int baseTZOffsetMinutes = tz.getOffset(System.currentTimeMillis())/(1000*60);
+
boolean isDesktop = isDesktop(arc);
ResponseWriter writer = context.getResponseWriter();
writer.startElement("table", component);
@@ -135,7 +146,7 @@
// get the currently selected Time
long selectedTime = _getSelectedTime(arc, bean, minTime, maxTime);
-
+
// get the id
String id = getClientId(context, component);
@@ -156,19 +167,22 @@
maxTime,
selectedTime);
- long displayedTime = displayedCalendar.getTime().getTime();
-
- // determine the day of this month that is selected
- int dom = displayedCalendar.get(Calendar.DAY_OF_MONTH);
-
int firstDOM = _getActualMinimumDayOfMonth(displayedCalendar);
int lastDOM = _getActualMaximumDayOfMonth(displayedCalendar);
-
+
// determine the the starting times and ending times of the first and
// last days of the month
- long firstDOMTime = displayedTime + (firstDOM - dom) * _MILLIS_IN_DAY;
- long lastDOMTime = displayedTime +
- ((long)(lastDOM + 1 - dom)) * _MILLIS_IN_DAY - 1;
+ // Create a copy of the calendar so we don't hammer the current values
+ Calendar calcCal = (Calendar) displayedCalendar.clone();
+ // First is easy
+ calcCal.set(Calendar.DAY_OF_MONTH, firstDOM);
+ long firstDOMTime = calcCal.getTimeInMillis();
+
+ // Last not just the last day of this month, it's the first day of next
+ // month minus a millisecond.
+ calcCal.set(Calendar.DAY_OF_MONTH, lastDOM);
+ calcCal.add(Calendar.DATE, 1);
+ long lastDOMTime = calcCal.getTimeInMillis() - 1;
DateFormatSymbols dateSymbols = _getDateFormatSymbols(arc);
@@ -325,7 +339,8 @@
int currDOM = firstDOM;
long currTime = firstDOMTime;
- long nextTime = currTime + _MILLIS_IN_DAY;
+ displayedCalendar.add(Calendar.DAY_OF_MONTH, 1);
+ long nextTime = displayedCalendar.getTimeInMillis();
int currLastDOW = firstDOWInMonth + dowCount;
String[] keysAndValues = new String[]{
@@ -376,10 +391,12 @@
// a date in the date field. (see bug #1482511)
//
writer.startElement("a", null);
- renderSelectDayAttributes(context,
+ renderSelectDayAttributes(arc,
+ context,
keysAndValues,
id,
currTime,
+ baseTZOffsetMinutes,
isInline,
isDesktop,
destString);
@@ -407,7 +424,8 @@
// move to the next day in time
currTime = nextTime;
- nextTime += _MILLIS_IN_DAY;
+ displayedCalendar.add(Calendar.DAY_OF_MONTH, 1);
+ nextTime = displayedCalendar.getTimeInMillis();
}
if (currDOM <= lastDOM)
@@ -425,6 +443,9 @@
break;
}
} while (true);
+
+ // Reset the calendar
+ displayedCalendar.set(Calendar.DAY_OF_MONTH, firstDOM);
//
// output the days from the next month in the last week
@@ -465,18 +486,24 @@
protected void renderSelectDayAttributes(
+ RenderingContext arc,
FacesContext context,
String[] keysAndValues,
String id,
long currTime,
+ int baseTZOffsetMinutes,
boolean isInline,
boolean isDesktop,
String destString
) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
+
if (isDesktop)
{
+ TimeZone tz = arc.getLocaleContext().getTimeZone();
+ int tzOffsetMinutes = tz.getOffset(currTime)/(1000*60);
+
StringBuilder clickRef = new StringBuilder(30);
writer.writeURIAttribute("href", "#", null);
@@ -502,6 +529,8 @@
}
clickRef.append(currTime);
+ if (tzOffsetMinutes != baseTZOffsetMinutes)
+ clickRef.append (", " + tzOffsetMinutes);
clickRef.append(')');
writer.writeAttribute("onclick", clickRef, null);
}
@@ -817,7 +846,7 @@
currentTime.set(Calendar.MONTH, currMonth);
- String value = String.valueOf(currentTime.getTime().getTime() - offset);
+ String value = String.valueOf(currentTime.getTimeInMillis() - offset);
writer.writeAttribute("value", value, null );
writer.writeText(months[currMonth], null);
@@ -982,7 +1011,7 @@
currentTime.set(Calendar.YEAR, year);
writer.writeAttribute("value",
- String.valueOf(currentTime.getTime().getTime()),
+ String.valueOf(currentTime.getTimeInMillis()),
null);
// output the label for the after item
Modified: myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/DateField.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/DateField.js?rev=738384&r1=738383&r2=738384&view=diff
==============================================================================
--- myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/DateField.js (original)
+++ myfaces/trinidad/trunk/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/DateField.js Wed Jan 28 07:23:01 2009
@@ -20,24 +20,45 @@
// _dfsv(): Date Field Set Value function.
function _dfsv(
dateField,
- newValue
+ newValue,
+ serverOffsetInMins
)
{
// Make sure we have valid values
if ((dateField == (void 0)) || (newValue == (void 0)))
return;
+
+ // Hold on to the initial date value
+ var baseDate = new Date(newValue);
+
+ // We need to compare the time zone that is on the client with the time
+ // zone that came from the localeContext on the server and adjust if
+ // necessary
+ var tzd = _getLocaleTimeZoneDifference2(baseDate, serverOffsetInMins);
+
+ // _getTimePortion below expects that newValue is time zero (midnight) on the given
+ // day. The code changes to handle the new Daylight Savings Time dates (as of
+ // 2007, DST was extended by a couple of weeks) broke the calculations for
+ // 2006 and prior on Windows. This yields an off-by-one-hour problem on the
+ // day after the DST switch. Here we adjust for that.
+ newValue = _dfGetMidnight(newValue + tzd);
// Add back in the time
// offset,since we don't want to overwrite the user's time when
// they pick a new date from the calendar.
newValue += _getTimePortion(dateField);
-
- // compare the time zone that is on the client with the time zone that
- // came from the localeContext on the server and adjust if necessary.
- // bug 3167883
- newValue += _getLocaleTimeZoneDifference2();
var newDate = new Date(newValue);
+
+ // If the date used for the time-of-day calculation is different from the
+ // timezone (daylight savings or standard time) of the base date, then we'll
+ // be off by an hour. Here we adjust for that hour. Note this is different
+ // from the check in the _getTimePortion method, that only checks for a
+ // timezone change on the particular day used for the calculation. Both
+ // checks are needed.
+ var tzDiffOffset = _getTimezoneDiff(baseDate, newDate);
+ if (tzDiffOffset != 0)
+ newDate = new Date (newValue - tzDiffOffset);
//
// get the format to use to format the result
@@ -139,7 +160,11 @@
dateField = _savedField1879034;
}
- _dfsv(dateField, newValue);
+ var serverOffset = closingWindow.serverOffsetInMins;
+ if (serverOffset != (void 0))
+ _dfsv(dateField, newValue, serverOffset);
+ else
+ _dfsv(dateField, newValue);
}
}
@@ -227,8 +252,10 @@
}
// add the current time in Millis since 1970
- destination += "&value=" + oldValue.getTime();
+ var timeval = oldValue.getTime() - _getLocaleTimeZoneDifference(oldValue);
+ destination += "&value=" + timeval
+
// add the locale
destination += "&loc=" + _locale;
@@ -329,8 +356,14 @@
oldValue.getDate());
// get only the time portion of the date in the field.
+ var diff = oldValue-oldValueDateOnly;
+
+ // If the timezone changed today, subtract out the offset.
+ // This will only happen on the day that we switch from standard time to
+ // daylight savings time, or back again.
+ diff -= _getTimezoneDiff(oldValue, oldValueDateOnly);
- return oldValue-oldValueDateOnly;
+ return diff;
}
/**
@@ -340,22 +373,60 @@
* the date field to use the timezone set on the locale context on the
* server instead of the timezone we get from javascript's getTimezoneOffset.
* see bug 3167883
+ * TRINIDAD-1349:_uixLocaleTZ stores the timezone offset of the server at
+ * the time the page was displayed (Current time), and currentDateTZOffset
+ * is the timezone offset of client at the current time as well. However,
+ * the timezone offsets for both client and server can differ for the
+ * date that was picked due to daylight savings rules. For example, the
+ * current time is 3 Dec 2008 and the server is in PST (UTC -8) and
+ * client is in Perth (AWDT, UTC + 9) so the difference is 17h. But if
+ * the user picks Apr 25, the server is actually in PDT then (UTC-7) and
+ * the client in AWST (UTC +8) so the difference is actually 15h. The original
+ * code would subtract 17h, which would cause the resulting date to move
+ * to the previous day. *
*/
-function _getLocaleTimeZoneDifference2()
+function _getLocaleTimeZoneDifference2(clientDate, serverOffset)
{
- var currentDate = new Date();
// timeZoneOffset in javascript appears to give
// the wrong sign, so I am switching it.
// the timeZoneOffset is in minutes.
- var currentDateTzOffset = currentDate.getTimezoneOffset() * -1;
+ var clientOffset = clientDate.getTimezoneOffset() * -1;
var tzOffsetDiff = 0;
- if (_uixLocaleTZ)
- tzOffsetDiff = (_uixLocaleTZ - currentDateTzOffset)*60*1000;
+ if (serverOffset != void(0))
+ tzOffsetDiff = (serverOffset - clientOffset)*60*1000;
+ else if (_uixLocaleTZ != (void(0)))
+ tzOffsetDiff = (_uixLocaleTZ - clientOffset)*60*1000;
return tzOffsetDiff;
}
/**
+ * Just find the difference in millis between the timezone of two dates
+ */
+function _getTimezoneDiff(oldDate, newDate)
+{
+ return (oldDate.getTimezoneOffset() - newDate.getTimezoneOffset()) * 60000;
+}
+
+/**
+ * _dfGetMidnight: Date Field Get Midnight
+ * Returns the date val for midnight on the date given by the
+ * input dateVal.
+ */
+function _dfGetMidnight(dateVal)
+{
+ var baseDate = new Date(dateVal);
+ // Just zero out the date
+ baseDate.setHours(0);
+ baseDate.setMinutes(0);
+ baseDate.setSeconds(0);
+ baseDate.setMilliseconds(0);
+
+ // and return the corresponding date value
+ return baseDate.getTime();
+}
+
+/**
* _dbb(): Date Field Blur handler
*
* Parameters:
@@ -420,7 +491,7 @@
* - source is the id of the calendar
* - value is the date value to select
*/
-function _calsd(source, value)
+function _calsd(source, value, serverOffsetInMins)
{
if (window._calActiveDateFields != (void 0))
@@ -428,7 +499,7 @@
var dateField = window._calActiveDateFields[source];
if (dateField)
- _dfsv(dateField, value);
+ _dfsv(dateField, value, serverOffsetInMins);
}
return false;
@@ -462,18 +533,20 @@
return false;
}
-function _selectDate(dateTime)
+function _selectDate(dateTime, serverOffsetInMins)
{
var dialog = parent.TrPopupDialog.getInstance();
if (dialog)
{
dialog.returnValue = dateTime;
+ dialog.serverOffsetInMins = serverOffsetInMins;
//TODO - Need Cleaner way to close dialogs using via getInstance()
parent.TrPopupDialog._returnFromDialog();
}
else
{
top.returnValue = dateTime;
+ top.serverOffsetInMins = serverOffsetInMins;
top._unloadADFDialog(window.event);
top.close();
}