FLEX: обработка смещения часового пояса - PullRequest
0 голосов
/ 28 июня 2011

Я разработал приложение FLEX для распределенного администрирования данных.Когда наши сотрудники из Азии указывают дату, она будет сохранена в +1 день.

Если я проверю смещение часового пояса, оно равно +60, их смещение + 520.

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

Я предполагаюэто проблема?Если да, предложите ли я исправить введенную дату за 460 минут до ее отправки на наш сервер для сохранения?Как это сделать?

Ответы [ 3 ]

6 голосов
/ 28 июня 2011

Когда вы создаете объект Date в ActionScript, он будет внутренне сохранять свое значение в числовом значении UTC, не зависящем от времени, однако это значение будет рассчитываться с применением поправки из-за локального смещения часового пояса / летнего времени клиента. Flash получает текущий часовой пояс базовой операционной системой, и в настоящее время нет способа установить пользовательский часовой пояс.

Таким образом, если вы не находитесь в ситуации UTC + 0, фактическое значение даты будет содержать смещение определенного количества часов / минут.

При повторном отображении той же даты форматы форматирования по умолчанию и стандартные элементы управления Flex преобразуют дату обратно в местный часовой пояс: когда две операции выполняются на одном и том же компьютере (или на машинах с одинаковым смещением часового пояса), эти исправления будут компенсировать друг друга, и вы вообще не заметите такого поведения.

Однако сохранение этого значения (например, отправка его в BlazeDS / LCDS для сохранения его в БД) и извлечение его из клиента с другим часовым поясом может привести к неожиданному эффекту, если вы не готовы обрабатывать их: для Например, если разница между поправками часового пояса двух клиентов отрицательна (например, -1 час), день, введенный как 28/06/2011, может отображаться как 27/06/2011 в компоненте DateField.

Это сложная проблема, и нет быстрого и простого решения: оно зависит от типа поддержки часового пояса, который вы хотите предоставить.

Самое простое решение - настроить всех клиентов на работу с общим часовым поясом, например часовым поясом сервера. К сожалению, текущая версия Flash Player не позволяет указывать явный часовой пояс, и для реализации этой стратегии необходимо вручную установить внутренние значения UTC для любой даты, созданной компонентами Flex, перед отправкой на сервер, чтобы компенсировать местное смещение часового пояса. Другой распространенный обходной путь - избегать использования объектов Date и использования строкового представления ISO для дат.

Вы можете найти много информации (и некоторые идеи об управлении часовым поясом) в Adobe Bug Tracker, см. Проблему https://bugs.adobe.com/jira/browse/FP-175 с заголовком «Установить конкретный часовой пояс на flashplayer. Это позволит приложениям сохранять то же самое часовой пояс для всех клиентов в разных часовых поясах. "

1 голос
/ 13 ноября 2014

решение Blaze DS / Adobe LiveCycle DS на основе https://forums.adobe.com/thread/1076594:

services-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.Ява

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;
}
1 голос
/ 30 июня 2011

Наконец-то я реализовал это решение:

получить данные с сервера в виде строки 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 (...)

Не стесняйтесь спрашивать дополнительную информацию!

...