/*
* � Copyright IBM Corp. 2010, 2014
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.ibm.xsp.extlib.component.dojo.converter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import com.ibm.commons.util.StringUtil;
import com.ibm.commons.xml.XMLException;
import com.ibm.commons.xml.util.XMIConverter;
import com.ibm.xsp.FacesExceptionEx;
import com.ibm.xsp.application.ApplicationEx;
import com.ibm.xsp.extlib.component.dojo.form.UIDojoDateTextBox;
import com.ibm.xsp.extlib.component.dojo.form.UIDojoTimeTextBox;
/**
* Dojo Date Converter.
*
* @author priand
*/
public class DateTimeConverter extends AbstractDojoConverter {
protected static final int TYPE_DATE = 0;
protected static final int TYPE_TIME = 1;
protected static final int TYPE_TIMESTAMP = 2;
protected int getDateTimeType(UIComponent component) {
if(component instanceof UIDojoDateTextBox) {
return TYPE_DATE;
}
if(component instanceof UIDojoTimeTextBox) {
return TYPE_TIME;
}
return TYPE_TIMESTAMP;
}
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if(StringUtil.isNotEmpty(value)) {
TimeZone tz = getDefaultTimeZone();
// If the date is sent as time, then assume today's date in the browser TZ
// So we'll have the proper conversion done. If we don't do that, then java
// uses 1/1/70 and it has an issue when rendering it back in summer, as it leads to
// one hour difference. This is also in sync with what the Notes backend API does
if(value.startsWith("T")) {
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
fmt.setTimeZone(tz);
value = fmt.format(new Date())+value;
}
// assume this is a string in ISO format
// In this case, dojo returns the right date but with a timezone specification computed
// using the browser information. Unfortunately, it doesn't support the daylight savings
// So that lead to a wrong time zone (http://trac.dojotoolkit.org/ticket/588)
// A solution is to ignore the timezone provided by dojo.
// But the date should be converted to the user TimeZone
try {
long dt = XMIConverter.readXMIDateStrict((String)value,false,true);
long offset = 0;
TimeZone clientTimeZone = tz;
TimeZone serverTimeZone = TimeZone.getDefault();
if( !serverTimeZone.equals(clientTimeZone) ){
// SPR#MKEE9HYHQ7 cannot use timeZone.getRawOffset()
// because client timezone is-summerTime-ness and the
// server timezone is-summerTime-ness may be different,
// so using the raw offset leads to problems during the
// period where one timezone has changed to summer time
// but the other timezone has not.
Date serverNow = new Date();
Date clientNow = java.util.Calendar.getInstance(clientTimeZone).getTime();
offset = serverTimeZone.getOffset(serverNow.getTime()) - clientTimeZone.getOffset(clientNow.getTime());
}
dt += offset;
return new Date(dt);
} catch(XMLException e) {
String msg = StringUtil.format("Error while converting date/time {0}",value); // $NLX-DateTimeConverter.Errorwhileconvertingdatetime0-1$
throw new FacesExceptionEx(msg,e);
}
}
return null;
}
public String getAsString(FacesContext context, UIComponent component, Object value) {
if(value instanceof Date) {
Date dateValue = (Date)value;
int type = getDateTimeType(component);
// Adjust the date to the desired timezone
// Dojo expect the the date already formatted within the desired time zone
// As the SimpleFormat uses the default timezone, we offset the difference so it is
// correctly formatted for dojo.
long offset = 0;
TimeZone clientTimeZone = getDefaultTimeZone();
TimeZone serverTimeZone = TimeZone.getDefault();
if( !serverTimeZone.equals(clientTimeZone) ){
// SPR#MKEE9HYHQ7 cannot use timeZone.getRawOffset()
// because client timezone is-summerTime-ness and the
// server timezone is-summerTime-ness may be different,
// so using the raw offset leads to problems during the
// period where one timezone has changed to summer time
// but the other timezone has not.
Date serverNow = new Date();
Date clientNow = java.util.Calendar.getInstance(clientTimeZone).getTime();
offset = serverTimeZone.getOffset(serverNow.getTime()) - clientTimeZone.getOffset(clientNow.getTime());
}
dateValue = new Date(dateValue.getTime()-offset);
if( type==TYPE_DATE ) {
return formatDateAsISODate(dateValue);
} else if( type==TYPE_TIME ) {
return formatTimeAsISOTime(dateValue);
} else {
return formatDateAsISODateTime(dateValue);
}
}
return "";
}
private static final TimeZone s_defaultTimeZone = TimeZone.getDefault();
private TimeZone getDefaultTimeZone() {
FacesContext context = FacesContext.getCurrentInstance();
if (context != null) {
try {
ApplicationEx application = (ApplicationEx)context.getApplication();
return application.getUserTimeZone(context);
}
catch (NullPointerException npe) {
}
}
return s_defaultTimeZone;
}
// Formatting utilities
private static String formatDateAsISODate(Date date) {
// DateFormat are not reentrant - must be created on demand
SimpleDateFormat dojoDate = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
return dojoDate.format(date);
}
private static String formatTimeAsISOTime(Date time) {
// DateFormat are not reentrant - must be created on demand
SimpleDateFormat dojoTime = new SimpleDateFormat("'T'HH:mm:ss"); //$NON-NLS-1$
return dojoTime.format(time);
}
private static String formatDateAsISODateTime(Date dateTime) {
// DateFormat are not reentrant - must be created on demand
SimpleDateFormat dojoTimestamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); //$NON-NLS-1$
return dojoTimestamp.format(dateTime);
}
}