我开发了一个用于分布式数据管理的FLEX应用程序。当我们的亚洲员工指定日期时,它将被保存+1天。
如果我检查我的时区偏移是+60,它们的偏移是+520。
var dNow:Date = new Date();
trace("Your time zone offset: " + dNow.getTimezoneOffset() + " minutes");
我认为这是问题所在?如果是这样,您是否建议我将输入的日期更正460分钟后再将其发送到我们的服务器进行保存?怎么做?
答案 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 / 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;
}