FLEX:处理时区偏移

时间:2011-06-28 08:50:44

标签: flex timezone offset

我开发了一个用于分布式数据管理的FLEX应用程序。当我们的亚洲员工指定日期时,它将被保存+1天。

如果我检查我的时区偏移是+60,它们的偏移是+520。

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

我认为这是问题所在?如果是这样,您是否建议我将输入的日期更正460分钟后再将其发送到我们的服务器进行保存?怎么做?

3 个答案:

答案 0 :(得分:6)

在ActionScript中创建Date对象时,它将在内部将其值存储在不含timezione的UTC数值中,但是,由于客户端的本地时区/夏令时偏移量,将根据更正计算此值。 Flash通过底层操作系统获取当前时区,目前无法设置自定义时区。

因此,除非您完全处于UTC + 0状态,否则Date的实际值将包含一定数量小时/分钟的偏移量。

当再次显示相同的日期时,默认格式化程序和标准Flex控件会将Date转换回本地时区:当两台操作在同一台机器上执行时(或在具有相同时区偏移的机器上执行),更正将相互补偿,你根本不会注意到这种行为。

但是,存储该值(例如,将其发送到BlazeDS / LCDS以将其保存在数据库中)并从具有不同时区的客户端检索它会产生意想不到的效果,如果您不准备处理它们:例如,如果两个客户端的时区更正之间的差异为负(例如,-1小时),则输入为28/06/2011的一天可以在DateField组件中显示为27/06/2011。

这是一个复杂的问题,并没有快速简便的解决方案:它取决于您想要提供的时区支持类型。

最简单的解决方案是将所有客户端设置为使用公共时区,例如服务器的时区。遗憾的是,当前版本的Flash Player不允许指定显式时区,要实现此策略,您需要在将Flex组件发送到服务器之前手动设置任何由Date组件创建的Date的内部UTC值,以补偿当地时区偏移。另一个常见的解决方法是避免使用Date对象并使用ISO字符串表示日期。

您可以在Adobe Bug Tracker中找到大量信息(以及有关时区管理的一些想法),请参阅https://bugs.adobe.com/jira/browse/FP-175问题,标题为“在Flashplayer上设置特定时区。这将使应用程序保持相同的时区在不同时区的所有客户。“

答案 1 :(得分:1)

最后我实施了这个解决方案:

从服务器获取数据作为ISO字符串(使用coldfusion到MS SQL Server):

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

然后在接收它时我将它转换为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 (...)

随时询问更多信息!

答案 2 :(得分:1)

基于https://forums.adobe.com/thread/1076594的Blaze DS / Adob​​e 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;
}