2011-06-28 110 views
0

我開發了一個用於分佈式數據管理的FLEX應用程序。當我們的亞洲員工指定日期時,它將被保存+1天。FLEX:處理時區偏移

如果我檢查我的時區偏移量是+60,它們的偏移量是+520。

var dNow:Date = new Date(); 
    trace("Your time zone offset: " + dNow.getTimezoneOffset() + " minutes"); 

我認爲這是問題所在?如果是這樣,你會建議我將輸入的日期改正460分鐘,然後再發送給我們的服務器進行保存嗎?怎麼做?

回答

1

最後我實現這個解決方案:

得到從服務器ISO字符串(使用ColdFusion的MS SQL Server)的數據它轉換的的ValueObject(以下Cairngorm的框架):

  if (obj.CONTRACTED_DELIVERY != null){ 
      this.CONTRACTED_DELIVERY = DateField.stringToDate(obj.CONTRACTED_DELIVERY,"DD.MM.YYYY"); 
     }else{ 
      this.CONTRACTED_DELIVERY = obj.CONTRACTED_DELIVERY; 
     } 

發送作爲ISO字符串服務器的日期:

UPDATE (...) 
SET CONTRACTED_DELIVERY = <cfif productionDetails.CONTRACTED_DELIVERY EQ ''>null<cfelse>'#dateFormat(productionDetails.CONTRACTED_DELIVERY,"YYYY-MM-DD")#'</cfif> 
WHERE (...) 

隨時索取更多信息!

5

當您在ActionScript中創建Date對象時,它將在內部將其值存儲爲無時間差的UTC數值,但是會根據客戶端的本地時區/日光節省偏移量應用更正來計算此值。 Flash通過底層操作系統獲取當前時區,目前無法設置自定義時區。

因此,除非您完全處於UTC + 0情況,否則日期的實際值將包含特定小時數/分鐘數的偏移量。

當再次顯示相同日期時,默認格式化程序和標準Flex控件會將日期轉換回本地時區:當兩個操作在同一臺計算機上(或具有相同時區偏移量的計算機上)執行時,這些更正將互相補償,你根本不會注意到這種行爲。

但是,如果您不準備處理它們,則將該值存儲(例如,將其發送到BlazeDS/LCDS以將其保存在數據庫中)並從具有不同時區的客戶端中檢索該值可能會產生意想不到的效果:例如,如果兩個客戶端的時區更正之間的差異爲負數(例如-1小時),則2011年6月28日輸入的日期可以在DateField組件中顯示爲27/06/2011。

這是一個複雜的問題,並沒有快速簡單的解決方案:它依賴於您想提供的時區支持類型。

最簡單的解決方案是將所有客戶端設置爲使用公共時區,例如服務器的時區。不幸的是,當前版本的Flash Player不允許指定明確的時區,並且要實現此策略,您需要在將Flex組件創建的任何Date的內部UTC值發送到服務器之前手動設置,以補償本地時區偏移。另一個常用的解決方法是避免使用Date對象並使用ISO字符串表示日期。

你可以找到在Adobe Bug跟蹤大量的信息(以及有關時區管理的一些想法),看到https://bugs.adobe.com/jira/browse/FP-175問題,標題爲「坐落於FlashPlayer的具體時區,這將使得應用能夠保持同一時區的所有客戶端在不同的時區。接收我當

SELECT CONVERT(varchar, CONTRACTED_DELIVERY, 104) AS CONTRACTED_DELIVERY 
FROM (...) 
WHERe (...) 

然後:「

+0

非常好的答案,但是你似乎聽起來很難設定正確的日期。很多時候,我讓服務器保存/發送一個通用的日期字符串(包括日期,時間和偏移量)並讓'DateFormatter.parseString'在我的命令類中完成這項工作。 –

+0

是的,根據你正在構建的應用程序的類型,使用字符串而不是Date對象進行服務器通信可能是一個可行的解決方案(我在答案中提到了它,但沒有詳細說明)。 但是,根據我的經驗,如果您有自定義複雜對象(結構化DTO/VO)並且日期字段可以嵌套在這些結構中,並且涉及客戶端日期計算時,事情會變得棘手。 我只是想警告,獨立於選擇的解決方案,對問題的良好理解對於避免不好的意外很重要。 –

1

基於https://forums.adobe.com/thread/1076594大火DS /使用Adobe的LiveCycle DS解決方案:

服務-config.xml中

<service id="myProxyBootstrapService" class="org.myapp.flex.proxy.MyProxyBootstrapService"/> 

MyProxyBootstrapService.java

MyProxyBootstrapService extends AbstractBootstrapService { 

@Override 
public void initialize(String arg0, ConfigMap arg1) { 
    PropertyProxyRegistry registry = PropertyProxyRegistry.getRegistry(); 
    registry.register(Serializable.class, new DateProxy()); 
} 

DateProxy.java

public class DateProxy extends BeanProxy { 

private static final long serialVersionUID = 8097540028987261941L; 

private Integer serverOffset; 

public DateProxy() { 
    super(); 
} 

@Override 
public Object getValue(Object instance, String propertyName) { 
    Object result = super.getValue(instance, propertyName); 
    if (result instanceof Date) { 
     result = toDate(result, true); 
    } 
    return result; 
} 

@Override 
public void setValue(Object object, String propertyName, Object value) { 
    if (value instanceof Date) { 
     Date date = toDate(value, false); 
     super.setValue(object, propertyName, date); 
    } else { 
     super.setValue(object, propertyName, value); 
    } 
} 

private Date toDate(Object value, Boolean serverToClient) { 
    Date date = (Date) value; 
    Integer clientOffset = getClientOffset(); 
    Integer serverOffset = getServerOffset(); 
    if (clientOffset != null && !clientOffset.equals(serverOffset)) { 
     Calendar cal = new GregorianCalendar(TimeZone.getDefault()); 
     cal.setTime(date); 
     cal.add(Calendar.MINUTE, serverToClient ? clientOffset - serverOffset : serverOffset - clientOffset); 
     date.setTime(cal.getTimeInMillis()); 
    } 
    return date; 
} 

private Integer getClientOffset() { 
    return (Integer) FlexContext.getFlexSession().getAttribute("TIMEZONE_FLEX_OFFSET"); 
} 

private Integer getServerOffset() { 
    if (serverOffset == null) { 
     serverOffset = Calendar.getInstance().getTimeZone().getOffset(new Date().getTime())/1000/60 * -1; 
    } 
    return serverOffset; 
}