2014年10月14日 星期二

iceface jsf 日期 少一天問題

因為他是個BUG嗎?....

總之因為當初他在 convertDateTime 的實作裡,把時區寫死成GMT還UTC忘了(總之就是格林威治時間)...
所以造成了很多很多很多很多的困擾...

話說找這問題的關鍵字還蠻難猜的~ 後來總算找到是..."jsf convertdatetime one day less"

解法是蠻多種的~但是....卡版本就要哭哭了...

看起來是JSF 2.0以上的版本可以用設定檔改成主機時區
<context-param>
    <param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
    <param-value>true</param-value>
</context-param>
 
或是基本的...直接寫死時區(timeZone大小寫要對喔,寫錯還不會出來=_=|||)~
但是看偶幾十頁要全重改一次就是很不爽一x一...
<f:convertDateTime pattern="yyyy/MM/dd" timeZone="GMT+8" /> 

然後用這個的除了文字顯示外,還有小日曆要一起修的問題~
所以就很不爽(假裝很厲害)的去寫了一個converter出來...
此法也只適用於jsf 1.6以上的樣子,看討論是因為
<f:converter converterId="XXXXXXXX" />
這種寫法, 1.6後才支援...
 
重點大概是~一定要繼承 DateTimeConverter,小日曆裡才吃得進去!!
改掉萬惡的時區。
getAsObject裡,一定要回傳java.util.Date,不然小日曆就擺臭臉給你看....

然後既然都自己刻了,就也順便修一下原本沒事就亂丟NullPointerException的問題...

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.DateTimeConverter;

public class DateInputConverter extends DateTimeConverter implements Converter {
 
 SimpleDateFormat sf = new SimpleDateFormat("yyyy/MM/dd");

 public Object getAsObject(FacesContext context, UIComponent component, String value) {
  java.util.Date re = null;
  try  {
   if(value != null && value.length() > 0)  {
    re = sf.parse(value);
   }
  }  catch(Exception e)  {
   
  }
  return re;
 }

 public String getAsString(FacesContext context, UIComponent component, Object value) {
  String re = "";
  try {
   if (value != null) {
    // format Timestamp
    if (value instanceof Timestamp || value instanceof java.util.Date) {     
     re = sf.format(value);
    }
   }
  }
  catch (Exception e) {
   e.printStackTrace();
  }
  return re;
 }
 
 public TimeZone getTimeZone()  {
  return TimeZone.getDefault();
 }
}

face設定檔裡面也要加自定的converter
<converter>
    <description>小日曆輸入 yyyy/MM/dd</description>
    <converter-id>formatDateInput</converter-id>
    <converter-class>XXXXXXX.DateInputConverter</converter-class>
</converter> 

前端page
<ice:selectInputDate id="birthday" renderMonthAsDropdown="true" 
    renderYearAsDropdown="true" renderWeekNumbers="true"
    value="#{bean.birthday}" title=""                             
    renderAsPopup="true">
        <f:converter converterId="formatDateInput" />
</ice:selectInputDate>  


沒有留言: